Commit dc78a772 authored by joreland@mysql.com's avatar joreland@mysql.com

bug#11166 - ndb

  Fix potential inconsistency when running ndb_restore due to faulty parsing
    of backup log wrt inserts
parent e6dfe6aa
...@@ -1676,13 +1676,30 @@ Backup::execWAIT_GCP_CONF(Signal* signal){ ...@@ -1676,13 +1676,30 @@ Backup::execWAIT_GCP_CONF(Signal* signal){
ptr.p->masterData.sendCounter= 0; ptr.p->masterData.sendCounter= 0;
ptr.p->masterData.gsn = GSN_BACKUP_FRAGMENT_REQ; ptr.p->masterData.gsn = GSN_BACKUP_FRAGMENT_REQ;
nextFragment(signal, ptr); nextFragment(signal, ptr);
return;
} else { } else {
jam(); jam();
CRASH_INSERTION((10009)); if(gcp >= ptr.p->startGCP + 3)
ptr.p->stopGCP = gcp; {
sendDropTrig(signal, ptr); // regular dropping of triggers CRASH_INSERTION((10009));
}//if ptr.p->stopGCP = gcp;
sendDropTrig(signal, ptr); // regular dropping of triggers
return;
}//if
/**
* Make sure that we got entire stopGCP
*/
WaitGCPReq * req = (WaitGCPReq*)signal->getDataPtrSend();
req->senderRef = reference();
req->senderData = ptr.i;
req->requestType = WaitGCPReq::CompleteForceStart;
sendSignal(DBDIH_REF, GSN_WAIT_GCP_REQ, signal,
WaitGCPReq::SignalLength,JBB);
return;
}
} }
/***************************************************************************** /*****************************************************************************
* *
* Master functionallity - Backup fragment * Master functionallity - Backup fragment
......
...@@ -765,6 +765,7 @@ RestoreLogIterator::RestoreLogIterator(const RestoreMetaData & md) ...@@ -765,6 +765,7 @@ RestoreLogIterator::RestoreLogIterator(const RestoreMetaData & md)
setLogFile(md, 0); setLogFile(md, 0);
m_count = 0; m_count = 0;
m_last_gci = 0;
} }
const LogEntry * const LogEntry *
...@@ -772,7 +773,6 @@ RestoreLogIterator::getNextLogEntry(int & res) { ...@@ -772,7 +773,6 @@ RestoreLogIterator::getNextLogEntry(int & res) {
// Read record length // Read record length
typedef BackupFormat::LogFile::LogEntry LogE; typedef BackupFormat::LogFile::LogEntry LogE;
Uint32 gcp= 0;
LogE * logE= 0; LogE * logE= 0;
Uint32 len= ~0; Uint32 len= ~0;
const Uint32 stopGCP = m_metaData.getStopGCP(); const Uint32 stopGCP = m_metaData.getStopGCP();
...@@ -802,10 +802,10 @@ RestoreLogIterator::getNextLogEntry(int & res) { ...@@ -802,10 +802,10 @@ RestoreLogIterator::getNextLogEntry(int & res) {
if(hasGcp){ if(hasGcp){
len--; len--;
gcp = ntohl(logE->Data[len-2]); m_last_gci = ntohl(logE->Data[len-2]);
} }
} while(gcp > stopGCP + 1); } while(m_last_gci > stopGCP + 1);
m_logEntry.m_table = m_metaData.getTable(logE->TableId); m_logEntry.m_table = m_metaData.getTable(logE->TableId);
switch(logE->TriggerEvent){ switch(logE->TriggerEvent){
case TriggerEvent::TE_INSERT: case TriggerEvent::TE_INSERT:
......
...@@ -361,6 +361,7 @@ private: ...@@ -361,6 +361,7 @@ private:
const RestoreMetaData & m_metaData; const RestoreMetaData & m_metaData;
Uint32 m_count; Uint32 m_count;
Uint32 m_last_gci;
LogEntry m_logEntry; LogEntry m_logEntry;
public: public:
RestoreLogIterator(const RestoreMetaData &); RestoreLogIterator(const RestoreMetaData &);
......
...@@ -512,7 +512,14 @@ BackupRestore::logEntry(const LogEntry & tup) ...@@ -512,7 +512,14 @@ BackupRestore::logEntry(const LogEntry & tup)
<< " Exiting..."; << " Exiting...";
exit(-1); exit(-1);
} }
if (check != 0)
{
err << "Error defining op: " << trans->getNdbError() << endl;
exit(-1);
} // if
Bitmask<4096> keys;
for (Uint32 i= 0; i < tup.size(); i++) for (Uint32 i= 0; i < tup.size(); i++)
{ {
const AttributeS * attr = tup[i]; const AttributeS * attr = tup[i];
...@@ -525,9 +532,21 @@ BackupRestore::logEntry(const LogEntry & tup) ...@@ -525,9 +532,21 @@ BackupRestore::logEntry(const LogEntry & tup)
const Uint32 length = (size / 8) * arraySize; const Uint32 length = (size / 8) * arraySize;
if (attr->Desc->m_column->getPrimaryKey()) if (attr->Desc->m_column->getPrimaryKey())
op->equal(attr->Desc->attrId, dataPtr, length); {
if(!keys.get(attr->Desc->attrId))
{
keys.set(attr->Desc->attrId);
check= op->equal(attr->Desc->attrId, dataPtr, length);
}
}
else else
op->setValue(attr->Desc->attrId, dataPtr, length); check= op->setValue(attr->Desc->attrId, dataPtr, length);
if (check != 0)
{
err << "Error defining op: " << trans->getNdbError() << endl;
exit(-1);
} // if
} }
const int ret = trans->execute(Commit); const int ret = trans->execute(Commit);
...@@ -536,18 +555,25 @@ BackupRestore::logEntry(const LogEntry & tup) ...@@ -536,18 +555,25 @@ BackupRestore::logEntry(const LogEntry & tup)
// Both insert update and delete can fail during log running // Both insert update and delete can fail during log running
// and it's ok // and it's ok
// TODO: check that the error is either tuple exists or tuple does not exist? // TODO: check that the error is either tuple exists or tuple does not exist?
bool ok= false;
NdbError errobj= trans->getNdbError();
switch(tup.m_type) switch(tup.m_type)
{ {
case LogEntry::LE_INSERT: case LogEntry::LE_INSERT:
if(errobj.status == NdbError::PermanentError &&
errobj.classification == NdbError::ConstraintViolation)
ok= true;
break; break;
case LogEntry::LE_UPDATE: case LogEntry::LE_UPDATE:
break;
case LogEntry::LE_DELETE: case LogEntry::LE_DELETE:
if(errobj.status == NdbError::PermanentError &&
errobj.classification == NdbError::NoDataFound)
ok= true;
break; break;
} }
if (false) if (!ok)
{ {
err << "execute failed: " << trans->getNdbError() << endl; err << "execute failed: " << errobj << endl;
exit(-1); exit(-1);
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment