VXIlogResult OSBlog::WriteEntry(const LogEntry &entry, bool logToStdout) { if (((! gblLogFile) && (! gblLogToStdout)) || (entry.size() < 1)) return VXIlog_RESULT_SUCCESS; // Convert to narrow characters unsigned int i; unsigned int n = entry.size(); const wchar_t *ptr = entry.Entry(); char outbuf[MAX_LOG_BUFFER]; for(i=0; i<n; i++) outbuf[i] = w2c(ptr[i]); outbuf[i] = '\0'; // Lock and write out the log entry if (VXItrdMutexLock(gblLogMutex) != VXItrd_RESULT_SUCCESS) return VXIlog_RESULT_SYSTEM_ERROR; VXIlogResult rc = VXIlog_RESULT_SUCCESS; if (gblLogFile) { if (fwrite(outbuf, sizeof(char), n, gblLogFile) < 1) { // should disable logging. rc = VXIlog_RESULT_IO_ERROR; } else { // to ensure we don't lose log lines on a crash/abort fflush(gblLogFile); } } if (gblLogToStdout && logToStdout && (fwrite(outbuf, sizeof(char), n, stdout) < 1 || fflush(stdout) != 0)) rc = VXIlog_RESULT_IO_ERROR; if (VXItrdMutexUnlock(gblLogMutex) != VXItrd_RESULT_SUCCESS) rc = VXIlog_RESULT_SYSTEM_ERROR; return rc; }
void BackupRestore::logEntry(const LogEntry & tup) { if (!m_restore) return; NdbTransaction * trans = m_ndb->startTransaction(); if (trans == NULL) { // Deep shit, TODO: handle the error err << "Cannot start transaction" << endl; exitHandler(); } // if const NdbDictionary::Table * table = get_table(tup.m_table->m_dictTable); NdbOperation * op = trans->getNdbOperation(table); if (op == NULL) { err << "Cannot get operation: " << trans->getNdbError() << endl; exitHandler(); } // if int check = 0; switch(tup.m_type) { case LogEntry::LE_INSERT: check = op->insertTuple(); break; case LogEntry::LE_UPDATE: check = op->updateTuple(); break; case LogEntry::LE_DELETE: check = op->deleteTuple(); break; default: err << "Log entry has wrong operation type." << " Exiting..."; exitHandler(); } if (check != 0) { err << "Error defining op: " << trans->getNdbError() << endl; exitHandler(); } // if Bitmask<4096> keys; for (Uint32 i= 0; i < tup.size(); i++) { const AttributeS * attr = tup[i]; int size = attr->Desc->size; int arraySize = attr->Desc->arraySize; const char * dataPtr = attr->Data.string_value; if (tup.m_table->have_auto_inc(attr->Desc->attrId)) tup.m_table->update_max_auto_val(dataPtr,size*arraySize); const Uint32 length = (size / 8) * arraySize; if (attr->Desc->m_column->getPrimaryKey()) { if(!keys.get(attr->Desc->attrId)) { keys.set(attr->Desc->attrId); check= op->equal(attr->Desc->attrId, dataPtr, length); } } else check= op->setValue(attr->Desc->attrId, dataPtr, length); if (check != 0) { err << "Error defining op: " << trans->getNdbError() << endl; exitHandler(); } // if } const int ret = trans->execute(NdbTransaction::Commit); if (ret != 0) { // Both insert update and delete can fail during log running // and it's ok // 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) { case LogEntry::LE_INSERT: if(errobj.status == NdbError::PermanentError && errobj.classification == NdbError::ConstraintViolation) ok= true; break; case LogEntry::LE_UPDATE: case LogEntry::LE_DELETE: if(errobj.status == NdbError::PermanentError && errobj.classification == NdbError::NoDataFound) ok= true; break; } if (!ok) { err << "execute failed: " << errobj << endl; exitHandler(); } } m_ndb->closeTransaction(trans); m_logCount++; }