summaryrefslogtreecommitdiff
path: root/storage/ndb
diff options
context:
space:
mode:
Diffstat (limited to 'storage/ndb')
-rw-r--r--storage/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp3
-rw-r--r--storage/ndb/test/include/HugoOperations.hpp3
-rw-r--r--storage/ndb/test/ndbapi/testBasic.cpp72
-rw-r--r--storage/ndb/test/run-test/daily-basic-tests.txt4
-rw-r--r--storage/ndb/test/src/HugoOperations.cpp6
5 files changed, 84 insertions, 4 deletions
diff --git a/storage/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp b/storage/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp
index 58032c92d5f..3b27446d3a9 100644
--- a/storage/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp
+++ b/storage/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp
@@ -1321,7 +1321,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);
@@ -1333,6 +1333,7 @@ Dbacc::startNext(Signal* signal, OperationrecPtr lastOp)
*/
return;
}
+ tmp.i = tmp.p->nextParallelQue;
}
upgrade:
diff --git a/storage/ndb/test/include/HugoOperations.hpp b/storage/ndb/test/include/HugoOperations.hpp
index b5014380eec..6126c705471 100644
--- a/storage/ndb/test/include/HugoOperations.hpp
+++ b/storage/ndb/test/include/HugoOperations.hpp
@@ -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();
diff --git a/storage/ndb/test/ndbapi/testBasic.cpp b/storage/ndb/test/ndbapi/testBasic.cpp
index e8e4548a91c..78cf28f5f76 100644
--- a/storage/ndb/test/ndbapi/testBasic.cpp
+++ b/storage/ndb/test/ndbapi/testBasic.cpp
@@ -1272,6 +1272,74 @@ runBug25090(NDBT_Context* ctx, NDBT_Step* step){
return NDBT_OK;
}
+int
+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;
+}
+
NDBT_TESTSUITE(testBasic);
TESTCASE("PkInsert",
"Verify that we can insert and delete from this table using PK"
@@ -1542,6 +1610,10 @@ TESTCASE("Bug25090",
"Verify what happens when we fill the db" ){
STEP(runBug25090);
}
+TESTCASE("Bug28073",
+ "Infinite loop in lock queue" ){
+ STEP(runBug28073);
+}
NDBT_TESTSUITE_END(testBasic);
#if 0
diff --git a/storage/ndb/test/run-test/daily-basic-tests.txt b/storage/ndb/test/run-test/daily-basic-tests.txt
index ddcc3f9aac1..3141e5e2c24 100644
--- a/storage/ndb/test/run-test/daily-basic-tests.txt
+++ b/storage/ndb/test/run-test/daily-basic-tests.txt
@@ -236,6 +236,10 @@ cmd: testBasic
args: -n Bug25090 T1
max-time: 500
+cmd: testBasic
+args: -n Bug28073
+
+max-time: 500
cmd: testIndex
args: -n Bug25059 -r 3000 T1
diff --git a/storage/ndb/test/src/HugoOperations.cpp b/storage/ndb/test/src/HugoOperations.cpp
index 50234cea351..be79a9f5701 100644
--- a/storage/ndb/test/src/HugoOperations.cpp
+++ b/storage/ndb/test/src/HugoOperations.cpp
@@ -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);