#At file:///home/zhl/mysql/wl4397/
2707 Leonard Zhou 2008-10-10
only for temp use
modified:
storage/ndb/include/kernel/signaldata/BackupImpl.hpp
storage/ndb/include/kernel/signaldata/BackupSignalData.hpp
storage/ndb/include/mgmapi/mgmapi.h
storage/ndb/src/kernel/blocks/backup/Backup.cpp
storage/ndb/src/kernel/blocks/backup/Backup.hpp
storage/ndb/src/kernel/blocks/backup/BackupFormat.hpp
storage/ndb/src/mgmapi/mgmapi.cpp
storage/ndb/src/mgmclient/CommandInterpreter.cpp
storage/ndb/src/mgmsrv/MgmtSrvr.cpp
storage/ndb/src/mgmsrv/MgmtSrvr.hpp
storage/ndb/src/mgmsrv/Services.cpp
storage/ndb/tools/restore/Restore.cpp
storage/ndb/tools/restore/Restore.hpp
storage/ndb/tools/restore/restore_main.cpp
=== modified file 'storage/ndb/include/kernel/signaldata/BackupImpl.hpp'
--- a/storage/ndb/include/kernel/signaldata/BackupImpl.hpp 2008-03-03 11:12:37 +0000
+++ b/storage/ndb/include/kernel/signaldata/BackupImpl.hpp 2008-10-10 18:37:07 +0000
@@ -33,7 +33,7 @@ class DefineBackupReq {
friend bool printDEFINE_BACKUP_REQ(FILE *, const Uint32 *, Uint32, Uint16);
public:
- STATIC_CONST( SignalLength = 9 + NdbNodeBitmask::Size);
+ STATIC_CONST( SignalLength = 10 + NdbNodeBitmask::Size);
private:
/**
@@ -67,6 +67,7 @@ private:
/* & 0x3 - waitCompleted
*/
Uint32 flags;
+ Uint32 logType;
};
class DefineBackupRef {
=== modified file 'storage/ndb/include/kernel/signaldata/BackupSignalData.hpp'
--- a/storage/ndb/include/kernel/signaldata/BackupSignalData.hpp 2008-03-03 11:12:37 +0000
+++ b/storage/ndb/include/kernel/signaldata/BackupSignalData.hpp 2008-10-10 18:37:07 +0000
@@ -35,7 +35,7 @@ class BackupReq {
friend bool printBACKUP_REQ(FILE *, const Uint32 *, Uint32, Uint16);
public:
- STATIC_CONST( SignalLength = 4 );
+ STATIC_CONST( SignalLength = 5 );
private:
Uint32 senderData;
@@ -44,6 +44,7 @@ private:
*/
Uint32 flags;
Uint32 inputBackupId;
+ Uint32 logType; //0: redo log file; 1: undo log file
};
class BackupData {
=== modified file 'storage/ndb/include/mgmapi/mgmapi.h'
--- a/storage/ndb/include/mgmapi/mgmapi.h 2008-08-07 03:45:20 +0000
+++ b/storage/ndb/include/mgmapi/mgmapi.h 2008-10-10 18:37:07 +0000
@@ -1027,6 +1027,7 @@ extern "C" {
* @param backup_id Backup ID is returned from function.
* @param reply Reply message.
* @param input_backupId run as backupId and set next backup id to input_backupId+1.
+ * @param logtype backup log type(redo/undo).
* @return -1 on error.
* @note backup_id will not be returned if
* wait_completed == 0
@@ -1034,7 +1035,8 @@ extern "C" {
int ndb_mgm_start_backup2(NdbMgmHandle handle, int wait_completed,
unsigned int* backup_id,
struct ndb_mgm_reply* reply,
- unsigned int input_backupId);
+ unsigned int input_backupId,
+ unsigned int logtype);
/**
* Abort backup
=== modified file 'storage/ndb/src/kernel/blocks/backup/Backup.cpp'
--- a/storage/ndb/src/kernel/blocks/backup/Backup.cpp 2008-09-30 07:40:45 +0000
+++ b/storage/ndb/src/kernel/blocks/backup/Backup.cpp 2008-10-10 18:37:07 +0000
@@ -1095,6 +1095,7 @@ Backup::execBACKUP_REQ(Signal* signal)
const Uint32 dataLen32 = req->backupDataLen; // In 32 bit words
const Uint32 flags = signal->getLength() > 2 ? req->flags : 2;
const Uint32 input_backupId = signal->getLength() > 3 ? req->inputBackupId : 0;
+ const Uint32 logtype = signal->getLength() > 4 ? req->logType : 0;
if(getOwnNodeId() != getMasterNodeId()) {
jam();
@@ -1139,10 +1140,11 @@ Backup::execBACKUP_REQ(Signal* signal)
ptr.p->flags = flags;
ptr.p->masterRef = reference();
ptr.p->nodes = c_aliveNodes;
- if(input_backupId)
- ptr.p->backupId = input_backupId;
+ ptr.p->backupId = input_backupId;
+ if(logtype == 1)
+ ptr.p->logType = BackupFormat::UNDO_FILE;
else
- ptr.p->backupId = 0;
+ ptr.p->logType = BackupFormat::LOG_FILE;
ptr.p->backupKey[0] = 0;
ptr.p->backupKey[1] = 0;
ptr.p->backupDataLen = 0;
@@ -1354,6 +1356,7 @@ Backup::sendDefineBackupReq(Signal *sign
req->nodes = ptr.p->nodes;
req->backupDataLen = ptr.p->backupDataLen;
req->flags = ptr.p->flags;
+ req->logType = ptr.p->logType;
ptr.p->masterData.gsn = GSN_DEFINE_BACKUP_REQ;
ptr.p->masterData.sendCounter = ptr.p->nodes;
@@ -2675,6 +2678,8 @@ Backup::execDEFINE_BACKUP_REQ(Signal* si
* as non master should never
* reply
*/
+
+ ptr.p->logType = signal->getLength() > 9 ? req->logType : BackupFormat::LOG_FILE;
ptr.p->masterRef = senderRef;
ptr.p->nodes = req->nodes;
ptr.p->backupId = backupId;
@@ -2781,7 +2786,7 @@ Backup::execDEFINE_BACKUP_REQ(Signal* si
ptr.p->ctlFilePtr = files[i].i;
break;
case 1:
- files[i].p->fileType = BackupFormat::LOG_FILE;
+ files[i].p->fileType = (BackupFormat::FileType)ptr.p->logType;
ptr.p->logFilePtr = files[i].i;
break;
case 2:
@@ -3068,7 +3073,7 @@ Backup::openFilesReply(Signal* signal,
}//if
ptr.p->files.getPtr(filePtr, ptr.p->logFilePtr);
- if(!insertFileHeader(BackupFormat::LOG_FILE, ptr.p, filePtr.p)) {
+ if(!insertFileHeader((BackupFormat::FileType)ptr.p->logType, ptr.p, filePtr.p)) {
jam();
defineBackupRef(signal, ptr, DefineBackupRef::FailedInsertFileHeader);
return;
@@ -4362,13 +4367,27 @@ Backup::execTRIG_ATTRINFO(Signal* signal
return;
}//if
- if(trg->getAttrInfoType() == TrigAttrInfo::BEFORE_VALUES) {
- jam();
- /**
- * Backup is doing REDO logging and don't need before values
- */
- return;
- }//if
+ BackupRecordPtr ptr LINT_SET_PTR;
+ c_backupPool.getPtr(ptr, trigPtr.p->backupPtr);
+
+ if(ptr.p->logType == BackupFormat::LOG_FILE) {
+ if(trg->getAttrInfoType() == TrigAttrInfo::BEFORE_VALUES) {
+ jam();
+ /**
+ * Backup is doing REDO logging and don't need before values
+ */
+ return;
+ }//if
+ }
+ else if(ptr.p->logType == BackupFormat::UNDO_FILE) {
+ if(trg->getAttrInfoType() == TrigAttrInfo::AFTER_VALUES) {
+ jam();
+ /**
+ * Backup is doing UNDO logging and don't need after values
+ */
+ return;
+ }//if
+ }
BackupFormat::LogFile::LogEntry * logEntry = trigPtr.p->logEntry;
if(logEntry == 0)
@@ -4462,8 +4481,16 @@ Backup::execFIRE_TRIG_ORD(Signal* signal
ptr.p->currGCP = gci;
}
+ Uint32 datalen = len;
len += (sizeof(BackupFormat::LogFile::LogEntry) >> 2) - 2;
trigPtr.p->logEntry->Length = htonl(len);
+ if(ptr.p->logType == BackupFormat::UNDO_FILE)
+ {
+ /* keep the length at both the end of logEntry and ->logEntry variable
+ The total length of logEntry is len + 2
+ */
+ trigPtr.p->logEntry->Data[datalen] = htonl(len);
+ }
ndbrequire(len + 1 <= trigPtr.p->operation->dataBuffer.getMaxWrite());
trigPtr.p->operation->dataBuffer.updateWritePtr(len + 1);
=== modified file 'storage/ndb/src/kernel/blocks/backup/Backup.hpp'
--- a/storage/ndb/src/kernel/blocks/backup/Backup.hpp 2008-03-27 17:20:50 +0000
+++ b/storage/ndb/src/kernel/blocks/backup/Backup.hpp 2008-10-10 18:37:07 +0000
@@ -437,6 +437,8 @@ public:
Uint32 backupDataLen; // Used for (un)packing backup request
SimpleProperties props;// Used for (un)packing backup request
+ Uint32 logType; // REDO,UNDO
+
struct SlaveData {
SignalCounter trigSendCounter;
Uint32 gsn;
=== modified file 'storage/ndb/src/kernel/blocks/backup/BackupFormat.hpp'
--- a/storage/ndb/src/kernel/blocks/backup/BackupFormat.hpp 2008-03-18 07:12:39 +0000
+++ b/storage/ndb/src/kernel/blocks/backup/BackupFormat.hpp 2008-10-10 18:37:07 +0000
@@ -71,7 +71,8 @@ struct BackupFormat {
CTL_FILE = 1,
LOG_FILE = 2,
DATA_FILE = 3,
- LCP_FILE = 4
+ LCP_FILE = 4,
+ UNDO_FILE = 5
};
/**
=== modified file 'storage/ndb/src/mgmapi/mgmapi.cpp'
--- a/storage/ndb/src/mgmapi/mgmapi.cpp 2008-08-21 22:14:40 +0000
+++ b/storage/ndb/src/mgmapi/mgmapi.cpp 2008-10-10 18:37:07 +0000
@@ -2085,7 +2085,8 @@ int
ndb_mgm_start_backup2(NdbMgmHandle handle, int wait_completed,
unsigned int* _backup_id,
struct ndb_mgm_reply*, /*reply*/
- unsigned int input_backupId)
+ unsigned int input_backupId,
+ unsigned int logtype)
{
SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_start_backup");
const ParserRow<ParserDummy> start_backup_reply[] = {
@@ -2099,8 +2100,8 @@ ndb_mgm_start_backup2(NdbMgmHandle handl
Properties args;
args.put("completed", wait_completed);
- if(input_backupId > 0)
- args.put("backupid", input_backupId);
+ args.put("backupid", input_backupId);
+ args.put("logtype", logtype);
const Properties *reply;
{ // start backup can take some time, set timeout high
Uint64 old_timeout= handle->timeout;
@@ -2133,7 +2134,7 @@ ndb_mgm_start_backup(NdbMgmHandle handle
struct ndb_mgm_reply* /*reply*/)
{
struct ndb_mgm_reply reply;
- return ndb_mgm_start_backup2(handle, wait_completed, _backup_id, &reply, 0);
+ return ndb_mgm_start_backup2(handle, wait_completed, _backup_id, &reply, 0, 0);
}
extern "C"
=== modified file 'storage/ndb/src/mgmclient/CommandInterpreter.cpp'
--- a/storage/ndb/src/mgmclient/CommandInterpreter.cpp 2008-03-14 13:34:05 +0000
+++ b/storage/ndb/src/mgmclient/CommandInterpreter.cpp 2008-10-10 18:37:07 +0000
@@ -264,8 +264,8 @@ static const char* helpText =
"SHOW CONFIG Print configuration\n"
"SHOW PARAMETERS Print configuration parameters\n"
#endif
-"START BACKUP [<backup id>] [NOWAIT | WAIT STARTED | WAIT COMPLETED]\n"
-" Start backup (default WAIT COMPLETED)\n"
+"START BACKUP [<backup id>] [REDO | UNDO] [NOWAIT | WAIT STARTED | WAIT COMPLETED]\n"
+" Start backup (default WAIT COMPLETED,REDO)\n"
"ABORT BACKUP <backup id> Abort backup\n"
"SHUTDOWN Shutdown all processes in cluster\n"
"CLUSTERLOG ON [<severity>] ... Enable Cluster logging\n"
@@ -329,7 +329,7 @@ static const char* helpTextStartBackup =
" NDB Cluster -- Management Client -- Help for START BACKUP command\n"
"---------------------------------------------------------------------------\n"
"START BACKUP Start a cluster backup\n\n"
-"START BACKUP [<backup id>] [NOWAIT | WAIT STARTED | WAIT COMPLETED]\n"
+"START BACKUP [<backup id>] [REDO | UNDO] [NOWAIT | WAIT STARTED | WAIT COMPLETED]\n"
" Start a backup for the cluster.\n"
" Each backup gets an ID number that is reported to the\n"
" user. This ID number can help you find the backup on the\n"
@@ -338,6 +338,10 @@ static const char* helpTextStartBackup =
" You can also start specified backup using START BACKUP <backup id> \n\n"
" <backup id> \n"
" Start a specified backup using <backup id> as bakcup ID number.\n"
+" REDO \n"
+" Write redo log to backup log file.\n"
+" UNDO \n"
+" Write undo log to backup log file.\n"
" NOWAIT \n"
" Start a cluster backup and return immediately.\n"
" The management client will return control directly\n"
@@ -2832,51 +2836,95 @@ CommandInterpreter::executeStartBackup(c
int result;
int flags = 2;
- if (sz == 2 && args[1] == "NOWAIT")
- {
- flags = 0;
- }
- else if (sz == 1 || (sz == 3 && args[1] == "WAIT" && args[2] == "COMPLETED"))
- {
- flags = 2;
- ndbout_c("Waiting for completed, this may take several minutes");
- }
- else if (sz == 3 && args[1] == "WAIT" && args[2] == "STARTED")
- {
- ndbout_c("Waiting for started, this may take several minutes");
- flags = 1;
- }
- else if (sscanf(args[1].c_str(), "%u", &input_backupId) == 1 && input_backupId > 0 && input_backupId < MAX_BACKUPS)
+ unsigned int logtype = 0;
+ bool b_log = false;
+ bool b_nowait = false;
+ bool b_wait_completed = false;
+ bool b_wait_started = false;
+
+ /*
+ All the commands list as follow:
+ start backup <backupid> nowait | start backup <backupid> redo/undo nowati | start backup <backupid> nowait redo/undo
+ start backup <backupid> | start backup <backupid> wait completed | start backup <backupid> redo/undo
+ start backup <backupid> redo/undo wait completed | start backup <backupid> wait completed redo/undo
+ start backup <backupid> wait started | start backup <backupid> redo/undo wait started
+ start backup <backupid> wait started redo/undo
+ */
+ for (int i= 1; i < sz; i++)
{
- // start backup n nowait
- if (sz == 3 && args[2] == "NOWAIT")
- {
- flags = 0;
+ if (i == 1 && sscanf(args[1].c_str(), "%u", &input_backupId) == 1) {
+ if (input_backupId > 0 && input_backupId < MAX_BACKUPS)
+ continue;
+ else {
+ invalid_command(parameters);
+ return -1;
+ }
}
- // start backup n; start backup n wait complete
- else if ( sz == 2 || (sz == 4 && args[2] == "WAIT" && args[3] =="COMPLETED"))
- {
- flags = 2;
- ndbout_c("Waiting for completed, this may take several minutes");
+
+ if (args[i] == "REDO") {
+ if (b_log ==true) {
+ invalid_command(parameters);
+ return -1;
+ }
+ b_log = true;
+ logtype = 0;
+ continue;
}
- //start backup n wait started
- else if (sz == 4 && args[2] == "WAIT" && args[3] == "STARTED")
- {
- ndbout_c("Waiting for started, this may take several minutes");
- flags = 1;
+ if (args[i] == "UNDO") {
+ if (b_log ==true) {
+ invalid_command(parameters);
+ return -1;
+ }
+ b_log = true;
+ logtype = 1;
+ continue;
}
- else
- {
- invalid_command(parameters);
- return -1;
+ if (args[i] == "NOWAIT") {
+ if (b_nowait == true || b_wait_completed == true || b_wait_started ==true) {
+ invalid_command(parameters);
+ return -1;
+ }
+ b_nowait == true;
+ flags = 0;
+ continue;
+ }
+ if (args[i] == "WAIT") {
+ if (b_nowait == true || b_wait_completed == true || b_wait_started ==true) {
+ invalid_command(parameters);
+ return -1;
+ }
+ if (i+1 < sz) {
+ if (args[i+1] == "COMPLETED") {
+ b_wait_completed == true;
+ flags = 2;
+ i++;
+ }
+ else if (args[i+1] == "STARTED") {
+ b_wait_started == true;
+ flags = 1;
+ i++;
+ }
+ else {
+ invalid_command(parameters);
+ return -1;
+ }
+ }
+ else {
+ invalid_command(parameters);
+ return -1;
+ }
+ continue;
}
- }
- else
- {
invalid_command(parameters);
return -1;
}
+ //print message
+ if (b_wait_completed)
+ ndbout_c("Waiting for completed, this may take several minutes");
+ if (b_wait_started)
+ ndbout_c("Waiting for started, this may take several minutes");
+
NdbLogEventHandle log_handle= NULL;
struct ndb_logevent log_event;
if (flags == 2 && !interactive)
@@ -2890,8 +2938,14 @@ CommandInterpreter::executeStartBackup(c
return -1;
}
}
+
+ //start backup N | start backup redo/undo
if (input_backupId > 0)
- result = ndb_mgm_start_backup2(m_mgmsrv, flags, &backupId, &reply, input_backupId);
+ result = ndb_mgm_start_backup2(m_mgmsrv, flags, &backupId, &reply, input_backupId, logtype);
+ //start backup redo/undo
+ else if(b_log == true)
+ result = ndb_mgm_start_backup2(m_mgmsrv, flags, &backupId, &reply, 0, logtype);
+ //start backup
else
result = ndb_mgm_start_backup(m_mgmsrv, flags, &backupId, &reply);
=== modified file 'storage/ndb/src/mgmsrv/MgmtSrvr.cpp'
--- a/storage/ndb/src/mgmsrv/MgmtSrvr.cpp 2008-09-02 09:28:24 +0000
+++ b/storage/ndb/src/mgmsrv/MgmtSrvr.cpp 2008-10-10 18:37:07 +0000
@@ -2585,7 +2585,7 @@ MgmtSrvr::eventReport(const Uint32 * the
***************************************************************************/
int
-MgmtSrvr::startBackup(Uint32& backupId, int waitCompleted, Uint32 input_backupId)
+MgmtSrvr::startBackup(Uint32& backupId, int waitCompleted, Uint32 input_backupId, Uint32 logtype)
{
SignalSender ss(theFacade);
ss.lock(); // lock will be released on exit
@@ -2603,16 +2603,11 @@ MgmtSrvr::startBackup(Uint32& backupId,
SimpleSignal ssig;
BackupReq* req = CAST_PTR(BackupReq, ssig.getDataPtrSend());
- if(input_backupId > 0)
- {
- ssig.set(ss, TestOrd::TraceAPI, BACKUP, GSN_BACKUP_REQ,
- BackupReq::SignalLength);
- req->inputBackupId = input_backupId;
- }
- else
- ssig.set(ss, TestOrd::TraceAPI, BACKUP, GSN_BACKUP_REQ,
- BackupReq::SignalLength - 1);
+ ssig.set(ss, TestOrd::TraceAPI, BACKUP, GSN_BACKUP_REQ,
+ BackupReq::SignalLength);
+ req->inputBackupId = input_backupId;
+ req->logType = logtype;
req->senderData = 19;
req->backupDataLen = 0;
assert(waitCompleted < 3);
=== modified file 'storage/ndb/src/mgmsrv/MgmtSrvr.hpp'
--- a/storage/ndb/src/mgmsrv/MgmtSrvr.hpp 2008-03-14 13:34:05 +0000
+++ b/storage/ndb/src/mgmsrv/MgmtSrvr.hpp 2008-10-10 18:37:07 +0000
@@ -309,7 +309,7 @@ public:
/**
* Backup functionallity
*/
- int startBackup(Uint32& backupId, int waitCompleted= 2, Uint32 input_backupId= 0);
+ int startBackup(Uint32& backupId, int waitCompleted= 2, Uint32 input_backupId= 0, Uint32 logtype= 0);
int abortBackup(Uint32 backupId);
int performBackup(Uint32* backupId);
=== modified file 'storage/ndb/src/mgmsrv/Services.cpp'
--- a/storage/ndb/src/mgmsrv/Services.cpp 2008-08-05 12:15:56 +0000
+++ b/storage/ndb/src/mgmsrv/Services.cpp 2008-10-10 18:37:07 +0000
@@ -191,6 +191,7 @@ ParserRow<MgmApiSession> commands[] = {
MGM_CMD("start backup", &MgmApiSession::startBackup, ""),
MGM_ARG("completed", Int, Optional ,"Wait until completed"),
MGM_ARG("backupid", Int, Optional ,"User input backup id"),
+ MGM_ARG("logtype", Int, Optional ,"backup log type"),
MGM_CMD("abort backup", &MgmApiSession::abortBackup, ""),
MGM_ARG("id", Int, Mandatory, "Backup id"),
@@ -700,19 +701,19 @@ MgmApiSession::startBackup(Parser<MgmApi
Properties const &args) {
DBUG_ENTER("MgmApiSession::startBackup");
unsigned backupId;
- unsigned input_backupId;
+ unsigned input_backupId= 0;
+ unsigned logtype= 0;
Uint32 completed= 2;
int result;
args.get("completed", &completed);
if(args.contains("backupid"))
- {
args.get("backupid", &input_backupId);
- result = m_mgmsrv.startBackup(backupId, completed, input_backupId);
- }
- else
- result = m_mgmsrv.startBackup(backupId, completed);
+ if(args.contains("logtype"))
+ args.get("logtype", &logtype);
+
+ result = m_mgmsrv.startBackup(backupId, completed, input_backupId, logtype);
m_output->println("start backup reply");
if(result != 0)
=== modified file 'storage/ndb/tools/restore/Restore.cpp'
--- a/storage/ndb/tools/restore/Restore.cpp 2008-09-19 06:45:00 +0000
+++ b/storage/ndb/tools/restore/Restore.cpp 2008-10-10 18:37:07 +0000
@@ -1106,6 +1106,7 @@ BackupFile::BackupFile(void (* _free_dat
m_file_size = 0;
m_file_pos = 0;
+ m_is_undolog = false;
}
BackupFile::~BackupFile(){
@@ -1161,13 +1162,54 @@ Uint32 BackupFile::buffer_get_ptr_ahead(
reset_buffers();
memcpy(m_buffer, m_buffer_ptr, m_buffer_data_left);
- int error;
- size_t r = azread(&m_file,
- ((char *)m_buffer) + m_buffer_data_left,
- m_buffer_sz - m_buffer_data_left, &error);
- m_file_pos += r;
- m_buffer_data_left += r;
- m_buffer_ptr = m_buffer;
+ if (m_is_undolog)
+ {
+ size_t r = 0;
+ int error;
+ // if have read all the entries. ftell(m_file) equal to m_file_pos
+ if (m_file_pos > sizeof(m_fileHeader))
+ {
+ if (m_file_pos - sizeof(m_fileHeader) <= m_buffer_sz - m_buffer_data_left)
+ {
+ //move to the start of data part
+ azseek(&m_file, sizeof(m_fileHeader), SEEK_SET);
+ r = azread(&m_file, ((char *)m_buffer) + m_buffer_data_left, m_file_pos - sizeof(m_fileHeader), &error);
+ azseek(&m_file, sizeof(m_fileHeader), SEEK_SET);
+ }
+ else
+ {
+ azseek(&m_file, -(m_buffer_sz - m_buffer_data_left), SEEK_CUR);
+ r = azread(&m_file, ((char *)m_buffer) + m_buffer_data_left, m_buffer_sz - m_buffer_data_left, &error);
+ azseek(&m_file, -(m_buffer_sz - m_buffer_data_left), SEEK_CUR);
+ }
+ /* reversal the new data
+ eg: before -- 123 456789
+ after -- 123 987654
+ */
+ char * copy_ptr;
+ char tmp;
+ copy_ptr = (char *)m_buffer + m_buffer_data_left;
+ for (int i = 0; i < r/2; i++ )
+ {
+ tmp = copy_ptr[i];
+ copy_ptr[i] = copy_ptr[r-i-1];
+ copy_ptr[r-i-1] = tmp;
+ }
+ }
+ m_file_pos -= r;
+ m_buffer_data_left += r;
+ m_buffer_ptr = m_buffer;
+ }
+ else
+ {
+ int error;
+ size_t r = azread(&m_file,
+ ((char *)m_buffer) + m_buffer_data_left,
+ m_buffer_sz - m_buffer_data_left, &error);
+ m_file_pos += r;
+ m_buffer_data_left += r;
+ m_buffer_ptr = m_buffer;
+ }
if (sz > m_buffer_data_left)
sz = size * (m_buffer_data_left / size);
@@ -1317,7 +1359,22 @@ BackupFile::readHeader(){
debug << "magicByteOrder is " << magicByteOrder << endl;
if (m_fileHeader.FileType != m_expectedFileHeader.FileType){
- abort();
+ if((m_expectedFileHeader.FileType == BackupFormat::LOG_FILE) &&
+ (m_fileHeader.FileType == BackupFormat::UNDO_FILE)){
+ m_is_undolog = true;
+ /* move pointer to end of data part.
+ move 4 bytes from the end of file
+ because footer contain 4 bytes 0 at the end of file.
+ we discard the remain data stored in m_buffer.
+ */
+ azseek(&m_file, 4, SEEK_END);
+ m_file_pos = m_file_size - 4;
+ m_buffer_data_left = 0;
+ m_buffer = m_buffer_ptr;
+ }
+ else {
+ abort();
+ }
}
// Check for BackupFormat::FileHeader::ByteOrder if swapping is needed
@@ -1529,6 +1586,140 @@ RestoreLogIterator::RestoreLogIterator(c
m_last_gci = 0;
}
+// compatible with redo log
+const LogEntry *
+RestoreLogIterator::getLogEntry(int & res) {
+ if (m_is_undolog) {
+ return getPreviousLogEntry(res= 0);
+ }
+ else {
+ return getNextLogEntry(res= 0);
+ }
+}
+
+const LogEntry *
+RestoreLogIterator::getPreviousLogEntry(int & res) {
+ // Read record length
+ const Uint32 stopGCP = m_metaData.getStopGCP();
+ Uint32 tableId;
+ Uint32 triggerEvent;
+ Uint32 frag_id;
+ Uint32 *attr_data;
+ Uint32 attr_data_len;
+ do {
+ Uint32 len;
+ Uint32 *logEntryPtr;
+ if (buffer_read(&len, sizeof(Uint32), 1) != 1){
+ res= -1;
+ return 0;
+ }
+ len= ntohl(len);
+
+ Uint32 data_len = sizeof(Uint32) + len*4;
+ if (buffer_get_ptr((void **)(&logEntryPtr), 1, data_len) != data_len) {
+ res= -2;
+ return 0;
+ }
+
+ if(len == 0){
+ res= 0;
+ return 0;
+ }
+
+ if (unlikely(m_metaData.getFileHeader().NdbVersion < NDBD_FRAGID_VERSION))
+ {
+ /*
+ FragId was introduced in LogEntry in version
+ 5.1.6
+ We set FragId to 0 in older versions (these versions
+ do not support restore of user defined partitioned
+ tables.
+ */
+ typedef BackupFormat::LogFile::LogEntry_no_fragid LogE_no_fragid;
+ LogE_no_fragid * logE_no_fragid= (LogE_no_fragid *)logEntryPtr;
+ tableId= ntohl(logE_no_fragid->TableId);
+ triggerEvent= ntohl(logE_no_fragid->TriggerEvent);
+ frag_id= 0;
+ attr_data= &logE_no_fragid->Data[0];
+ attr_data_len= len - ((offsetof(LogE_no_fragid, Data) >> 2) - 1);
+ }
+ else /* normal case */
+ {
+ typedef BackupFormat::LogFile::LogEntry LogE;
+ LogE * logE= (LogE *)logEntryPtr;
+ tableId= ntohl(logE->TableId);
+ triggerEvent= ntohl(logE->TriggerEvent);
+ frag_id= ntohl(logE->FragId);
+ attr_data= &logE->Data[0];
+ attr_data_len= len - ((offsetof(LogE, Data) >> 2) - 1);
+ }
+
+ const bool hasGcp= (triggerEvent & 0x10000) != 0;
+ triggerEvent &= 0xFFFF;
+
+ if(hasGcp){
+ // last attr_data is gci info
+ attr_data_len--;
+ m_last_gci = ntohl(*(attr_data + attr_data_len));
+ }
+ } while(m_last_gci > stopGCP + 1);
+
+ m_logEntry.m_table = m_metaData.getTable(tableId);
+ switch(triggerEvent){
+ case TriggerEvent::TE_INSERT:
+ m_logEntry.m_type = LogEntry::LE_INSERT;
+ break;
+ case TriggerEvent::TE_UPDATE:
+ m_logEntry.m_type = LogEntry::LE_UPDATE;
+ break;
+ case TriggerEvent::TE_DELETE:
+ m_logEntry.m_type = LogEntry::LE_DELETE;
+ break;
+ default:
+ res = -1;
+ return NULL;
+ }
+
+ const TableS * tab = m_logEntry.m_table;
+ m_logEntry.clear();
+
+ AttributeHeader * ah = (AttributeHeader *)attr_data;
+ AttributeHeader *end = (AttributeHeader *)(attr_data + attr_data_len);
+ AttributeS * attr;
+ m_logEntry.m_frag_id = frag_id;
+ while(ah < end){
+ attr= m_logEntry.add_attr();
+ if(attr == NULL) {
+ ndbout_c("Restore: Failed to allocate memory");
+ res = -1;
+ return 0;
+ }
+
+ if(unlikely(!m_hostByteOrder))
+ *(Uint32*)ah = Twiddle32(*(Uint32*)ah);
+
+ attr->Desc = (* tab)[ah->getAttributeId()];
+ assert(attr->Desc != 0);
+
+ const Uint32 sz = ah->getDataSize();
+ if(sz == 0){
+ attr->Data.null = true;
+ attr->Data.void_value = NULL;
+ } else {
+ attr->Data.null = false;
+ attr->Data.void_value = ah->getDataPtr();
+ }
+
+ Twiddle(attr->Desc, &(attr->Data));
+
+ ah = ah->getNext();
+ }
+
+ m_count ++;
+ res = 0;
+ return &m_logEntry;
+}
+
const LogEntry *
RestoreLogIterator::getNextLogEntry(int & res) {
// Read record length
=== modified file 'storage/ndb/tools/restore/Restore.hpp'
--- a/storage/ndb/tools/restore/Restore.hpp 2008-09-19 06:45:00 +0000
+++ b/storage/ndb/tools/restore/Restore.hpp 2008-10-10 18:37:07 +0000
@@ -298,6 +298,8 @@ protected:
Uint64 m_file_size;
Uint64 m_file_pos;
+ bool m_is_undolog;
+
void (* free_data_callback)();
virtual void reset_buffers() {}
@@ -465,11 +467,14 @@ private:
Uint32 m_count;
Uint32 m_last_gci;
LogEntry m_logEntry;
+// bool m_is_undolog;
public:
RestoreLogIterator(const RestoreMetaData &);
virtual ~RestoreLogIterator() {};
+ const LogEntry * getLogEntry(int & res);
const LogEntry * getNextLogEntry(int & res);
+ const LogEntry * getPreviousLogEntry(int & res);
};
NdbOut& operator<<(NdbOut& ndbout, const TableS&);
=== modified file 'storage/ndb/tools/restore/restore_main.cpp'
--- a/storage/ndb/tools/restore/restore_main.cpp 2008-09-19 06:45:00 +0000
+++ b/storage/ndb/tools/restore/restore_main.cpp 2008-10-10 18:37:07 +0000
@@ -1032,7 +1032,8 @@ main(int argc, char** argv)
}
const LogEntry * logEntry = 0;
- while ((logEntry = logIter.getNextLogEntry(res= 0)) != 0)
+// while ((logEntry = logIter.getNextLogEntry(res= 0)) != 0)
+ while ((logEntry = logIter.getLogEntry(res= 0)) != 0)
{
const TableS* table = logEntry->m_table;
OutputStream *output = table_output[table->getLocalId()];
| Thread |
|---|
| • bzr commit into mysql-5.1 branch (leonard:2707) WL#4397 | Leonard Zhou | 10 Oct |