List:Commits« Previous MessageNext Message »
From:Leonard Zhou Date:October 10 2008 6:38pm
Subject:bzr commit into mysql-5.1 branch (leonard:2707) WL#4397
View as plain text  
#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#4397Leonard Zhou10 Oct