Commit 39914c9b authored by knielsen@ymer.(none)'s avatar knielsen@ymer.(none)

Merge ymer.(none):/usr/local/mysql/mysql-5.1-telco-gca

into  ymer.(none):/usr/local/mysql/mysql-5.1-new-ndb
parents f1898c05 0027a93d
......@@ -369,14 +369,16 @@ public:
void executeAsynch(ExecType aTypeOfExec,
NdbAsynchCallback aCallback,
void* anyObject,
NdbOperation::AbortOption = NdbOperation::DefaultAbortOption);
NdbOperation::AbortOption = NdbOperation::DefaultAbortOption,
int forceSend= 0);
#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
void executeAsynch(::ExecType aTypeOfExec,
NdbAsynchCallback aCallback,
void* anyObject,
::AbortOption abortOption= ::DefaultAbortOption)
::AbortOption abortOption= ::DefaultAbortOption,
int forceSend= 0)
{ executeAsynch((ExecType)aTypeOfExec, aCallback, anyObject,
(NdbOperation::AbortOption)abortOption); }
(NdbOperation::AbortOption)abortOption, forceSend); }
#endif
#endif
/**
......
......@@ -1320,7 +1320,7 @@ Dbacc::startNext(Signal* signal, OperationrecPtr lastOp)
* We must check if there are many transactions in parallel queue...
*/
OperationrecPtr tmp;
tmp.i = loPtr.p->nextParallelQue;
tmp= loPtr;
while (tmp.i != RNIL)
{
ptrCheckGuard(tmp, coprecsize, operationrec);
......@@ -1332,6 +1332,7 @@ Dbacc::startNext(Signal* signal, OperationrecPtr lastOp)
*/
return;
}
tmp.i = tmp.p->nextParallelQue;
}
upgrade:
......
......@@ -676,6 +676,17 @@ NdbTransaction::executeAsynchPrepare(NdbTransaction::ExecType aTypeOfExec,
DBUG_VOID_RETURN;
}//NdbTransaction::executeAsynchPrepare()
void
NdbTransaction::executeAsynch(ExecType aTypeOfExec,
NdbAsynchCallback aCallback,
void* anyObject,
AbortOption abortOption,
int forceSend)
{
executeAsynchPrepare(aTypeOfExec, aCallback, anyObject, abortOption);
theNdb->sendPreparedTransactions(forceSend);
}
void NdbTransaction::close()
{
theNdb->closeTransaction(this);
......
......@@ -27,7 +27,8 @@ public:
const NdbDictionary::Index* idx = 0);
~HugoOperations();
int startTransaction(Ndb*);
int startTransaction(Ndb*, const NdbDictionary::Table *table= 0,
const char *keyData= 0, Uint32 keyLen= 0);
int setTransaction(NdbTransaction*,bool not_null_ok= false);
int closeTransaction(Ndb*);
NdbTransaction* getTransaction();
......
......@@ -1374,6 +1374,73 @@ runBug27756(NDBT_Context* ctx, NDBT_Step* step)
return NDBT_OK;
}
runBug28073(NDBT_Context *ctx, NDBT_Step* step)
{
int result = NDBT_OK;
const NdbDictionary::Table *table= ctx->getTab();
HugoOperations hugoOp1(*table);
HugoOperations hugoOp2(*table);
Ndb* pNdb = GETNDB(step);
int loops = ctx->getNumLoops();
bool inserted= false;
while (loops--)
{
if (!inserted)
{
CHECK(hugoOp1.startTransaction(pNdb) == 0);
CHECK(hugoOp1.pkInsertRecord(pNdb, 1, 1) == 0);
CHECK(hugoOp1.execute_Commit(pNdb) == 0);
CHECK(hugoOp1.closeTransaction(pNdb) == 0);
inserted= 1;
}
// Use TC hint to hit the same node in both transactions.
Uint32 key_val= 0;
const char *key= (const char *)(&key_val);
CHECK(hugoOp1.startTransaction(pNdb, table, key, 4) == 0);
CHECK(hugoOp2.startTransaction(pNdb, table, key, 4) == 0);
// First take 2*read lock on the tuple in transaction 1.
for (Uint32 i= 0; i < 2; i++)
{
CHECK(hugoOp1.pkReadRecord(pNdb, 1, 1, NdbOperation::LM_Read) == 0);
CHECK(hugoOp1.pkReadRecord(pNdb, 1, 1, NdbOperation::LM_Read) == 0);
}
CHECK(hugoOp1.execute_NoCommit(pNdb) == 0);
// Now send ops in two transactions, one batch.
// First 2*read in transaction 2.
for (Uint32 i= 0; i < 2; i++)
{
CHECK(hugoOp2.pkReadRecord(pNdb, 1, 1, NdbOperation::LM_Read) == 0);
CHECK(hugoOp2.pkReadRecord(pNdb, 1, 1, NdbOperation::LM_Read) == 0);
}
CHECK(hugoOp2.execute_async_prepare(pNdb, NdbTransaction::NoCommit) == 0);
// Second op an update in transaction 1.
CHECK(hugoOp1.pkUpdateRecord(pNdb, 1, 1) == 0);
CHECK(hugoOp1.execute_async_prepare(pNdb, NdbTransaction::Commit) == 0);
// Transaction 1 will now hang waiting on transaction 2 to commit before it
// can upgrade its read lock to a write lock.
// With the bug, we get a node failure due to watchdog timeout here.
CHECK(hugoOp2.wait_async(pNdb) == 0);
// Now commit transaction 2, we should see transaction 1 finish with the
// update.
CHECK(hugoOp2.execute_async_prepare(pNdb, NdbTransaction::Commit) == 0);
CHECK(hugoOp2.wait_async(pNdb) == 0);
// No error check, as transaction 1 may have terminated already.
hugoOp1.wait_async(pNdb);
CHECK(hugoOp1.closeTransaction(pNdb) == 0);
CHECK(hugoOp2.closeTransaction(pNdb) == 0);
}
return result;
}
template class Vector<Uint64>;
NDBT_TESTSUITE(testBasic);
......@@ -1656,6 +1723,10 @@ TESTCASE("Bug27756",
"Verify what happens when we fill the db" ){
STEP(runBug27756);
}
TESTCASE("Bug28073",
"Infinite loop in lock queue" ){
STEP(runBug28073);
}
NDBT_TESTSUITE_END(testBasic);
#if 0
......
......@@ -1517,6 +1517,75 @@ runTestIgnoreError(NDBT_Context* ctx, NDBT_Step* step)
return NDBT_OK;
}
static void
testExecuteAsynchCallback(int res, NdbTransaction *con, void *data_ptr)
{
int *res_ptr= (int *)data_ptr;
*res_ptr= res;
}
int runTestExecuteAsynch(NDBT_Context* ctx, NDBT_Step* step){
/* Test that NdbTransaction::executeAsynch() works (BUG#27495). */
int result = NDBT_OK;
const NdbDictionary::Table* pTab = ctx->getTab();
Ndb* pNdb = new Ndb(&ctx->m_cluster_connection, "TEST_DB");
if (pNdb == NULL){
ndbout << "pNdb == NULL" << endl;
return NDBT_FAILED;
}
if (pNdb->init(2048)){
ERR(pNdb->getNdbError());
delete pNdb;
return NDBT_FAILED;
}
NdbConnection* pCon = pNdb->startTransaction();
if (pCon == NULL){
ERR(pNdb->getNdbError());
delete pNdb;
return NDBT_FAILED;
}
NdbScanOperation* pOp = pCon->getNdbScanOperation(pTab->getName());
if (pOp == NULL){
ERR(pOp->getNdbError());
pNdb->closeTransaction(pCon);
delete pNdb;
return NDBT_FAILED;
}
if (pOp->readTuples() != 0){
ERR(pOp->getNdbError());
pNdb->closeTransaction(pCon);
delete pNdb;
return NDBT_FAILED;
}
if (pOp->getValue(NdbDictionary::Column::FRAGMENT) == 0){
ERR(pOp->getNdbError());
pNdb->closeTransaction(pCon);
delete pNdb;
return NDBT_FAILED;
}
int res= 42;
pCon->executeAsynch(NoCommit, testExecuteAsynchCallback, &res);
while(pNdb->pollNdb(100000) == 0)
;
if (res != 0){
ERR(pCon->getNdbError());
ndbout << "Error returned from execute: " << res << endl;
result= NDBT_FAILED;
}
pNdb->closeTransaction(pCon);
delete pNdb;
return result;
}
template class Vector<NdbScanOperation*>;
......@@ -1616,6 +1685,10 @@ TESTCASE("IgnoreError", ""){
FINALIZER(runClearTable);
FINALIZER(createPkIndex_Drop);
}
TESTCASE("ExecuteAsynch",
"Check that executeAsync() works (BUG#27495)\n"){
INITIALIZER(runTestExecuteAsynch);
}
NDBT_TESTSUITE_END(testNdbApi);
int main(int argc, const char** argv){
......
......@@ -243,6 +243,10 @@ max-time: 1000
cmd: testBasic
args: -n Bug27756
max-time: 500
cmd: testBasic
args: -n Bug28073
max-time: 500
cmd: testIndex
args: -n Bug25059 -r 3000 T1
......@@ -688,6 +692,10 @@ max-time: 500
cmd: testNdbApi
args: -n Bug_WritePartialIgnoreError T1
max-time: 500
cmd: testNdbApi
args: -n ExecuteAsynch T1
#max-time: 500
#cmd: testInterpreter
#args: T1
......
......@@ -15,13 +15,15 @@
#include <HugoOperations.hpp>
int HugoOperations::startTransaction(Ndb* pNdb){
int HugoOperations::startTransaction(Ndb* pNdb,
const NdbDictionary::Table *table,
const char *keyData, Uint32 keyLen){
if (pTrans != NULL){
ndbout << "HugoOperations::startTransaction, pTrans != NULL" << endl;
return NDBT_FAILED;
}
pTrans = pNdb->startTransaction();
pTrans = pNdb->startTransaction(table, keyData, keyLen);
if (pTrans == NULL) {
const NdbError err = pNdb->getNdbError();
ERR(err);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment