List:Commits« Previous MessageNext Message »
From:jonas oreland Date:April 5 2011 9:12am
Subject:bzr commit into mysql-5.1-telco-7.0 branch (jonas:4279) Bug#12324191
View as plain text  
#At file:///home/jonas/src/telco-7.0/ based on revid:ole.john.aske@stripped

 4279 jonas oreland	2011-04-05
      ndb - bug#12324191 - fix tup-scan with locks, validate rowid in Dbtup::execACCKEYCONF

    modified:
      storage/ndb/src/kernel/blocks/dbtup/DbtupScan.cpp
      storage/ndb/test/ndbapi/testScan.cpp
      storage/ndb/test/run-test/daily-basic-tests.txt
=== modified file 'storage/ndb/src/kernel/blocks/dbtup/DbtupScan.cpp'
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupScan.cpp	2011-02-01 23:27:25 +0000
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupScan.cpp	2011-04-05 09:12:21 +0000
@@ -475,6 +475,21 @@ Dbtup::execACCKEYCONF(Signal* signal)
   jamEntry();
   ScanOpPtr scanPtr;
   scanPtr.i = signal->theData[0];
+
+  Uint32 localKey1 = signal->theData[3];
+  Uint32 localKey2 = signal->theData[4];
+  Uint32 localKeyFlag = signal->theData[5];
+  Local_key tmp;
+  if (localKeyFlag == 1)
+  {
+    tmp.assref(localKey1);
+  }
+  else
+  {
+    tmp.m_page_no = localKey1;
+    tmp.m_page_idx = localKey2;
+  }
+
   c_scanOpPool.getPtr(scanPtr);
   ScanOp& scan = *scanPtr.p;
   ndbrequire(scan.m_bits & ScanOp::SCAN_LOCK_WAIT && scan.m_accLockOp != RNIL);
@@ -482,10 +497,37 @@ Dbtup::execACCKEYCONF(Signal* signal)
   if (scan.m_state == ScanOp::Blocked) {
     // the lock wait was for current entry
     jam();
-    scan.m_state = ScanOp::Locked;
-    // LQH has the ball
-    return;
+
+    if (likely(scan.m_scanPos.m_key_mm.m_page_no == tmp.m_page_no &&
+               scan.m_scanPos.m_key_mm.m_page_idx == tmp.m_page_idx))
+    {
+      jam();
+      scan.m_state = ScanOp::Locked;
+      // LQH has the ball
+      return;
+    }
+    else
+    {
+      jam();
+      /**
+       * This means that there was DEL/INS on rowid that we tried to lock
+       *   and the primary key that was previously located on this rowid
+       *   (scanPos.m_key_mm) has moved.
+       *   (DBACC keeps of track of primary keys)
+       *
+       * We don't care about the primary keys, but is interested in ROWID
+       *   so rescan this position.
+       *   Which is implemented by using execACCKEYREF...
+       */
+      ndbout << "execACCKEYCONF "
+             << scan.m_scanPos.m_key_mm
+             << " != " << tmp << " ";
+      scan.m_bits |= ScanOp::SCAN_LOCK_WAIT;
+      execACCKEYREF(signal);
+      return;
+    }
   }
+
   if (scan.m_state != ScanOp::Aborting) {
     // we were moved, release lock
     jam();

=== modified file 'storage/ndb/test/ndbapi/testScan.cpp'
--- a/storage/ndb/test/ndbapi/testScan.cpp	2011-03-28 11:59:09 +0000
+++ b/storage/ndb/test/ndbapi/testScan.cpp	2011-04-05 09:12:21 +0000
@@ -297,6 +297,7 @@ int runScanRead(NDBT_Context* ctx, NDBT_
   int parallelism = ctx->getProperty("Parallelism", 240);
   int abort = ctx->getProperty("AbortProb", 5);
   int tupscan = ctx->getProperty("TupScan", (Uint32)0);
+  int lockmode = ctx->getProperty("LockMode", NdbOperation::LM_CommittedRead);
 
   int i = 0;
   HugoTransactions hugoTrans(*ctx->getTab());
@@ -308,12 +309,13 @@ int runScanRead(NDBT_Context* ctx, NDBT_
     {
       scan_flags |= NdbScanOperation::SF_TupScan;
       if (hugoTrans.scanReadRecords(GETNDB(step), records, abort, parallelism,
-                                    NdbOperation::LM_CommittedRead,
+                                    NdbOperation::LockMode(lockmode),
                                     scan_flags) != 0)
         return NDBT_FAILED;
     }
-    else if (hugoTrans.scanReadRecords(GETNDB(step), records, abort, parallelism)
-             != 0)
+    else if (hugoTrans.scanReadRecords(GETNDB(step), records, abort,
+                                       parallelism,
+                                       NdbOperation::LockMode(lockmode)) != 0)
     {
       return NDBT_FAILED;
     }
@@ -363,11 +365,13 @@ int runRandScanRead(NDBT_Context* ctx, N
 
 int runScanReadIndex(NDBT_Context* ctx, NDBT_Step* step){
   int loops = ctx->getNumLoops();
-  int records = ctx->getNumRecords();
+  int records = ctx->getProperty("Rows", ctx->getNumRecords());
   int parallelism = ctx->getProperty("Parallelism", 240);
   int abort = ctx->getProperty("AbortProb", 5);
-  const NdbDictionary::Index * pIdx = 
-    GETNDB(step)->getDictionary()->getIndex(orderedPkIdxName, 
+  int lockmode = ctx->getProperty("LockMode", NdbOperation::LM_CommittedRead);
+  int rand_mode = ctx->getProperty("RandScanOptions", Uint32(1));
+  const NdbDictionary::Index * pIdx =
+    GETNDB(step)->getDictionary()->getIndex(orderedPkIdxName,
 					    ctx->getTab()->getName());
 
   int i = 0;
@@ -376,11 +380,17 @@ int runScanReadIndex(NDBT_Context* ctx, 
     g_info << i << ": ";
     bool sort = (rand() % 100) > 50 ? true : false;
     bool desc = (rand() % 100) > 50 ? true : false;
+    NdbOperation::LockMode lm = (NdbOperation::LockMode)(rand() % 3);
     desc = false;       // random causes too many deadlocks
+    if (rand_mode == 0)
+    {
+      sort = false;
+      desc = false;
+      lm = (NdbOperation::LockMode)lockmode;
+    }
     int scan_flags =
       (NdbScanOperation::SF_OrderBy & -(int)sort) |
       (NdbScanOperation::SF_Descending & -(int)desc);
-    NdbOperation::LockMode lm = (NdbOperation::LockMode)(rand() % 3);
     if (hugoTrans.scanReadRecords(GETNDB(step), pIdx,
 				  records, abort, parallelism,
 				  lm,
@@ -1414,6 +1424,115 @@ runBug54945(NDBT_Context* ctx, NDBT_Step
   return NDBT_OK;
 }
 
+#define CHK_RET_FAILED(x) if (!(x)) { ndbout_c("Failed on line: %u", __LINE__); return NDBT_FAILED; }
+
+int
+runMixedDML(NDBT_Context* ctx, NDBT_Step* step)
+{
+  Ndb* pNdb = GETNDB(step);
+  const NdbDictionary::Table* pTab = ctx->getTab();
+
+  unsigned seed = (unsigned)NdbTick_CurrentMillisecond();
+
+  const int rows = ctx->getNumRecords();
+  const int loops = 10 * ctx->getNumLoops();
+  const int until_stopped = ctx->getProperty("UntilStopped");
+  const int batch = ctx->getProperty("Batch", Uint32(50));
+
+  const NdbRecord * pRowRecord = pTab->getDefaultRecord();
+  CHK_RET_FAILED(pRowRecord != 0);
+
+  const Uint32 len = NdbDictionary::getRecordRowLength(pRowRecord);
+  Uint8 * pRow = new Uint8[len];
+
+  int count_ok = 0;
+  int count_failed = 0;
+  for (int i = 0; i < loops || (until_stopped && !ctx->isTestStopped()); i++)
+  {
+    NdbTransaction* pTrans = pNdb->startTransaction();
+    CHK_RET_FAILED(pTrans != 0);
+
+    int lastrow = 0;
+    int result = 0;
+    for (int rowNo = 0; rowNo < batch; rowNo++)
+    {
+      int left = rows - lastrow;
+      int rowId = lastrow;
+      if (left)
+      {
+        rowId += ndb_rand_r(&seed) % (left / 10 + 1);
+      }
+      else
+      {
+        break;
+      }
+      lastrow = rowId;
+
+      bzero(pRow, len);
+
+      HugoCalculator calc(* pTab);
+      calc.setValues(pRow, pRowRecord, rowId, rand());
+
+      NdbOperation::OperationOptions opts;
+      bzero(&opts, sizeof(opts));
+
+      const NdbOperation* pOp = 0;
+      switch(ndb_rand_r(&seed) % 3){
+      case 0:
+        pOp = pTrans->writeTuple(pRowRecord, (char*)pRow,
+                                 pRowRecord, (char*)pRow,
+                                 0,
+                                 &opts,
+                                 sizeof(opts));
+        break;
+      case 1:
+        pOp = pTrans->deleteTuple(pRowRecord, (char*)pRow,
+                                  pRowRecord, (char*)pRow,
+                                  0,
+                                  &opts,
+                                  sizeof(opts));
+        break;
+      case 2:
+        pOp = pTrans->updateTuple(pRowRecord, (char*)pRow,
+                                  pRowRecord, (char*)pRow,
+                                  0,
+                                  &opts,
+                                  sizeof(opts));
+        break;
+      }
+      CHK_RET_FAILED(pOp != 0);
+      result = pTrans->execute(NoCommit, AO_IgnoreError);
+      if (result != 0)
+      {
+        goto found_error;
+      }
+    }
+
+    result = pTrans->execute(Commit, AO_IgnoreError);
+    if (result != 0)
+    {
+  found_error:
+      count_failed++;
+      NdbError err = pTrans->getNdbError();
+      ndbout << err << endl;
+      CHK_RET_FAILED(err.status == NdbError::TemporaryError ||
+                     err.classification == NdbError::NoDataFound ||
+                     err.classification == NdbError::ConstraintViolation);
+    }
+    else
+    {
+      count_ok++;
+    }
+    pTrans->close();
+  }
+
+  ndbout_c("count_ok: %d count_failed: %d",
+           count_ok, count_failed);
+  delete [] pRow;
+
+  return NDBT_OK;
+}
+
 NDBT_TESTSUITE(testScan);
 TESTCASE("ScanRead", 
 	 "Verify scan requirement: It should be possible "\
@@ -1951,6 +2070,15 @@ TESTCASE("Bug54945", "")
 {
   INITIALIZER(runBug54945);
 }
+TESTCASE("Bug12324191", "")
+{
+  TC_PROPERTY("LockMode", Uint32(NdbOperation::LM_Read));
+  TC_PROPERTY("TupScan", Uint32(1));
+  TC_PROPERTY("Rows", Uint32(0));
+  INITIALIZER(runLoadTable);
+  STEP(runScanRead);
+  STEPS(runMixedDML,10);
+}
 NDBT_TESTSUITE_END(testScan);
 
 int main(int argc, const char** argv){

=== modified file 'storage/ndb/test/run-test/daily-basic-tests.txt'
--- a/storage/ndb/test/run-test/daily-basic-tests.txt	2011-04-01 07:10:05 +0000
+++ b/storage/ndb/test/run-test/daily-basic-tests.txt	2011-04-05 09:12:21 +0000
@@ -563,6 +563,10 @@ max-time: 500
 cmd: testScan
 args: -n Bug54945 T1
 
+max-time: 600
+cmd: testScan
+args: -n Bug12324191 T1 T6 T13
+
 max-time: 1800
 cmd: testNodeRestart
 args: -n Bug27003 T1


Attachment: [text/bzr-bundle] bzr/jonas@mysql.com-20110405091221-rr1jq22awomyb4qc.bundle
Thread
bzr commit into mysql-5.1-telco-7.0 branch (jonas:4279) Bug#12324191jonas oreland5 Apr