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: ...@@ -369,14 +369,16 @@ public:
void executeAsynch(ExecType aTypeOfExec, void executeAsynch(ExecType aTypeOfExec,
NdbAsynchCallback aCallback, NdbAsynchCallback aCallback,
void* anyObject, void* anyObject,
NdbOperation::AbortOption = NdbOperation::DefaultAbortOption); NdbOperation::AbortOption = NdbOperation::DefaultAbortOption,
int forceSend= 0);
#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED #ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
void executeAsynch(::ExecType aTypeOfExec, void executeAsynch(::ExecType aTypeOfExec,
NdbAsynchCallback aCallback, NdbAsynchCallback aCallback,
void* anyObject, void* anyObject,
::AbortOption abortOption= ::DefaultAbortOption) ::AbortOption abortOption= ::DefaultAbortOption,
int forceSend= 0)
{ executeAsynch((ExecType)aTypeOfExec, aCallback, anyObject, { executeAsynch((ExecType)aTypeOfExec, aCallback, anyObject,
(NdbOperation::AbortOption)abortOption); } (NdbOperation::AbortOption)abortOption, forceSend); }
#endif #endif
#endif #endif
/** /**
......
...@@ -1320,7 +1320,7 @@ Dbacc::startNext(Signal* signal, OperationrecPtr lastOp) ...@@ -1320,7 +1320,7 @@ Dbacc::startNext(Signal* signal, OperationrecPtr lastOp)
* We must check if there are many transactions in parallel queue... * We must check if there are many transactions in parallel queue...
*/ */
OperationrecPtr tmp; OperationrecPtr tmp;
tmp.i = loPtr.p->nextParallelQue; tmp= loPtr;
while (tmp.i != RNIL) while (tmp.i != RNIL)
{ {
ptrCheckGuard(tmp, coprecsize, operationrec); ptrCheckGuard(tmp, coprecsize, operationrec);
...@@ -1332,6 +1332,7 @@ Dbacc::startNext(Signal* signal, OperationrecPtr lastOp) ...@@ -1332,6 +1332,7 @@ Dbacc::startNext(Signal* signal, OperationrecPtr lastOp)
*/ */
return; return;
} }
tmp.i = tmp.p->nextParallelQue;
} }
upgrade: upgrade:
......
...@@ -676,6 +676,17 @@ NdbTransaction::executeAsynchPrepare(NdbTransaction::ExecType aTypeOfExec, ...@@ -676,6 +676,17 @@ NdbTransaction::executeAsynchPrepare(NdbTransaction::ExecType aTypeOfExec,
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
}//NdbTransaction::executeAsynchPrepare() }//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() void NdbTransaction::close()
{ {
theNdb->closeTransaction(this); theNdb->closeTransaction(this);
......
...@@ -27,7 +27,8 @@ public: ...@@ -27,7 +27,8 @@ public:
const NdbDictionary::Index* idx = 0); const NdbDictionary::Index* idx = 0);
~HugoOperations(); ~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 setTransaction(NdbTransaction*,bool not_null_ok= false);
int closeTransaction(Ndb*); int closeTransaction(Ndb*);
NdbTransaction* getTransaction(); NdbTransaction* getTransaction();
......
...@@ -1374,6 +1374,73 @@ runBug27756(NDBT_Context* ctx, NDBT_Step* step) ...@@ -1374,6 +1374,73 @@ runBug27756(NDBT_Context* ctx, NDBT_Step* step)
return NDBT_OK; 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>; template class Vector<Uint64>;
NDBT_TESTSUITE(testBasic); NDBT_TESTSUITE(testBasic);
...@@ -1656,6 +1723,10 @@ TESTCASE("Bug27756", ...@@ -1656,6 +1723,10 @@ TESTCASE("Bug27756",
"Verify what happens when we fill the db" ){ "Verify what happens when we fill the db" ){
STEP(runBug27756); STEP(runBug27756);
} }
TESTCASE("Bug28073",
"Infinite loop in lock queue" ){
STEP(runBug28073);
}
NDBT_TESTSUITE_END(testBasic); NDBT_TESTSUITE_END(testBasic);
#if 0 #if 0
......
...@@ -1517,6 +1517,75 @@ runTestIgnoreError(NDBT_Context* ctx, NDBT_Step* step) ...@@ -1517,6 +1517,75 @@ runTestIgnoreError(NDBT_Context* ctx, NDBT_Step* step)
return NDBT_OK; 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*>; template class Vector<NdbScanOperation*>;
...@@ -1616,6 +1685,10 @@ TESTCASE("IgnoreError", ""){ ...@@ -1616,6 +1685,10 @@ TESTCASE("IgnoreError", ""){
FINALIZER(runClearTable); FINALIZER(runClearTable);
FINALIZER(createPkIndex_Drop); FINALIZER(createPkIndex_Drop);
} }
TESTCASE("ExecuteAsynch",
"Check that executeAsync() works (BUG#27495)\n"){
INITIALIZER(runTestExecuteAsynch);
}
NDBT_TESTSUITE_END(testNdbApi); NDBT_TESTSUITE_END(testNdbApi);
int main(int argc, const char** argv){ int main(int argc, const char** argv){
......
...@@ -243,6 +243,10 @@ max-time: 1000 ...@@ -243,6 +243,10 @@ max-time: 1000
cmd: testBasic cmd: testBasic
args: -n Bug27756 args: -n Bug27756
max-time: 500
cmd: testBasic
args: -n Bug28073
max-time: 500 max-time: 500
cmd: testIndex cmd: testIndex
args: -n Bug25059 -r 3000 T1 args: -n Bug25059 -r 3000 T1
...@@ -688,6 +692,10 @@ max-time: 500 ...@@ -688,6 +692,10 @@ max-time: 500
cmd: testNdbApi cmd: testNdbApi
args: -n Bug_WritePartialIgnoreError T1 args: -n Bug_WritePartialIgnoreError T1
max-time: 500
cmd: testNdbApi
args: -n ExecuteAsynch T1
#max-time: 500 #max-time: 500
#cmd: testInterpreter #cmd: testInterpreter
#args: T1 #args: T1
......
...@@ -15,13 +15,15 @@ ...@@ -15,13 +15,15 @@
#include <HugoOperations.hpp> #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){ if (pTrans != NULL){
ndbout << "HugoOperations::startTransaction, pTrans != NULL" << endl; ndbout << "HugoOperations::startTransaction, pTrans != NULL" << endl;
return NDBT_FAILED; return NDBT_FAILED;
} }
pTrans = pNdb->startTransaction(); pTrans = pNdb->startTransaction(table, keyData, keyLen);
if (pTrans == NULL) { if (pTrans == NULL) {
const NdbError err = pNdb->getNdbError(); const NdbError err = pNdb->getNdbError();
ERR(err); 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