#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#48037 | Jonas Oreland | 20 Oct |