List:Commits« Previous MessageNext Message »
From:knielsen Date:April 26 2007 8:01am
Subject:bk commit into 5.1 tree (knielsen:1.2488)
View as plain text  
Below is the list of changes that have just been committed into a local
5.1 repository of knielsen. When knielsen does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet@stripped, 2007-04-26 08:01:06+02:00, knielsen@ymer.(none) +10 -0
  Merge ymer.(none):/usr/local/mysql/mysql-5.1-new-ndb
  into  ymer.(none):/usr/local/mysql/mysql-5.1-telco
  MERGE: 1.2484.1.6

  storage/ndb/include/ndbapi/NdbOperation.hpp@stripped, 2007-04-26 07:59:29+02:00,
knielsen@ymer.(none) +0 -0
    Auto merged
    MERGE: 1.42.3.1

  storage/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp@stripped, 2007-04-26 07:59:29+02:00,
knielsen@ymer.(none) +0 -0
    Auto merged
    MERGE: 1.83.1.2

  storage/ndb/src/ndbapi/NdbBlob.cpp@stripped, 2007-04-26 07:59:29+02:00, knielsen@ymer.(none)
+0 -0
    Auto merged
    MERGE: 1.55.1.1

  storage/ndb/src/ndbapi/NdbOperationDefine.cpp@stripped, 2007-04-26 07:59:29+02:00,
knielsen@ymer.(none) +0 -0
    Auto merged
    MERGE: 1.29.1.2

  storage/ndb/src/ndbapi/NdbScanOperation.cpp@stripped, 2007-04-26 07:59:30+02:00,
knielsen@ymer.(none) +0 -0
    Auto merged
    MERGE: 1.105.1.10

  storage/ndb/src/ndbapi/NdbTransaction.cpp@stripped, 2007-04-26 07:59:30+02:00,
knielsen@ymer.(none) +0 -0
    Auto merged
    MERGE: 1.75.1.3

  storage/ndb/test/ndbapi/testBasic.cpp@stripped, 2007-04-26 07:59:30+02:00,
knielsen@ymer.(none) +0 -0
    Auto merged
    MERGE: 1.17.1.4

  storage/ndb/test/ndbapi/testBlobs.cpp@stripped, 2007-04-26 07:59:30+02:00,
knielsen@ymer.(none) +0 -0
    Auto merged
    MERGE: 1.38.1.1

  storage/ndb/test/ndbapi/testNdbApi.cpp@stripped, 2007-04-26 08:01:03+02:00,
knielsen@ymer.(none) +59 -59
    Manual merge.
    MERGE: 1.25.1.1

  storage/ndb/test/run-test/daily-basic-tests.txt@stripped, 2007-04-26 07:59:30+02:00,
knielsen@ymer.(none) +0 -0
    Auto merged
    MERGE: 1.61.1.21

# This is a BitKeeper patch.  What follows are the unified diffs for the
# set of deltas contained in the patch.  The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User:	knielsen
# Host:	ymer.(none)
# Root:	/usr/local/mysql/mysql-5.1-telco/RESYNC

--- 1.95/storage/ndb/test/run-test/daily-basic-tests.txt	2007-04-26 08:01:14 +02:00
+++ 1.96/storage/ndb/test/run-test/daily-basic-tests.txt	2007-04-26 08:01:14 +02:00
@@ -244,6 +244,10 @@ cmd: testBasic
 args: -n Bug27756
 
 max-time: 500
+cmd: testBasic
+args: -n Bug28073
+
+max-time: 500
 cmd: testIndex
 args: -n Bug25059 -r 3000 T1
 
@@ -696,6 +700,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 
@@ -715,6 +723,14 @@ args: T6 
 max-time: 1500
 cmd: testBlobs
 args:
+
+max-time: 600
+cmd: testBlobs
+args: -bug 27018
+
+max-time: 600
+cmd: testBlobs
+args: -bug 27370
 
 max-time: 5000
 cmd: testOIBasic

--- 1.45/storage/ndb/include/ndbapi/NdbOperation.hpp	2007-04-26 08:01:14 +02:00
+++ 1.46/storage/ndb/include/ndbapi/NdbOperation.hpp	2007-04-26 08:01:14 +02:00
@@ -949,6 +949,8 @@ protected:
   // get table or index key from prepared signals
   int getKeyFromTCREQ(Uint32* data, Uint32 & size);
 
+  virtual void setReadLockMode(LockMode lockMode);
+
 /******************************************************************************
  * These are the private variables that are defined in the operation objects.
  *****************************************************************************/

--- 1.85/storage/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp	2007-04-26 08:01:14 +02:00
+++ 1.86/storage/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp	2007-04-26 08:01:14 +02:00
@@ -1320,7 +1320,7 @@ Dbacc::startNext(Signal* signal, Operati
    * 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, Operati
        */
       return;
     }
+    tmp.i = tmp.p->nextParallelQue;
   }
   
 upgrade:

--- 1.77/storage/ndb/src/ndbapi/NdbTransaction.cpp	2007-04-26 08:01:14 +02:00
+++ 1.78/storage/ndb/src/ndbapi/NdbTransaction.cpp	2007-04-26 08:01:14 +02:00
@@ -676,6 +676,17 @@ NdbTransaction::executeAsynchPrepare(Ndb
   DBUG_VOID_RETURN;
 }//NdbTransaction::executeAsynchPrepare()
 
+void
+NdbTransaction::executeAsynch(ExecType aTypeOfExec,
+                              NdbAsynchCallback aCallback,
+                              void* anyObject,
+                              NdbOperation::AbortOption abortOption,
+                              int forceSend)
+{
+  executeAsynchPrepare(aTypeOfExec, aCallback, anyObject, abortOption);
+  theNdb->sendPreparedTransactions(forceSend);
+}
+
 void NdbTransaction::close()
 {
   theNdb->closeTransaction(this);

--- 1.31/storage/ndb/src/ndbapi/NdbOperationDefine.cpp	2007-04-26 08:01:14 +02:00
+++ 1.32/storage/ndb/src/ndbapi/NdbOperationDefine.cpp	2007-04-26 08:01:14 +02:00
@@ -333,6 +333,36 @@ NdbOperation::interpretedDeleteTuple()
   }//if
 }//NdbOperation::interpretedDeleteTuple()
 
+void
+NdbOperation::setReadLockMode(LockMode lockMode)
+{
+  /* We only support changing lock mode for read operations at this time. */
+  assert(theOperationType == ReadRequest || theOperationType == ReadExclusive);
+  switch (lockMode)
+  {
+    case LM_CommittedRead:
+      theOperationType= ReadRequest;
+      theSimpleIndicator= 1;
+      theDirtyIndicator= 1;
+      break;
+    case LM_Read:
+      theNdbCon->theSimpleState= 0;
+      theOperationType= ReadRequest;
+      theSimpleIndicator= 0;
+      theDirtyIndicator= 0;
+      break;
+    case LM_Exclusive:
+      theNdbCon->theSimpleState= 0;
+      theOperationType= ReadExclusive;
+      theSimpleIndicator= 0;
+      theDirtyIndicator= 0;
+      break;
+    default:
+      /* Not supported / invalid. */
+      assert(false);
+  }
+  theLockMode= lockMode;
+}
 
 
 /******************************************************************************

--- 1.115/storage/ndb/src/ndbapi/NdbScanOperation.cpp	2007-04-26 08:01:14 +02:00
+++ 1.116/storage/ndb/src/ndbapi/NdbScanOperation.cpp	2007-04-26 08:01:14 +02:00
@@ -138,34 +138,9 @@ NdbScanOperation::readTuples(NdbScanOper
   }
 
   theNdbCon->theScanningOp = this;
-  theLockMode = lm;
-
-  bool lockExcl, lockHoldMode, readCommitted;
-  switch(lm){
-  case NdbScanOperation::LM_Read:
-    lockExcl = false;
-    lockHoldMode = true;
-    readCommitted = false;
-    break;
-  case NdbScanOperation::LM_Exclusive:
-    lockExcl = true;
-    lockHoldMode = true;
-    readCommitted = false;
-    break;
-  case NdbScanOperation::LM_CommittedRead:
-    lockExcl = false;
-    lockHoldMode = false;
-    readCommitted = true;
-    break;
-  default:
-    setErrorCode(4003);
-    return -1;
-  }
-
-  m_keyInfo = ((scan_flags & SF_KeyInfo) || lockExcl) ? 1 : 0;
   bool tupScan = (scan_flags & SF_TupScan);
 
-#if 1 // XXX temp for testing
+#if 0 // XXX temp for testing
   { char* p = getenv("NDB_USE_TUPSCAN");
     if (p != 0) {
       unsigned n = atoi(p); // 0-10
@@ -225,13 +200,13 @@ NdbScanOperation::readTuples(NdbScanOper
   Uint32 reqInfo = 0;
   ScanTabReq::setParallelism(reqInfo, parallel);
   ScanTabReq::setScanBatch(reqInfo, 0);
-  ScanTabReq::setLockMode(reqInfo, lockExcl);
-  ScanTabReq::setHoldLockFlag(reqInfo, lockHoldMode);
-  ScanTabReq::setReadCommittedFlag(reqInfo, readCommitted);
   ScanTabReq::setRangeScanFlag(reqInfo, rangeScan);
   ScanTabReq::setTupScanFlag(reqInfo, tupScan);
   req->requestInfo = reqInfo;
 
+  m_keyInfo = (scan_flags & SF_KeyInfo) ? 1 : 0;
+  setReadLockMode(lm);
+
   Uint64 transId = theNdbCon->getTransactionId();
   req->transId1 = (Uint32) transId;
   req->transId2 = (Uint32) (transId >> 32);
@@ -249,6 +224,41 @@ NdbScanOperation::readTuples(NdbScanOper
 
   getFirstATTRINFOScan();
   return 0;
+}
+
+void
+NdbScanOperation::setReadLockMode(LockMode lockMode)
+{
+  bool lockExcl, lockHoldMode, readCommitted;
+  switch (lockMode)
+  {
+    case LM_CommittedRead:
+      lockExcl= false;
+      lockHoldMode= false;
+      readCommitted= true;
+      break;
+    case LM_Read:
+      lockExcl= false;
+      lockHoldMode= true;
+      readCommitted= false;
+      break;
+    case LM_Exclusive:
+      lockExcl= true;
+      lockHoldMode= true;
+      readCommitted= false;
+      m_keyInfo= 1;
+      break;
+    default:
+      /* Not supported / invalid. */
+      assert(false);
+  }
+  theLockMode= lockMode;
+  ScanTabReq *req= CAST_PTR(ScanTabReq, theSCAN_TABREQ->getDataPtrSend());
+  Uint32 reqInfo= req->requestInfo;
+  ScanTabReq::setLockMode(reqInfo, lockExcl);
+  ScanTabReq::setHoldLockFlag(reqInfo, lockHoldMode);
+  ScanTabReq::setReadCommittedFlag(reqInfo, readCommitted);
+  req->requestInfo= reqInfo;
 }
 
 int

--- 1.21/storage/ndb/test/ndbapi/testBasic.cpp	2007-04-26 08:01:14 +02:00
+++ 1.22/storage/ndb/test/ndbapi/testBasic.cpp	2007-04-26 08:01:14 +02:00
@@ -1374,6 +1374,74 @@ runBug27756(NDBT_Context* ctx, NDBT_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;
+}
+
 template class Vector<Uint64>;
 
 NDBT_TESTSUITE(testBasic);
@@ -1655,6 +1723,10 @@ TESTCASE("DeleteRead", 
 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);
 

--- 1.40/storage/ndb/test/ndbapi/testBlobs.cpp	2007-04-26 08:01:14 +02:00
+++ 1.41/storage/ndb/test/ndbapi/testBlobs.cpp	2007-04-26 08:01:14 +02:00
@@ -157,6 +157,7 @@ printusage()
     << "bug tests" << endl
     << "  -bug 4088   ndb api hang with mixed ops on index table" << endl
     << "  -bug 27018  middle partial part write clobbers rest of part" <<
endl
+    << "  -bug 27370  Potential inconsistent blob reads for ReadCommitted reads"
<< endl
     ;
 }
 
@@ -2140,12 +2141,210 @@ bugtest_27018()
   return 0;
 }
 
+
+struct bug27370_data {
+  Ndb *m_ndb;
+  char m_current_write_value;
+  char *m_writebuf;
+  Uint32 m_blob1_size;
+  Uint32 m_pk1;
+  char m_pk2[g_max_pk2len + 1];
+  bool m_thread_stop;
+};
+
+void *bugtest_27370_thread(void *arg)
+{
+  bug27370_data *data= (bug27370_data *)arg;
+
+  while (!data->m_thread_stop)
+  {
+    memset(data->m_writebuf, data->m_current_write_value, data->m_blob1_size);
+    data->m_current_write_value++;
+
+    NdbConnection *con;
+    if ((con= data->m_ndb->startTransaction()) == 0)
+      return (void *)"Failed to create transaction";
+    NdbOperation *opr;
+    if ((opr= con->getNdbOperation(g_opt.m_tname)) == 0)
+      return (void *)"Failed to create operation";
+    if (opr->writeTuple() != 0)
+      return (void *)"writeTuple() failed";
+    if (opr->equal("PK1", data->m_pk1) != 0)
+      return (void *)"equal(PK1) failed";
+    if (g_opt.m_pk2len != 0)
+      if (opr->equal("PK2", data->m_pk2) != 0)
+        return (void *)"equal(PK2) failed";
+    NdbBlob *bh;
+    if ((bh= opr->getBlobHandle("BL1")) == 0)
+      return (void *)"getBlobHandle() failed";
+    if (bh->setValue(data->m_writebuf, data->m_blob1_size) != 0)
+      return (void *)"setValue() failed";
+    if (con->execute(Commit, AbortOnError, 1) != 0)
+      return (void *)"execute() failed";
+    data->m_ndb->closeTransaction(con);
+  }
+
+  return NULL;                                  // Success
+}
+
+static int
+bugtest_27370()
+{
+  DBG("bug test 27370 - Potential inconsistent blob reads for ReadCommitted reads");
+
+  bug27370_data data;
+
+  data.m_ndb= new Ndb(g_ncc, "TEST_DB");
+  CHK(data.m_ndb->init(20) == 0);
+  CHK(data.m_ndb->waitUntilReady() == 0);
+
+  data.m_current_write_value= 0;
+  data.m_blob1_size= g_opt.m_blob1.m_inline + 10 * g_opt.m_blob1.m_partsize;
+  CHK((data.m_writebuf= new char [data.m_blob1_size]) != 0);
+  data.m_pk1= 27370;
+  memset(data.m_pk2, 'x', g_max_pk2len);
+  data.m_pk2[g_max_pk2len]= '\0';
+  data.m_thread_stop= false;
+
+  memset(data.m_writebuf, data.m_current_write_value, data.m_blob1_size);
+  data.m_current_write_value++;
+
+  CHK((g_con= g_ndb->startTransaction()) != 0);
+  CHK((g_opr= g_con->getNdbOperation(g_opt.m_tname)) != 0);
+  CHK(g_opr->writeTuple() == 0);
+  CHK(g_opr->equal("PK1", data.m_pk1) == 0);
+  if (g_opt.m_pk2len != 0)
+    CHK(g_opr->equal("PK2", data.m_pk2) == 0);
+  CHK((g_bh1= g_opr->getBlobHandle("BL1")) != 0);
+  CHK(g_bh1->setValue(data.m_writebuf, data.m_blob1_size) == 0);
+  CHK(g_con->execute(Commit) == 0);
+  g_ndb->closeTransaction(g_con);
+  g_con= NULL;
+
+  pthread_t thread_handle;
+  CHK(pthread_create(&thread_handle, NULL, bugtest_27370_thread, &data) == 0);
+
+  DBG("bug test 27370 - PK blob reads");
+  Uint32 seen_updates= 0;
+  while (seen_updates < 50)
+  {
+    CHK((g_con= g_ndb->startTransaction()) != 0);
+    CHK((g_opr= g_con->getNdbOperation(g_opt.m_tname)) != 0);
+    CHK(g_opr->readTuple(NdbOperation::LM_CommittedRead) == 0);
+    CHK(g_opr->equal("PK1", data.m_pk1) == 0);
+    if (g_opt.m_pk2len != 0)
+      CHK(g_opr->equal("PK2", data.m_pk2) == 0);
+    CHK((g_bh1= g_opr->getBlobHandle("BL1")) != 0);
+    CHK(g_con->execute(NoCommit, AbortOnError, 1) == 0);
+
+    const Uint32 loop_max= 10;
+    char read_char;
+    char original_read_char= 0;
+    Uint32 readloop;
+    for (readloop= 0;; readloop++)
+    {
+      if (readloop > 0)
+      {
+        if (readloop > 1)
+        {
+          /* Compare against first read. */
+          CHK(read_char == original_read_char);
+        }
+        else
+        {
+          /*
+            We count the number of times we see the other thread had the
+            chance to update, so that we can be sure it had the opportunity
+            to run a reasonable number of times before we stop.
+          */
+          if (original_read_char != read_char)
+            seen_updates++;
+          original_read_char= read_char;
+        }
+      }
+      if (readloop > loop_max)
+        break;
+      Uint32 readSize= 1;
+      CHK(g_bh1->setPos(urandom(data.m_blob1_size)) == 0);
+      CHK(g_bh1->readData(&read_char, readSize) == 0);
+      CHK(readSize == 1);
+      ExecType commitType= readloop == loop_max ? Commit : NoCommit;
+      CHK(g_con->execute(commitType, AbortOnError, 1) == 0);
+    }
+    g_ndb->closeTransaction(g_con);
+    g_con= NULL;
+  }
+
+  DBG("bug test 27370 - table scan blob reads");
+  seen_updates= 0;
+  while (seen_updates < 50)
+  {
+    CHK((g_con= g_ndb->startTransaction()) != 0);
+    CHK((g_ops= g_con->getNdbScanOperation(g_opt.m_tname)) != 0);
+    CHK(g_ops->readTuples(NdbOperation::LM_CommittedRead) == 0);
+    CHK((g_bh1= g_ops->getBlobHandle("BL1")) != 0);
+    CHK(g_con->execute(NoCommit, AbortOnError, 1) == 0);
+    CHK(g_ops->nextResult(true) == 0);
+
+    const Uint32 loop_max= 10;
+    char read_char;
+    char original_read_char= 0;
+    Uint32 readloop;
+    for (readloop= 0;; readloop++)
+    {
+      if (readloop > 0)
+      {
+        if (readloop > 1)
+        {
+          /* Compare against first read. */
+          CHK(read_char == original_read_char);
+        }
+        else
+        {
+          /*
+            We count the number of times we see the other thread had the
+            chance to update, so that we can be sure it had the opportunity
+            to run a reasonable number of times before we stop.
+          */
+          if (original_read_char != read_char)
+            seen_updates++;
+          original_read_char= read_char;
+        }
+      }
+      if (readloop > loop_max)
+        break;
+      Uint32 readSize= 1;
+      CHK(g_bh1->setPos(urandom(data.m_blob1_size)) == 0);
+      CHK(g_bh1->readData(&read_char, readSize) == 0);
+      CHK(readSize == 1);
+      CHK(g_con->execute(NoCommit, AbortOnError, 1) == 0);
+    }
+
+    CHK(g_ops->nextResult(true) == 1);
+    g_ndb->closeTransaction(g_con);
+    g_con= NULL;
+  }
+
+  data.m_thread_stop= true;
+  void *thread_return;
+  CHK(pthread_join(thread_handle, &thread_return) == 0);
+  DBG("bug 27370 - thread return status: " <<
+      (thread_return ? (char *)thread_return : "<null>"));
+  CHK(thread_return == 0);
+
+  g_con= NULL;
+  g_opr= NULL;
+  g_bh1= NULL;
+  return 0;
+}
+
 static struct {
   int m_bug;
   int (*m_test)();
 } g_bugtest[] = {
   { 4088, bugtest_4088 },
-  { 27018, bugtest_27018 }
+  { 27018, bugtest_27018 },
+  { 27370, bugtest_27370 }
 };
 
 NDB_COMMAND(testOdbcDriver, "testBlobs", "testBlobs", "testBlobs", 65535)

--- 1.26/storage/ndb/test/ndbapi/testNdbApi.cpp	2007-04-26 08:01:14 +02:00
+++ 1.27/storage/ndb/test/ndbapi/testNdbApi.cpp	2007-04-26 08:01:14 +02:00
@@ -1572,6 +1572,75 @@ int runCheckNdbObjectList(NDBT_Context* 
   return (cnt1 == do_cnt(con)) ? NDBT_OK : NDBT_FAILED;
 }
   
+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*>;
 
 
@@ -1674,6 +1743,10 @@ TESTCASE("IgnoreError", ""){
 TESTCASE("CheckNdbObjectList", 
 	 ""){ 
   INITIALIZER(runCheckNdbObjectList);
+}
+TESTCASE("ExecuteAsynch", 
+	 "Check that executeAsync() works (BUG#27495)\n"){ 
+  INITIALIZER(runTestExecuteAsynch);
 }
 NDBT_TESTSUITE_END(testNdbApi);
 

--- 1.57/storage/ndb/src/ndbapi/NdbBlob.cpp	2007-04-26 08:01:14 +02:00
+++ 1.58/storage/ndb/src/ndbapi/NdbBlob.cpp	2007-04-26 08:01:14 +02:00
@@ -1837,7 +1837,7 @@ NdbBlob::atPrepare(NdbTransaction* aCon,
     if (isReadOp()) {
       // upgrade lock mode
       if (theNdbOp->theLockMode == NdbOperation::LM_CommittedRead)
-        theNdbOp->theLockMode = NdbOperation::LM_Read;
+        theNdbOp->setReadLockMode(NdbOperation::LM_Read);
       // add read of head+inline in this op
       if (getHeadInlineValue(theNdbOp) == -1)
         DBUG_RETURN(-1);
@@ -1858,7 +1858,7 @@ NdbBlob::atPrepare(NdbTransaction* aCon,
   if (isScanOp()) {
     // upgrade lock mode
     if (theNdbOp->theLockMode == NdbOperation::LM_CommittedRead)
-      theNdbOp->theLockMode = NdbOperation::LM_Read;
+      theNdbOp->setReadLockMode(NdbOperation::LM_Read);
     // add read of head+inline in this op
     if (getHeadInlineValue(theNdbOp) == -1)
       DBUG_RETURN(-1);
Thread
bk commit into 5.1 tree (knielsen:1.2488)knielsen26 Apr