List:Commits« Previous MessageNext Message »
From:Jonas Oreland Date:October 20 2009 12:10pm
Subject:bzr commit into mysql-5.1-telco-6.2 branch (jonas:3021) Bug#48037
View as plain text  
#At file:///home/jonas/src/telco-6.2/ based on revid:jonas@stripped

 3021 Jonas Oreland	2009-10-20
      ndb - bug#48037
        Fix various abort cases with indexes that could in worst case 
          cause node-failure

    modified:
      storage/ndb/src/kernel/blocks/ERROR_codes.txt
      storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp
      storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp
      storage/ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp
      storage/ndb/test/ndbapi/testBasic.cpp
=== modified file 'storage/ndb/src/kernel/blocks/ERROR_codes.txt'
--- a/storage/ndb/src/kernel/blocks/ERROR_codes.txt	2009-10-05 10:38:50 +0000
+++ b/storage/ndb/src/kernel/blocks/ERROR_codes.txt	2009-10-20 12:10:49 +0000
@@ -2,7 +2,7 @@ Next QMGR 938
 Next NDBCNTR 1002
 Next NDBFS 2000
 Next DBACC 3002
-Next DBTUP 4029
+Next DBTUP 4031
 Next DBLQH 5054
 Next DBDICT 6008
 Next DBDIH 7215

=== modified file 'storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp'
--- a/storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp	2009-10-09 09:09:48 +0000
+++ b/storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp	2009-10-20 12:10:49 +0000
@@ -1972,7 +1972,8 @@ private:
                       Ptr<Operationrec> regOperPtr,
                       Ptr<Fragrecord>,
                       Tablerec* regTabPtr,
-                      KeyReqStruct* req_struct);
+                      KeyReqStruct* req_struct,
+                      Local_key ** accminupdateptr);
 
 //------------------------------------------------------------------
 //------------------------------------------------------------------

=== modified file 'storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp'
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp	2009-10-16 15:37:14 +0000
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp	2009-10-20 12:10:49 +0000
@@ -746,19 +746,36 @@ void Dbtup::execTUPKEYREQ(Signal* signal
      {
        jam();
    do_insert:
-       if (handleInsertReq(signal, operPtr,
-			   fragptr, regTabPtr, &req_struct) == -1) 
+       Local_key accminupdate;
+       Local_key * accminupdateptr = &accminupdate;
+       if (unlikely(handleInsertReq(signal, operPtr,
+                                    fragptr, regTabPtr, &req_struct,
+                                    &accminupdateptr) == -1))
        {
-	 return;
+         return;
        }
+
+       terrorCode = 0;
+       checkImmediateTriggersAfterInsert(&req_struct,
+                                         regOperPtr,
+                                         regTabPtr,
+                                         disk_page != RNIL);
+
+       if (unlikely(terrorCode != 0))
+       {
+         tupkeyErrorLab(signal);
+         return;
+       }
+
        if (!regTabPtr->tuxCustomTriggers.isEmpty()) 
        {
-	 jam();
-	 if (executeTuxInsertTriggers(signal,
-				      regOperPtr,
-				      regFragPtr,
-				      regTabPtr) != 0) {
-	   jam();
+         jam();
+         if (unlikely(executeTuxInsertTriggers(signal,
+                                               regOperPtr,
+                                               regFragPtr,
+                                               regTabPtr) != 0))
+         {
+           jam();
            /*
             * TUP insert succeeded but add of TUX entries failed.  All
             * TUX changes have been rolled back at this point.
@@ -773,53 +790,65 @@ void Dbtup::execTUPKEYREQ(Signal* signal
             */
            signal->theData[0] = operPtr.i;
            do_tup_abortreq(signal, ZSKIP_TUX_TRIGGERS);
-	   tupkeyErrorLab(signal);
-	   return;
-	 }
+           tupkeyErrorLab(signal);
+           return;
+         }
        }
-       checkImmediateTriggersAfterInsert(&req_struct,
-					 regOperPtr,
-					 regTabPtr,
-                                         disk_page != RNIL);
+
+       if (accminupdateptr)
+       {
+         /**
+          * Update ACC local-key, once *everything* has completed succesfully
+          */
+         c_lqh->accminupdate(signal,
+                             regOperPtr->userpointer,
+                             accminupdateptr);
+       }
+
        sendTUPKEYCONF(signal, &req_struct, regOperPtr);
        return;
      }
 
      if (Roptype == ZUPDATE) {
        jam();
-       if (handleUpdateReq(signal, regOperPtr,
-			   regFragPtr, regTabPtr, &req_struct, disk_page != RNIL) == -1) {
-	 return;
+       if (unlikely(handleUpdateReq(signal, regOperPtr,
+                                    regFragPtr, regTabPtr,
+                                    &req_struct, disk_page != RNIL) == -1))
+       {
+         return;
+       }
+
+       terrorCode = 0;
+       checkImmediateTriggersAfterUpdate(&req_struct,
+                                         regOperPtr,
+                                         regTabPtr,
+                                         disk_page != RNIL);
+
+       if (unlikely(terrorCode != 0))
+       {
+         tupkeyErrorLab(signal);
+         return;
        }
-       // If update operation is done on primary, 
-       // check any after op triggers
-       terrorCode= 0;
-       if (!regTabPtr->tuxCustomTriggers.isEmpty()) {
-	 jam();
-	 if (executeTuxUpdateTriggers(signal,
-				      regOperPtr,
-				      regFragPtr,
-				      regTabPtr) != 0) {
-	   jam();
+
+       if (!regTabPtr->tuxCustomTriggers.isEmpty())
+       {
+         jam();
+         if (unlikely(executeTuxUpdateTriggers(signal,
+                                               regOperPtr,
+                                               regFragPtr,
+                                               regTabPtr) != 0))
+         {
+           jam();
            /*
             * See insert case.
             */
            signal->theData[0] = operPtr.i;
            do_tup_abortreq(signal, ZSKIP_TUX_TRIGGERS);
-	   tupkeyErrorLab(signal);
-	   return;
-	 }
-       }
-       checkImmediateTriggersAfterUpdate(&req_struct,
-					 regOperPtr,
-					 regTabPtr,
-                                         disk_page != RNIL);
-       // XXX use terrorCode for now since all methods are void
-       if (terrorCode != 0) 
-       {
-	 tupkeyErrorLab(signal);
-	 return;
+           tupkeyErrorLab(signal);
+           return;
+         }
        }
+
        sendTUPKEYCONF(signal, &req_struct, regOperPtr);
        return;
      } 
@@ -827,24 +856,31 @@ void Dbtup::execTUPKEYREQ(Signal* signal
      {
        jam();
        req_struct.log_size= 0;
-       if (handleDeleteReq(signal, regOperPtr,
-			   regFragPtr, regTabPtr, 
-			   &req_struct,
-			   disk_page != RNIL) == -1) {
-	 return;
+       if (unlikely(handleDeleteReq(signal, regOperPtr,
+                                    regFragPtr, regTabPtr,
+                                    &req_struct,
+                                    disk_page != RNIL) == -1))
+       {
+         return;
        }
-       /*
-	* TUX doesn't need to check for triggers at delete since entries in
-	* the index are kept until commit time.
-	*/
 
-       /*
-	* Secondary index triggers fire on the primary after a delete.
-	*/
+       terrorCode = 0;
        checkImmediateTriggersAfterDelete(&req_struct,
-					 regOperPtr, 
-					 regTabPtr,
+                                         regOperPtr,
+                                         regTabPtr,
                                          disk_page != RNIL);
+
+       if (unlikely(terrorCode != 0))
+       {
+         tupkeyErrorLab(signal);
+         return;
+       }
+
+       /*
+        * TUX doesn't need to check for triggers at delete since entries in
+        * the index are kept until commit time.
+        */
+
        sendTUPKEYCONF(signal, &req_struct, regOperPtr);
        return;
      }
@@ -855,7 +891,7 @@ void Dbtup::execTUPKEYREQ(Signal* signal
    }
 
    tupkeyErrorLab(signal);
- }
+}
 
 void
 Dbtup::setup_fixed_part(KeyReqStruct* req_struct,
@@ -1094,6 +1130,9 @@ int Dbtup::handleUpdateReq(Signal* signa
     jam();
     setChecksum(req_struct->m_tuple_ptr, regTabPtr);
   }
+
+  set_tuple_state(operPtrP, TUPLE_PREPARED);
+
   return 0;
   
 error:
@@ -1326,7 +1365,8 @@ int Dbtup::handleInsertReq(Signal* signa
                            Ptr<Operationrec> regOperPtr,
                            Ptr<Fragrecord> fragPtr,
                            Tablerec* regTabPtr,
-                           KeyReqStruct *req_struct)
+                           KeyReqStruct *req_struct,
+                           Local_key ** accminupdateptr)
 {
   Uint32 tup_version = 1;
   Fragrecord* regFragPtr = fragPtr.p;
@@ -1620,17 +1660,21 @@ int Dbtup::handleInsertReq(Signal* signa
 
     Local_key accKey = regOperPtr.p->m_tuple_location;
     accKey.m_page_no = frag_page_id;
-
-    c_lqh->accminupdate(signal,
-                        regOperPtr.p->userpointer,
-                        &accKey);
+    ** accminupdateptr = accKey;
   }
-  
+  else
+  {
+    * accminupdateptr = 0; // No accminupdate should be performed
+  }
+
   if (regTabPtr->m_bits & Tablerec::TR_Checksum) 
   {
     jam();
     setChecksum(req_struct->m_tuple_ptr, regTabPtr);
   }
+
+  set_tuple_state(regOperPtr.p, TUPLE_PREPARED);
+
   return 0;
   
 size_change_error:
@@ -1728,6 +1772,9 @@ int Dbtup::handleDeleteReq(Signal* signa
       goto error;
     }
   }
+
+  set_tuple_state(regOperPtr, TUPLE_PREPARED);
+
   if (req_struct->attrinfo_len == 0)
   {
     return 0;

=== modified file 'storage/ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp'
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp	2009-05-26 18:53:34 +0000
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp	2009-10-20 12:10:49 +0000
@@ -759,6 +759,14 @@ void Dbtup::executeTrigger(KeyReqStruct 
     executeDirect= false; // remove warning
   }//switch
 
+
+  if (ERROR_INSERTED(4030))
+  {
+    terrorCode = ZREAD_ONLY_CONSTRAINT_VIOLATION;
+    // XXX should return status and abort the rest
+    return;
+  }
+
   req_struct->no_fired_triggers++;
 
   trigAttrInfo->setAttrInfoType(TrigAttrInfo::PRIMARY_KEY);

=== modified file 'storage/ndb/test/ndbapi/testBasic.cpp'
--- a/storage/ndb/test/ndbapi/testBasic.cpp	2009-10-16 15:37:14 +0000
+++ b/storage/ndb/test/ndbapi/testBasic.cpp	2009-10-20 12:10:49 +0000
@@ -24,6 +24,7 @@
 
 #define GETNDB(ps) ((NDBT_NdbApiStep*)ps)->getNdb()
 
+#include <signaldata/DictTabInfo.hpp>
 
 /**
  * TODO 
@@ -1092,7 +1093,9 @@ struct TupError 
     TE_VARSIZE  = 0x1,
     TE_MULTI_OP = 0x2,
     TE_DISK     = 0x4,
-    TE_REPLICA  = 0x8
+    TE_REPLICA  = 0x8,
+    TE_OI       = 0x10, // Ordered index
+    TE_UI       = 0x20  // Unique hash index
   };
   int op;
   int error;
@@ -1111,6 +1114,9 @@ f_tup_errors[] = 
   { NdbOperation::InsertRequest, 4019, TupError::TE_REPLICA }, //Alloc rowid error
   { NdbOperation::InsertRequest, 4020, TupError::TE_MULTI_OP }, // Size change error
   { NdbOperation::InsertRequest, 4021, TupError::TE_DISK },    // Out of disk space
+  { NdbOperation::InsertRequest, 4022, TupError::TE_OI },
+  { NdbOperation::InsertRequest, 4023, TupError::TE_OI },
+  { NdbOperation::UpdateRequest, 4030, TupError::TE_UI },
   { -1, 0, 0 }
 };
 
@@ -1138,6 +1144,16 @@ runTupErrors(NDBT_Context* ctx, NDBT_Ste
     bits |= TupError::TE_REPLICA;
   }
 
+  NdbDictionary::Dictionary::List l;
+  pNdb->getDictionary()->listIndexes(l, tab->getName());
+  for (i = 0; i<(int)l.count; i++)
+  {
+    if (DictTabInfo::isOrderedIndex(l.elements[i].type))
+      bits |= TupError::TE_OI;
+    if (DictTabInfo::isUniqueIndex(l.elements[i].type))
+      bits |= TupError::TE_UI;
+  }
+
   /**
    * Insert
    */
@@ -1145,20 +1161,18 @@ runTupErrors(NDBT_Context* ctx, NDBT_Ste
   {
     if (f_tup_errors[i].op != NdbOperation::InsertRequest)
     {
-      g_info << "Skipping " << f_tup_errors[i].error 
-	     << " -  not insert" << endl;
       continue;
     }
 
     if ((f_tup_errors[i].bits & bits) != f_tup_errors[i].bits)
     {
-      g_info << "Skipping " << f_tup_errors[i].error 
-	     << " - req bits: " << hex << f_tup_errors[i].bits
-	     << " bits: " << hex << bits << endl;
+      g_err << "Skipping " << f_tup_errors[i].error
+            << " - req bits: " << hex << f_tup_errors[i].bits
+            << " bits: " << hex << bits << endl;
       continue;
     }
     
-    g_info << "Testing error insert: " << f_tup_errors[i].error << endl;
+    g_err << "Testing error insert: " << f_tup_errors[i].error << endl;
     restarter.insertErrorInAllNodes(f_tup_errors[i].error);
     if (f_tup_errors[i].bits & TupError::TE_MULTI_OP)
     {
@@ -1174,6 +1188,42 @@ runTupErrors(NDBT_Context* ctx, NDBT_Ste
       return NDBT_FAILED;
     }      
   }
+
+  /**
+   * update
+   */
+  hugoTrans.loadTable(pNdb, 5);
+  for(i = 0; f_tup_errors[i].op != -1; i++)
+  {
+    if (f_tup_errors[i].op != NdbOperation::UpdateRequest)
+    {
+      continue;
+    }
+
+    if ((f_tup_errors[i].bits & bits) != f_tup_errors[i].bits)
+    {
+      g_err << "Skipping " << f_tup_errors[i].error
+            << " - req bits: " << hex << f_tup_errors[i].bits
+            << " bits: " << hex << bits << endl;
+      continue;
+    }
+
+    g_err << "Testing error insert: " << f_tup_errors[i].error << endl;
+    restarter.insertErrorInAllNodes(f_tup_errors[i].error);
+    if (f_tup_errors[i].bits & TupError::TE_MULTI_OP)
+    {
+
+    }
+    else
+    {
+      hugoTrans.scanUpdateRecords(pNdb, 5);
+    }
+    restarter.insertErrorInAllNodes(0);
+    if (hugoTrans.scanUpdateRecords(pNdb, 5) != 0)
+    {
+      return NDBT_FAILED;
+    }
+  }
   
   return NDBT_OK;
 }
@@ -1530,39 +1580,56 @@ runBug20535(NDBT_Context* ctx, NDBT_Step
 int
 runDDInsertFailUpdateBatch(NDBT_Context* ctx, NDBT_Step* step)
 {
+  Ndb* pNdb = GETNDB(step);
   NdbRestarter restarter;
   
   const NdbDictionary::Table * tab = ctx->getTab();
   
+  int errCode = 0;
+  int expectedError = 0;
   {
     bool tabHasDD = false;
-    
     for(int i = 0; i<tab->getNoOfColumns(); i++)
     {
       tabHasDD |= (tab->getColumn(i)->getStorageType() == 
                    NdbDictionary::Column::StorageTypeDisk);
     }
     
-    if (!tabHasDD)
+    if (tabHasDD)
     {
-      ndbout_c("Table %s has no disk attributes, skipping",
+      errCode = 4021;
+      expectedError = 1601;
+    }
+    else
+    {
+      NdbDictionary::Dictionary::List l;
+      pNdb->getDictionary()->listIndexes(l, tab->getName());
+      for (Uint32 i = 0; i<l.count; i++)
+      {
+        if (DictTabInfo::isOrderedIndex(l.elements[i].type))
+        {
+          errCode = 4023;
+          expectedError = 9999;
+          break;
+        }
+      }
+    }
+
+    if (errCode == 0)
+    {
+      ndbout_c("Table %s has no disk attributes or ordered indexes, skipping",
                tab->getName());
       return NDBT_OK;
     }
   }
 
   HugoOperations hugoOps(*ctx->getTab());
-  Ndb* pNdb = GETNDB(step);
-
-  /* Error Insert 4021 - DD tuple insert will fail in disk
-   * space preallocation step
-   */
-  restarter.insertErrorInAllNodes(4021);
 
   int result = NDBT_OK;
   
   for (Uint32 loop = 0; loop < 100; loop ++)
   {
+    restarter.insertErrorInAllNodes(errCode);
     CHECK(hugoOps.startTransaction(pNdb) == 0);
     
     /* Create batch with insert op (which will fail due to disk allocation issue)
@@ -1581,7 +1648,7 @@ runDDInsertFailUpdateBatch(NDBT_Context*
     
     NdbError err= hugoOps.getTransaction()->getNdbError();
     
-    CHECK(err.code == 1601); // Disk prealloc error
+    CHECK(err.code == expectedError);
     
     hugoOps.closeTransaction(pNdb);
   }  


Attachment: [text/bzr-bundle] bzr/jonas@mysql.com-20091020121049-gwqflvg1hqya1pfm.bundle
Thread
bzr commit into mysql-5.1-telco-6.2 branch (jonas:3021) Bug#48037Jonas Oreland20 Oct