List:Commits« Previous MessageNext Message »
From:Jonas Oreland Date:September 18 2008 6:56am
Subject:bzr commit into mysql-5.1 branch (jonas:2764)
View as plain text  
#At file:///home/jonas/src/telco-6.4/

 2764 Jonas Oreland	2008-09-18 [merge]
      merge
added:
  storage/ndb/src/mgmsrv/testConfig.cpp
modified:
  storage/ndb/src/common/debugger/signaldata/AlterTab.cpp
  storage/ndb/src/kernel/blocks/backup/Backup.cpp
  storage/ndb/src/kernel/blocks/backup/Backup.hpp
  storage/ndb/src/kernel/blocks/dblqh/DblqhProxy.cpp
  storage/ndb/src/kernel/blocks/dblqh/DblqhProxy.hpp
  storage/ndb/src/kernel/blocks/dbtup/DbtupBuffer.cpp
  storage/ndb/src/kernel/vm/mt.cpp
  storage/ndb/src/mgmsrv/Config.cpp
  storage/ndb/src/mgmsrv/Config.hpp
  storage/ndb/src/mgmsrv/ConfigInfo.cpp
  storage/ndb/src/mgmsrv/Makefile.am
  storage/ndb/src/mgmsrv/MgmtSrvr.cpp

=== modified file 'storage/ndb/src/common/debugger/signaldata/AlterTab.cpp'
--- a/storage/ndb/src/common/debugger/signaldata/AlterTab.cpp	2007-12-25 16:15:08 +0000
+++ b/storage/ndb/src/common/debugger/signaldata/AlterTab.cpp	2008-09-16 18:33:52 +0000
@@ -29,10 +29,10 @@ printALTER_TAB_REQ(FILE* output, const U
   fprintf(output, " gci: %u", sig->gci);
   fprintf(output, " changeMask: 0x%x", sig->changeMask);
   fprintf(output, "\n");
-  fprintf(output, "connectPtr: %u", sig->connectPtr);
-  fprintf(output, "noOfNewAttr: %u", sig->noOfNewAttr);
-  fprintf(output, "newNoOfCharsets: %u", sig->newNoOfCharsets);
-  fprintf(output, "newNoOfKeyAttrs: %u", sig->newNoOfKeyAttrs);
+  fprintf(output, " connectPtr: %u", sig->connectPtr);
+  fprintf(output, " noOfNewAttr: %u", sig->noOfNewAttr);
+  fprintf(output, " newNoOfCharsets: %u", sig->newNoOfCharsets);
+  fprintf(output, " newNoOfKeyAttrs: %u", sig->newNoOfKeyAttrs);
   fprintf(output, "\n");
   return true;
 }
@@ -43,7 +43,7 @@ printALTER_TAB_CONF(FILE* output, const 
   const AlterTabConf* sig = (const AlterTabConf*)theData;
   fprintf(output, " senderRef: 0x%x", sig->senderRef);
   fprintf(output, " senderData: %u", sig->senderData);
-  fprintf(output, "connectPtr: %u", sig->connectPtr);
+  fprintf(output, " connectPtr: %u", sig->connectPtr);
   fprintf(output, "\n");
   return true;
 }

=== modified file 'storage/ndb/src/kernel/blocks/backup/Backup.cpp'
--- a/storage/ndb/src/kernel/blocks/backup/Backup.cpp	2008-09-12 12:55:29 +0000
+++ b/storage/ndb/src/kernel/blocks/backup/Backup.cpp	2008-09-16 18:29:47 +0000
@@ -250,7 +250,7 @@ Backup::execCONTINUEB(Signal* signal)
       Uint32 * dst;
       if (!filePtr.p->operation.dataBuffer.getWritePtr(&dst, sz))
       {
-	sendSignalWithDelay(BACKUP_REF, GSN_CONTINUEB, signal, 100, 4);
+	sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 100, 4);
 	return;
       }
       
@@ -288,7 +288,7 @@ Backup::execCONTINUEB(Signal* signal)
     signal->theData[1] = ptr_I;
     signal->theData[2] = tabPtr_I;
     signal->theData[3] = fragPtr_I;
-    sendSignal(BACKUP_REF, GSN_CONTINUEB, signal, 4, JBB);
+    sendSignal(reference(), GSN_CONTINUEB, signal, 4, JBB);
     return;
   }
   case BackupContinueB::START_FILE_THREAD:
@@ -365,7 +365,7 @@ Backup::execCONTINUEB(Signal* signal)
     if (ERROR_INSERTED(10039))
     {
       jam();
-      sendSignalWithDelay(BACKUP_REF, GSN_CONTINUEB, signal, 300, 
+      sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 300, 
 			  signal->getLength());
       return;
     }
@@ -374,9 +374,29 @@ Backup::execCONTINUEB(Signal* signal)
       jam();
       CLEAR_ERROR_INSERT_VALUE;
       ndbout_c("Resuming backup");
-      memmove(signal->theData, signal->theData + 1, 
+
+      Uint32 filePtr_I = Tdata1;
+      BackupFilePtr filePtr;
+      c_backupFilePool.getPtr(filePtr, filePtr_I);
+      BackupRecordPtr ptr;
+      c_backupPool.getPtr(ptr, filePtr.p->backupPtr);
+      TablePtr tabPtr;
+      findTable(ptr, tabPtr, filePtr.p->tableId);
+      FragmentPtr fragPtr;
+      tabPtr.p->fragments.getPtr(fragPtr, filePtr.p->fragmentNo);
+
+      BlockReference lqhRef = 0;
+      if (ptr.p->is_lcp()) {
+        lqhRef = calcInstanceBlockRef(DBLQH);
+      } else {
+        const Uint32 instanceKey = fragPtr.p->lqhInstanceKey;
+        ndbrequire(instanceKey != 0);
+        lqhRef = numberToRef(DBLQH, instanceKey, getOwnNodeId());
+      }
+
+      memmove(signal->theData, signal->theData + 2, 
 	      4*ScanFragNextReq::SignalLength);
-      BlockReference lqhRef = calcInstanceBlockRef(DBLQH);
+
       sendSignal(lqhRef, GSN_SCAN_NEXTREQ, signal, 
 		 ScanFragNextReq::SignalLength, JBB);
       return ;
@@ -412,7 +432,7 @@ Backup::execBACKUP_LOCK_TAB_CONF(Signal 
     signal->theData[1] = ptr.i;
     signal->theData[2] = tabPtr.i;
     signal->theData[3] = 0;       // Start from first fragment of next table
-    sendSignal(BACKUP_REF, GSN_CONTINUEB, signal, 4, JBB);
+    sendSignal(reference(), GSN_CONTINUEB, signal, 4, JBB);
     return;
   }
   case BackupLockTab::GET_TABINFO_CONF:
@@ -496,7 +516,7 @@ Backup::execDUMP_STATE_ORD(Signal* signa
     BackupReq * req = (BackupReq*)signal->getDataPtrSend();
     req->senderData = 23;
     req->backupDataLen = 0;
-    sendSignal(BACKUP_REF, GSN_BACKUP_REQ,signal,BackupReq::SignalLength, JBB);
+    sendSignal(reference(), GSN_BACKUP_REQ,signal,BackupReq::SignalLength, JBB);
     startTime = NdbTick_CurrentMillisecond();
     return;
   }
@@ -1415,7 +1435,8 @@ Backup::sendDefineBackupReq(Signal *sign
   
   ptr.p->masterData.gsn = GSN_DEFINE_BACKUP_REQ;
   ptr.p->masterData.sendCounter = ptr.p->nodes;
-  NodeReceiverGroup rg(BACKUP, ptr.p->nodes);
+  BlockNumber backupBlockNo = numberToBlock(BACKUP, instance());
+  NodeReceiverGroup rg(backupBlockNo, ptr.p->nodes);
   sendSignal(rg, GSN_DEFINE_BACKUP_REQ, signal, 
 	     DefineBackupReq::SignalLength, JBB);
   
@@ -1774,7 +1795,8 @@ Backup::sendStartBackup(Signal* signal, 
    */
   ptr.p->masterData.gsn = GSN_START_BACKUP_REQ;
   ptr.p->masterData.sendCounter = ptr.p->nodes;
-  NodeReceiverGroup rg(BACKUP, ptr.p->nodes);
+  BlockNumber backupBlockNo = numberToBlock(BACKUP, instance());
+  NodeReceiverGroup rg(backupBlockNo, ptr.p->nodes);
   sendSignal(rg, GSN_START_BACKUP_REQ, signal,
 	     StartBackupReq::SignalLength, JBB);
 }
@@ -1977,7 +1999,7 @@ Backup::nextFragment(Signal* signal, Bac
 	req->count = 0;
 
 	ptr.p->masterData.sendCounter++;
-	const BlockReference ref = numberToRef(BACKUP, nodeId);
+	const BlockReference ref = numberToRef(BACKUP, instance(), nodeId);
 	sendSignal(ref, GSN_BACKUP_FRAGMENT_REQ, signal,
 		   BackupFragmentReq::SignalLength, JBB);
       }//if
@@ -2077,7 +2099,8 @@ Backup::execBACKUP_FRAGMENT_CONF(Signal*
       rep->noOfTableRowsHigh = (Uint32)(tabPtr.p->noOfRecords >> 32);
       rep->noOfFragmentRowsLow = (Uint32)(noOfRecords & 0xFFFFFFFF);
       rep->noOfFragmentRowsHigh = (Uint32)(noOfRecords >> 32);
-      NodeReceiverGroup rg(BACKUP, ptr.p->nodes);
+      BlockNumber backupBlockNo = numberToBlock(BACKUP, instance());
+      NodeReceiverGroup rg(backupBlockNo, ptr.p->nodes);
       sendSignal(rg, GSN_BACKUP_FRAGMENT_COMPLETE_REP, signal,
                  BackupFragmentCompleteRep::SignalLength, JBB);
     }
@@ -2248,7 +2271,7 @@ Backup::sendDropTrig(Signal* signal, Bac
 	  signal->theData[1] = ptr.i;
 	  signal->theData[2] = tabPtr.i;
 	  signal->theData[3] = 0;
-	  sendSignal(BACKUP_REF, GSN_CONTINUEB, signal, 4, JBB);
+	  sendSignal(reference(), GSN_CONTINUEB, signal, 4, JBB);
 	}
 	else
 	{
@@ -2387,7 +2410,8 @@ Backup::sendStopBackup(Signal* signal, B
 
   ptr.p->masterData.gsn = GSN_STOP_BACKUP_REQ;
   ptr.p->masterData.sendCounter = ptr.p->nodes;
-  NodeReceiverGroup rg(BACKUP, ptr.p->nodes);
+  BlockNumber backupBlockNo = numberToBlock(BACKUP, instance());
+  NodeReceiverGroup rg(backupBlockNo, ptr.p->nodes);
   sendSignal(rg, GSN_STOP_BACKUP_REQ, signal, 
 	     StopBackupReq::SignalLength, JBB);
 }
@@ -2577,7 +2601,8 @@ Backup::masterAbort(Signal* signal, Back
   ord->backupId = ptr.p->backupId;
   ord->backupPtr = ptr.i;
   ord->senderData= ptr.i;
-  NodeReceiverGroup rg(BACKUP, ptr.p->nodes);
+  BlockNumber backupBlockNo = numberToBlock(BACKUP, instance());
+  NodeReceiverGroup rg(backupBlockNo, ptr.p->nodes);
   
   switch(ptr.p->masterData.gsn){
   case GSN_DEFINE_BACKUP_REQ:
@@ -2628,7 +2653,7 @@ Backup::abort_scan(Signal * signal, Back
       if(fragPtr.p->scanning != 0 && ptr.p->nodes.get(nodeId)) {
         jam();
 	
-	const BlockReference ref = numberToRef(BACKUP, nodeId);
+	const BlockReference ref = calcInstanceBlockRef(BACKUP, nodeId);
 	sendSignal(ref, GSN_ABORT_BACKUP_ORD, signal,
 		   AbortBackupOrd::SignalLength, JBB);
 	
@@ -3184,7 +3209,7 @@ Backup::openFilesReply(Signal* signal, 
     
     signal->theData[0] = BackupContinueB::START_FILE_THREAD;
     signal->theData[1] = filePtr.i;
-    sendSignalWithDelay(BACKUP_REF, GSN_CONTINUEB, signal, 100, 2);
+    sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 100, 2);
   }
   else
   {
@@ -3581,6 +3606,7 @@ Backup::execDIH_SCAN_TAB_CONF(Signal* si
     fragPtr.p->scanning = 0;
     fragPtr.p->tableId = tableId;
     fragPtr.p->fragmentId = i;
+    fragPtr.p->lqhInstanceKey = 0;
     fragPtr.p->node = 0;
   }//for
   
@@ -3654,6 +3680,7 @@ Backup::execDIH_SCAN_GET_NODES_CONF(Sign
   const Uint32 nodeCount = conf->count;
   const Uint32 tableId = conf->tableId;
   const Uint32 fragNo = conf->fragId;
+  const Uint32 instanceKey = conf->instanceKey;
 
   ndbrequire(nodeCount > 0 && nodeCount <= MAX_REPLICAS);
   
@@ -3665,6 +3692,7 @@ Backup::execDIH_SCAN_GET_NODES_CONF(Sign
 
   FragmentPtr fragPtr;
   tabPtr.p->fragments.getPtr(fragPtr, fragNo);
+  fragPtr.p->lqhInstanceKey = instanceKey;
   
   fragPtr.p->node = conf->nodes[0];
 
@@ -3718,7 +3746,7 @@ Backup::execSTART_BACKUP_REQ(Signal* sig
       filePtr.p->m_flags |= BackupFile::BF_FILE_THREAD;
       signal->theData[0] = BackupContinueB::START_FILE_THREAD;
       signal->theData[1] = filePtr.i;
-      sendSignalWithDelay(BACKUP_REF, GSN_CONTINUEB, signal, 100, 2);
+      sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 100, 2);
     }//if
   }//for
 
@@ -3799,7 +3827,7 @@ Backup::execBACKUP_FRAGMENT_REQ(Signal* 
   if(!filePtr.p->operation.newFragment(tableId, fragPtr.p->fragmentId)) {
     jam();
     req->count = count + 1;
-    sendSignalWithDelay(BACKUP_REF, GSN_BACKUP_FRAGMENT_REQ, signal, 50,
+    sendSignalWithDelay(reference(), GSN_BACKUP_FRAGMENT_REQ, signal, 50,
 			signal->length());
     ptr.p->slaveState.setState(STARTED);
     return;
@@ -3846,7 +3874,14 @@ Backup::execBACKUP_FRAGMENT_REQ(Signal* 
     req->clientOpPtr= filePtr.i;
     req->batch_size_rows= parallelism;
     req->batch_size_bytes= 0;
-    BlockReference lqhRef = calcInstanceBlockRef(DBLQH);
+    BlockReference lqhRef = 0;
+    if (ptr.p->is_lcp()) {
+      lqhRef = calcInstanceBlockRef(DBLQH);
+    } else {
+      const Uint32 instanceKey = fragPtr.p->lqhInstanceKey;
+      ndbrequire(instanceKey != 0);
+      lqhRef = numberToRef(DBLQH, instanceKey, getOwnNodeId());
+    }
     sendSignal(lqhRef, GSN_SCAN_FRAGREQ, signal,
                ScanFragReq::SignalLength, JBB);
     
@@ -4105,7 +4140,7 @@ Backup::fragmentCompleted(Signal* signal
     jam();
     signal->theData[0] = BackupContinueB::BUFFER_FULL_FRAG_COMPLETE;
     signal->theData[1] = filePtr.i;
-    sendSignalWithDelay(BACKUP_REF, GSN_CONTINUEB, signal, 50, 2);
+    sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 50, 2);
     return;
   }//if
   
@@ -4157,7 +4192,21 @@ void
 Backup::checkScan(Signal* signal, BackupFilePtr filePtr)
 {  
   OperationRecord & op = filePtr.p->operation;
-  BlockReference lqhRef = calcInstanceBlockRef(DBLQH);
+  BlockReference lqhRef = 0;
+  {
+    BackupRecordPtr ptr LINT_SET_PTR;
+    c_backupPool.getPtr(ptr, filePtr.p->backupPtr);
+    if (ptr.p->is_lcp()) {
+      lqhRef = calcInstanceBlockRef(DBLQH);
+    } else {
+      TablePtr tabPtr;
+      ndbrequire(findTable(ptr, tabPtr, filePtr.p->tableId));
+      FragmentPtr fragPtr;
+      tabPtr.p->fragments.getPtr(fragPtr, filePtr.p->fragmentNo);
+      const Uint32 instanceKey = fragPtr.p->lqhInstanceKey;
+      lqhRef = numberToRef(DBLQH, instanceKey, getOwnNodeId());
+    }
+  }
 
   if(filePtr.p->errorCode != 0)
   {
@@ -4196,11 +4245,12 @@ Backup::checkScan(Signal* signal, Backup
 	       filePtr.p->tableId,
 	       filePtr.p->fragmentNo,
 	       filePtr.p->operation.noOfRecords);
-      memmove(signal->theData+1, signal->theData, 
+      memmove(signal->theData+2, signal->theData, 
 	      4*ScanFragNextReq::SignalLength);
       signal->theData[0] = BackupContinueB::ZDELAY_SCAN_NEXT;
-      sendSignalWithDelay(BACKUP_REF, GSN_CONTINUEB, signal, 
-			  300, 1+ScanFragNextReq::SignalLength);
+      signal->theData[1] = filePtr.i;
+      sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 
+			  300, 2+ScanFragNextReq::SignalLength);
       return;
     }
     if(ERROR_INSERTED(10032))
@@ -4240,7 +4290,7 @@ Backup::checkScan(Signal* signal, Backup
   
   signal->theData[0] = BackupContinueB::BUFFER_FULL_SCAN;
   signal->theData[1] = filePtr.i;
-  sendSignalWithDelay(BACKUP_REF, GSN_CONTINUEB, signal, 50, 2);
+  sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 50, 2);
 }
 
 void
@@ -4612,7 +4662,8 @@ Backup::sendAbortBackupOrd(Signal* signa
     const Uint32 nodeId = node.p->nodeId;
     if(node.p->alive && ptr.p->nodes.get(nodeId)) {
       jam();
-      sendSignal(numberToRef(BACKUP, nodeId), GSN_ABORT_BACKUP_ORD, signal, 
+      BlockReference ref = calcInstanceBlockRef(BACKUP, nodeId);
+      sendSignal(ref, GSN_ABORT_BACKUP_ORD, signal, 
 		 AbortBackupOrd::SignalLength, JBB);
     }//if
   }//for
@@ -4868,7 +4919,8 @@ Backup::execABORT_BACKUP_ORD(Signal* sig
 #ifdef DEBUG_ABORT
       ndbout_c("---- Forward to master nodeId = %u", getMasterNodeId());
 #endif
-      sendSignal(calcBackupBlockRef(getMasterNodeId()), GSN_ABORT_BACKUP_ORD, 
+      BlockReference ref = calcInstanceBlockRef(BACKUP, getMasterNodeId());
+      sendSignal(ref, GSN_ABORT_BACKUP_ORD, 
 		 signal, AbortBackupOrd::SignalLength, JBB);
       return;
     }

=== modified file 'storage/ndb/src/kernel/blocks/backup/Backup.hpp'
--- a/storage/ndb/src/kernel/blocks/backup/Backup.hpp	2008-07-26 05:13:40 +0000
+++ b/storage/ndb/src/kernel/blocks/backup/Backup.hpp	2008-09-16 18:29:47 +0000
@@ -180,6 +180,7 @@ public:
     Uint32 tableId;
     Uint16 node;
     Uint16 fragmentId;
+    Uint8 lqhInstanceKey;
     Uint8 scanned;  // 0 = not scanned x = scanned by node x
     Uint8 scanning; // 0 = not scanning x = scanning on node x
     Uint8 lcp_no;

=== modified file 'storage/ndb/src/kernel/blocks/dblqh/DblqhProxy.cpp'
--- a/storage/ndb/src/kernel/blocks/dblqh/DblqhProxy.cpp	2008-08-23 06:32:32 +0000
+++ b/storage/ndb/src/kernel/blocks/dblqh/DblqhProxy.cpp	2008-09-16 18:33:52 +0000
@@ -59,6 +59,11 @@ DblqhProxy::DblqhProxy(Block_context& ct
   addRecSignal(GSN_DROP_TAB_CONF, &DblqhProxy::execDROP_TAB_CONF);
   addRecSignal(GSN_DROP_TAB_REF, &DblqhProxy::execDROP_TAB_REF);
 
+  // GSN_ALTER_TAB_REQ
+  addRecSignal(GSN_ALTER_TAB_REQ, &DblqhProxy::execALTER_TAB_REQ);
+  addRecSignal(GSN_ALTER_TAB_CONF, &DblqhProxy::execALTER_TAB_CONF);
+  addRecSignal(GSN_ALTER_TAB_REF, &DblqhProxy::execALTER_TAB_REF);
+
   // GSN_START_RECREQ
   addRecSignal(GSN_START_RECREQ, &DblqhProxy::execSTART_RECREQ);
   addRecSignal(GSN_START_RECCONF, &DblqhProxy::execSTART_RECCONF);
@@ -726,13 +731,109 @@ DblqhProxy::sendDROP_TAB_CONF(Signal* si
     ref->senderData = ss.m_req.senderData;
     ref->tableId = ss.m_req.tableId;
     ref->errorCode = ss.m_error;
-    sendSignal(dictRef, GSN_DROP_TAB_CONF,
+    sendSignal(dictRef, GSN_DROP_TAB_REF,
                signal, DropTabConf::SignalLength, JBB);
   }
 
   ssRelease<Ss_DROP_TAB_REQ>(ssId);
 }
 
+// GSN_ALTER_TAB_REQ
+
+void
+DblqhProxy::execALTER_TAB_REQ(Signal* signal)
+{
+  const AlterTabReq* req = (const AlterTabReq*)signal->getDataPtr();
+  Uint32 ssId = getSsId(req);
+  Ss_ALTER_TAB_REQ& ss = ssSeize<Ss_ALTER_TAB_REQ>(ssId);
+  ss.m_req = *req;
+  ndbrequire(signal->getLength() == AlterTabReq::SignalLength);
+
+  {
+    SectionHandle handle(this, signal);
+    ss.m_sections = handle.m_cnt;
+    ndbrequire(ss.m_sections <= 1);
+    if (ss.m_sections >= 1) {
+      ss.m_sz0 = handle.m_ptr[0].p->m_sz;
+      ndbrequire(ss.m_sz0 <= ss.MaxSection0);
+      ::copy(ss.m_section0, handle.m_ptr[0]);
+    }
+    releaseSections(handle);
+  }
+
+  sendREQ(signal, ss);
+}
+
+void
+DblqhProxy::sendALTER_TAB_REQ(Signal* signal, Uint32 ssId)
+{
+  Ss_ALTER_TAB_REQ& ss = ssFind<Ss_ALTER_TAB_REQ>(ssId);
+
+  AlterTabReq* req = (AlterTabReq*)signal->getDataPtrSend();
+  *req = ss.m_req;
+  req->senderRef = reference();
+  req->senderData = ssId;
+  if (ss.m_sections == 0) {
+    jam();
+    sendSignal(workerRef(ss.m_worker), GSN_ALTER_TAB_REQ,
+               signal, AlterTabReq::SignalLength, JBB);
+  } else {
+    jam();
+    LinearSectionPtr ptr[3];
+    ptr[0].sz = ss.m_sz0;
+    ptr[0].p = ss.m_section0;
+    sendSignal(workerRef(ss.m_worker), GSN_ALTER_TAB_REQ,
+               signal, AlterTabReq::SignalLength, JBB, ptr, 1);
+  }
+}
+
+void
+DblqhProxy::execALTER_TAB_CONF(Signal* signal)
+{
+  const AlterTabConf* conf = (const AlterTabConf*)signal->getDataPtr();
+  Uint32 ssId = getSsId(conf);
+  Ss_ALTER_TAB_REQ& ss = ssFind<Ss_ALTER_TAB_REQ>(ssId);
+  recvCONF(signal, ss);
+}
+
+void
+DblqhProxy::execALTER_TAB_REF(Signal* signal)
+{
+  const AlterTabRef* ref = (const AlterTabRef*)signal->getDataPtr();
+  Uint32 ssId = getSsId(ref);
+  Ss_ALTER_TAB_REQ& ss = ssFind<Ss_ALTER_TAB_REQ>(ssId);
+  recvREF(signal, ss, ref->errorCode);
+}
+
+void
+DblqhProxy::sendALTER_TAB_CONF(Signal* signal, Uint32 ssId)
+{
+  Ss_ALTER_TAB_REQ& ss = ssFind<Ss_ALTER_TAB_REQ>(ssId);
+  BlockReference dictRef = ss.m_req.senderRef;
+
+  if (!lastReply(ss))
+    return;
+
+  if (ss.m_error == 0) {
+    jam();
+    AlterTabConf* conf = (AlterTabConf*)signal->getDataPtrSend();
+    conf->senderRef = reference();
+    conf->senderData = ss.m_req.senderData;
+    sendSignal(dictRef, GSN_ALTER_TAB_CONF,
+               signal, AlterTabConf::SignalLength, JBB);
+  } else {
+    jam();
+    AlterTabRef* ref = (AlterTabRef*)signal->getDataPtrSend();
+    ref->senderRef = reference();
+    ref->senderData = ss.m_req.senderData;
+    ref->errorCode = ss.m_error;
+    sendSignal(dictRef, GSN_ALTER_TAB_REF,
+               signal, AlterTabConf::SignalLength, JBB);
+  }
+
+  ssRelease<Ss_ALTER_TAB_REQ>(ssId);
+}
+
 // GSN_START_RECREQ
 
 void

=== modified file 'storage/ndb/src/kernel/blocks/dblqh/DblqhProxy.hpp'
--- a/storage/ndb/src/kernel/blocks/dblqh/DblqhProxy.hpp	2008-08-23 06:32:32 +0000
+++ b/storage/ndb/src/kernel/blocks/dblqh/DblqhProxy.hpp	2008-09-16 18:33:52 +0000
@@ -24,6 +24,7 @@
 #include <signaldata/GCP.hpp>
 #include <signaldata/PrepDropTab.hpp>
 #include <signaldata/DropTab.hpp>
+#include <signaldata/AlterTab.hpp>
 #include <signaldata/StartRec.hpp>
 #include <signaldata/LqhTransReq.hpp>
 #include <signaldata/LqhTransConf.hpp>
@@ -230,6 +231,41 @@ protected:
   void execDROP_TAB_REF(Signal*);
   void sendDROP_TAB_CONF(Signal*, Uint32 ssId);
 
+  // GSN_ALTER_TAB_REQ
+  struct Ss_ALTER_TAB_REQ : SsParallel {
+    AlterTabReq m_req;
+    Uint32 m_sections;
+    // wl4391_todo check max length in various cases
+    enum { MaxSection0 = 2 * MAX_ATTRIBUTES_IN_TABLE };
+    Uint32 m_sz0;
+    Uint32 m_section0[MaxSection0];
+    Ss_ALTER_TAB_REQ() {
+      m_sendREQ = (SsFUNC)&DblqhProxy::sendALTER_TAB_REQ;
+      m_sendCONF = (SsFUNC)&DblqhProxy::sendALTER_TAB_CONF;
+      m_sections = 0;
+      m_sz0 = 0;
+    }
+    enum { poolSize = 1 };
+    static SsPool<Ss_ALTER_TAB_REQ>& pool(LocalProxy* proxy) {
+      return ((DblqhProxy*)proxy)->c_ss_ALTER_TAB_REQ;
+    }
+  };
+  SsPool<Ss_ALTER_TAB_REQ> c_ss_ALTER_TAB_REQ;
+  Uint32 getSsId(const AlterTabReq* req) {
+    return SsIdBase | req->tableId;
+  }
+  Uint32 getSsId(const AlterTabConf* conf) {
+    return conf->senderData;
+  }
+  Uint32 getSsId(const AlterTabRef* ref) {
+    return ref->senderData;
+  }
+  void execALTER_TAB_REQ(Signal*);
+  void sendALTER_TAB_REQ(Signal*, Uint32 ssId);
+  void execALTER_TAB_CONF(Signal*);
+  void execALTER_TAB_REF(Signal*);
+  void sendALTER_TAB_CONF(Signal*, Uint32 ssId);
+
   // GSN_START_RECREQ
   struct Ss_START_RECREQ : SsParallel {
     StartRecReq m_req;

=== modified file 'storage/ndb/src/kernel/blocks/dbtup/DbtupBuffer.cpp'
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupBuffer.cpp	2008-08-11 11:48:10 +0000
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupBuffer.cpp	2008-09-16 18:29:47 +0000
@@ -246,10 +246,11 @@ void Dbtup::sendReadAttrinfo(Signal* sig
      * The UTIL/TC blocks are in another thread (in multi-threaded ndbd), so
      * must use sendSignal().
      *
-     * In MT LQH only LQH and BACKUP are in same thread.
+     * In MT LQH only LQH and BACKUP are in same thread, and BACKUP only
+     * in LCP case since user-backup uses single worker.
      */
     BlockNumber blockMain = blockToMain(block);
-    if (blockMain == DBLQH || blockMain == BACKUP)
+    if (blockMain == DBLQH)
     {
       EXECUTE_DIRECT(blockMain, GSN_TRANSID_AI, signal, 3 + ToutBufIndex);
       jamEntry();
@@ -260,6 +261,13 @@ void Dbtup::sendReadAttrinfo(Signal* sig
       EXECUTE_DIRECT(blockMain, GSN_TRANSID_AI, signal, 3 + ToutBufIndex, 0);
       jamEntry();
     }
+    else if (blockMain == BACKUP)
+    {
+      Uint32 iNo = blockToInstance(block);
+      // wl4391_todo maybe not MT safe in non-LCP case
+      EXECUTE_DIRECT(blockMain, GSN_TRANSID_AI, signal, 3 + ToutBufIndex, iNo);
+      jamEntry();
+    }
     else
     {
       jam();

=== modified file 'storage/ndb/src/kernel/vm/mt.cpp'
--- a/storage/ndb/src/kernel/vm/mt.cpp	2008-08-27 20:27:20 +0000
+++ b/storage/ndb/src/kernel/vm/mt.cpp	2008-09-16 18:33:52 +0000
@@ -1823,11 +1823,16 @@ execute_signals(thr_data *selfptr, thr_j
 
 #ifdef VM_TRACE
     if (globalData.testOn) { //wl4391_todo segments
+      SegmentedSectionPtr ptr[3];
+      ptr[0].i = sig->m_sectionPtrI[0];
+      ptr[1].i = sig->m_sectionPtrI[1];
+      ptr[2].i = sig->m_sectionPtrI[2];
+      ::getSections(seccnt, ptr);
       globalSignalLoggers.executeSignal(*s,
                                         0,
                                         &sig->theData[0], 
-                                        globalData.ownId);
-
+                                        globalData.ownId,
+                                        ptr, seccnt);
     }
 #endif
 

=== modified file 'storage/ndb/src/mgmsrv/Config.cpp'
--- a/storage/ndb/src/mgmsrv/Config.cpp	2008-07-29 14:04:27 +0000
+++ b/storage/ndb/src/mgmsrv/Config.cpp	2008-09-16 09:37:22 +0000
@@ -20,12 +20,25 @@
 #include "ConfigInfo.hpp"
 
 
+static void require(bool b)
+{
+  if (!b)
+    abort();
+}
+
+
 Config::Config(struct ndb_mgm_configuration *config_values) :
   m_configValues(config_values)
 {
 }
 
 
+Config::Config(ConfigValues *config_values) :
+  m_configValues((struct ndb_mgm_configuration*)config_values)
+{
+}
+
+
 Config::~Config() {
   if(m_configValues != 0){
     free(m_configValues);
@@ -47,7 +60,7 @@ Config::print() const {
 
   for(unsigned i= 0; i < num_sections; i++) {
     unsigned section= sections[i];
-    ndb_mgm_configuration_iterator it(*m_configValues, section);
+    ConfigIter it(this, section);
 
     if (it.first())
       continue;
@@ -81,3 +94,554 @@ Config::print() const {
     }
   }
 }
+
+
+
+Uint32
+Config::getGeneration() const
+{
+  Uint32 generation;
+  ConfigIter iter(this, CFG_SECTION_SYSTEM);
+
+  if (iter.get(CFG_SYS_CONFIG_GENERATION, &generation))
+    return 0;
+
+  return generation;
+}
+
+
+
+bool
+Config::setValue(Uint32 section, Uint32 section_no,
+                 Uint32 id, Uint32 new_val)
+{
+  ConfigValues::Iterator iter(m_configValues->m_config);
+  if (iter.openSection(section, section_no)){
+    if (!iter.set(id, new_val))
+      return false;
+  }
+  else
+  {
+    ConfigValuesFactory cf(&m_configValues->m_config);
+    if (!cf.openSection(section, section_no))
+      return false;
+    if (!cf.put(CFG_TYPE_OF_SECTION, section))
+      return false;
+    if (!cf.put(id, new_val))
+      return false;
+    cf.closeSection();
+
+    m_configValues= (struct ndb_mgm_configuration*)cf.getConfigValues();
+  }
+
+  return true;
+}
+
+
+bool
+Config::setGeneration(Uint32 new_gen)
+{
+  return setValue(CFG_SECTION_SYSTEM, 0,
+                  CFG_SYS_CONFIG_GENERATION,
+                  new_gen);
+}
+
+
+Uint32
+Config::pack(UtilBuffer& buf) const
+{
+  return m_configValues->m_config.pack(buf);
+}
+
+
+
+enum diff_types {
+  DT_DIFF,            // Value differed
+  DT_MISSING_VALUE,   // Value didn't exist
+  DT_MISSING_SECTION, // Section missing
+  DT_ILLEGAL_CHANGE    // Illegal change detected
+};
+
+
+static void
+add_diff(const char* name, const char* key,
+         Properties& diff,
+         const char* value_name, Properties* value)
+{
+
+  Properties *section;
+  // Create a new section if it did not exist
+  if (!diff.getCopy(key, &section)){
+    Properties new_section(true);
+    new_section.put("Key", key);
+    new_section.put("Name", name);
+
+    require(diff.put(key, &new_section));
+
+    // Get copy of section
+    require(diff.getCopy(key, &section));
+  }
+
+  // Make sure type of diff has been set
+  Uint32 type;
+  require(value->get("Type", &type));
+
+  // Add the value to the section if not already added
+  if (!section->put(value_name, value))
+    require(section->getPropertiesErrno() ==
+            E_PROPERTIES_ELEMENT_ALREADY_EXISTS);
+
+  // Put the updated section into the diff
+  require(diff.put(key, section, true));
+
+  delete section;
+}
+
+
+static void
+compare_value(const char* name, const char* key,
+              const ConfigInfo::ParamInfo* pinfo,
+              ndb_mgm_configuration_iterator& it,
+              ndb_mgm_configuration_iterator& it2,
+              Properties& diff)
+{
+  Uint32 pid= pinfo->_paramId;
+  {
+    Uint32 val;
+    if (it.get(pid, &val) == 0) {
+      Uint32 val2;
+      if (it2.get(pid, &val2) == 0) {
+        if (val != val2){
+          Properties info(true);
+          info.put("Type", DT_DIFF);
+          info.put("New", val2);
+          info.put("Old", val);
+          add_diff(name, key,
+                   diff,
+                   pinfo->_fname, &info);
+        }
+      }
+      else
+      {
+        Properties info(true);
+        info.put("Type", DT_MISSING_VALUE);
+        info.put("Old", val);
+        add_diff(name, key,
+                 diff,
+                 pinfo->_fname, &info);
+      }
+      return;
+    }
+  }
+
+  {
+    Uint64 val;
+    if (it.get(pid, &val) == 0) {
+      Uint64 val2;
+      if (it2.get(pid, &val2) == 0) {
+        if (val != val2) {
+          Properties info(true);
+          info.put("Type", DT_DIFF);
+          info.put("New", val2);
+          info.put("Old", val);
+          add_diff(name, key,
+                   diff,
+                   pinfo->_fname, &info);
+        }
+      }
+      else
+      {
+        Properties info(true);
+        info.put("Type", DT_MISSING_VALUE);
+        info.put("Old", val);
+        add_diff(name, key,
+                 diff,
+                 pinfo->_fname, &info);
+      }
+      return;
+    }
+  }
+
+  {
+    const char* val;
+    if (it.get(pid, &val) == 0) {
+      const char* val2;
+      if (it2.get(pid, &val2) == 0) {
+        if (strcmp(val, val2)) {
+          Properties info(true);
+          info.put("Type", DT_DIFF);
+          info.put("New", val2);
+          info.put("Old", val);
+          add_diff(name, key,
+                   diff,
+                   pinfo->_fname, &info);
+        }
+      }
+      else
+      {
+        Properties info(true);
+        info.put("Type", DT_MISSING_VALUE);
+        info.put("Old", val);
+        add_diff(name, key,
+                 diff,
+                 pinfo->_fname, &info);
+      }
+      return;
+    }
+  }
+}
+
+
+static void
+diff_system(const Config* a, const Config* b, Properties& diff)
+{
+  ConfigIter itA(a, CFG_SECTION_SYSTEM);
+  ConfigIter itB(b, CFG_SECTION_SYSTEM);
+
+  // Check each possible configuration value
+  const ConfigInfo::ParamInfo* pinfo= NULL;
+  ConfigInfo::ParamInfoIter param_iter(g_info,
+                                       CFG_SECTION_SYSTEM,
+                                       CFG_SECTION_SYSTEM);
+  while((pinfo= param_iter.next())) {
+    /*  Loop through the section and compare values */
+    compare_value("SYSTEM", "", pinfo, itA, itB, diff);
+  }
+}
+
+
+static void
+diff_nodes(const Config* a, const Config* b, Properties& diff)
+{
+  ConfigIter itA(a, CFG_SECTION_NODE);
+
+  for(;itA.valid(); itA.next())
+  {
+
+    /* Get typ of Node */
+    Uint32 nodeType;
+    require(itA.get(CFG_TYPE_OF_SECTION, &nodeType) == 0);
+
+    BaseString name(g_info.sectionName(CFG_SECTION_NODE, nodeType));
+
+    /* Get NodeId which is "primary key" */
+    Uint32 nodeId;
+    require(itA.get(CFG_NODE_ID, &nodeId) == 0);
+
+    BaseString key;
+    key.assfmt("NodeId=%d", nodeId);
+
+    /* Position itB in the section with same NodeId */
+    ConfigIter itB(b, CFG_SECTION_NODE);
+    if (itB.find(CFG_NODE_ID, nodeId) != 0)
+    {
+      // A whole node has been removed
+      Properties info(true);
+      info.put("Type", DT_MISSING_SECTION);
+      info.put("Why", "Node removed");
+      add_diff(name.c_str(), key.c_str(),
+               diff,
+               "Node removed", &info);
+
+      continue;
+    }
+
+    /* Make sure it has the same node type */
+    Uint32 nodeType2;
+    require(itB.get(CFG_TYPE_OF_SECTION, &nodeType2) == 0);
+    if ((nodeType == NODE_TYPE_DB || nodeType == NODE_TYPE_MGM) &&
+        nodeType != nodeType2)
+    {
+      // DB or MGM node has changed type -> not allowed change
+      Properties info(true);
+      info.put("Type", DT_ILLEGAL_CHANGE);
+      info.put("Why", "Node has changed type");
+      add_diff(name.c_str(), key.c_str(),
+               diff,
+               "Node type changed", &info);
+      continue;
+    }
+
+    // Check each possible configuration value
+    const ConfigInfo::ParamInfo* pinfo= NULL;
+    ConfigInfo::ParamInfoIter param_iter(g_info, CFG_SECTION_NODE, nodeType);
+    while((pinfo= param_iter.next())) {
+      /*  Loop through the section and compare values */
+      compare_value(name.c_str(), key.c_str(), pinfo, itA, itB, diff);
+    }
+  }
+}
+
+
+static void
+diff_connections(const Config* a, const Config* b, Properties& diff)
+{
+  ConfigIter itA(a, CFG_SECTION_CONNECTION);
+
+  for(;itA.valid(); itA.next())
+  {
+    /* Get typ of connection */
+    Uint32 connectionType;
+    require(itA.get(CFG_TYPE_OF_SECTION, &connectionType) == 0);
+
+    BaseString name(g_info.sectionName(CFG_SECTION_CONNECTION, connectionType));
+
+    /* Get NodeId1 and NodeId2 which is "primary key" */
+    Uint32 nodeId1_A, nodeId2_A;
+    require(itA.get(CFG_CONNECTION_NODE_1, &nodeId1_A) == 0);
+    require(itA.get(CFG_CONNECTION_NODE_2, &nodeId2_A) == 0);
+
+    BaseString key;
+    key.assfmt("NodeId1=%d;NodeId2=%d", nodeId1_A, nodeId2_A);
+
+    /* Find the connecton in other config */
+    ConfigIter itB(b, CFG_SECTION_CONNECTION);
+    bool found= false;
+    Uint32 nodeId1_B, nodeId2_B;
+    while(itB.get(CFG_CONNECTION_NODE_1, &nodeId1_B) == 0 &&
+          itB.get(CFG_CONNECTION_NODE_2, &nodeId2_B) == 0)
+    {
+      if (nodeId1_A == nodeId1_B && nodeId2_A == nodeId2_B)
+      {
+        found= true;
+        break;
+      }
+
+      if(itB.next() != 0)
+        break;
+    }
+
+    if (!found)
+    {
+      // A connection has been removed
+      Properties info(true);
+      info.put("Type", DT_MISSING_SECTION);
+      info.put("Why", "Connection removed");
+      add_diff(name.c_str(), key.c_str(),
+               diff,
+               "Connection removed", &info);
+
+      continue;
+    }
+
+    // Check each possible configuration value
+    const ConfigInfo::ParamInfo* pinfo= NULL;
+    ConfigInfo::ParamInfoIter param_iter(g_info,
+                                         CFG_SECTION_CONNECTION,
+                                         connectionType);
+    while((pinfo= param_iter.next())) {
+      /*  Loop through the section and compare values */
+      compare_value(name.c_str(), key.c_str(), pinfo, itA, itB, diff);
+    }
+  }
+}
+
+
+static bool
+include_section(const unsigned* exclude, unsigned section){
+  if (exclude == NULL)
+    return true;
+
+  while(*exclude){
+    if (*exclude == section)
+      return false;
+    exclude++;
+  }
+  return true;
+}
+
+
+/**
+  Generate a diff list
+*/
+
+void Config::diff(const Config* other, Properties& diff,
+                  const unsigned* exclude) const {
+
+  if (include_section(exclude, CFG_SECTION_SYSTEM)) {
+    diff_system(this, other, diff);
+    diff_system(other, this, diff);
+  }
+  if (include_section(exclude, CFG_SECTION_NODE)) {
+    diff_nodes(this, other, diff);
+    diff_nodes(other, this, diff);
+  }
+  if (include_section(exclude, CFG_SECTION_CONNECTION)) {
+    diff_connections(this, other, diff);
+    diff_connections(other, this, diff);
+  }
+}
+
+
+static const char*
+p2s(const Properties* prop, const char* name, BaseString& buf){
+  PropertiesType type;
+  require(prop->getTypeOf(name, &type));
+  switch(type){
+  case PropertiesType_Uint32:
+  {
+    Uint32 val;
+    require(prop->get(name, &val));
+    buf.assfmt("%d", val);
+    break;
+  }
+  case PropertiesType_Uint64:
+  {
+    Uint64 val;
+    require(prop->get(name, &val));
+    buf.assfmt("%lld", val);
+    break;
+  }
+  case PropertiesType_char:
+  {
+    require(prop->get(name, buf));
+    break;
+  }
+  default:
+    require(false);
+    break;
+  }
+  return buf.c_str();
+}
+
+
+const char*
+Config::diff2str(const Properties& diff_list, BaseString& str) const
+{
+  const char* name;
+  Properties::Iterator prop_it(&diff_list);
+  while ((name= prop_it.next())){
+
+    const Properties *node;
+    require(diff_list.get(name, &node));
+
+    require(node->get("Name", &name));
+    str.appfmt("[%s]\n", name);
+
+    BaseString key;
+    require(node->get("Key", key));
+    if (key.length() > 0){
+      Vector<BaseString> keys;
+      key.split(keys, ";");
+      for (unsigned i= 0; i < keys.size(); i++)
+        str.appfmt("%s\n", keys[i].c_str());
+    }
+
+    BaseString buf;
+    Properties::Iterator prop_it2(node);
+    while ((name= prop_it2.next())){
+
+      const Properties *what;
+      if (!node->get(name, &what))
+        continue;
+
+      Uint32 type;
+      require(what->get("Type", &type));
+      switch (type) {
+      case DT_DIFF:
+      {
+        str.appfmt("-%s=%s\n", name, p2s(what, "Old", buf));
+        str.appfmt("+%s=%s\n", name, p2s(what, "New", buf));
+        break;
+      }
+
+      case DT_MISSING_VALUE:
+      {
+        str.appfmt("-%s=%s\n", name, p2s(what, "Old", buf));
+        break;
+      }
+
+      case DT_MISSING_SECTION:
+      {
+        const char* why;
+        if (what->get("Why", &why))
+          str.appfmt("%s\n", why);
+        break;
+      }
+
+      case DT_ILLEGAL_CHANGE:
+      {
+        const char* why;
+        str.appfmt("Illegal change\n");
+        if (what->get("Why", &why))
+          str.appfmt("%s\n", why);
+        break;
+      }
+
+      default:
+        str.appfmt("Illegal 'type' found in diff_list\n");
+        require(false);
+        break;
+      }
+    }
+    str.appfmt("\n");
+  }
+  return str.c_str();
+}
+
+
+void Config::print_diff(const Config* other) const {
+  Properties diff_list;
+  diff(other, diff_list);
+  BaseString str;
+  ndbout_c("%s", diff2str(diff_list, str));
+}
+
+
+const char*
+Config::diff2str(const Config* other, BaseString& str) const {
+  Properties diff_list;
+  diff(other, diff_list);
+  return diff2str(diff_list, str);
+}
+
+
+bool Config::equal(const Properties& diff_list) const {
+  int count= 0;
+  Properties::Iterator prop_it(&diff_list);
+  while ((prop_it.next()))
+    count++;
+  return (count == 0);
+}
+
+
+bool Config::equal(const Config* other, const unsigned * exclude) const {
+  Properties diff_list;
+  diff(other, diff_list, exclude);
+  return equal(diff_list);
+}
+
+
+
+bool Config::illegal_change(const Properties& diff_list) const {
+  bool illegal= false;
+  const char* name;
+  Properties::Iterator prop_it(&diff_list);
+  while ((name= prop_it.next())){
+
+    const Properties *node;
+    require(diff_list.get(name, &node));
+
+    Properties::Iterator prop_it2(node);
+    while ((name= prop_it2.next())){
+
+      const Properties *what;
+      if (!node->get(name, &what))
+        continue;
+
+      Uint32 type;
+      require(what->get("Type", &type));
+      if (type == DT_ILLEGAL_CHANGE)
+        illegal= true;
+    }
+  }
+  return illegal;
+}
+
+
+bool Config::illegal_change(const Config* other) const {
+  Properties diff_list;
+  diff(other, diff_list);
+  return illegal_change(diff_list);
+}
+

=== modified file 'storage/ndb/src/mgmsrv/Config.hpp'
--- a/storage/ndb/src/mgmsrv/Config.hpp	2008-07-29 13:38:18 +0000
+++ b/storage/ndb/src/mgmsrv/Config.hpp	2008-09-16 09:37:22 +0000
@@ -32,11 +32,59 @@
 class Config {
 public:
   Config(struct ndb_mgm_configuration *config_values = NULL);
+  Config(ConfigValues* config_values);
   virtual ~Config();
 
   void print() const;
 
+  /*
+    Returns generation of the config
+    0 => not set(yet), ie. config has never been committed
+   */
+  Uint32 getGeneration() const;
+  bool setGeneration(Uint32);
+
+  /*
+   Pack the config into a UtilBuffer and return it's size in bytes
+  */
+  Uint32 pack(UtilBuffer&) const;
+
+  /*
+    Compare against another config and return a list of
+    differences in a Properties object
+  */
+  void diff(const Config* other, Properties& diff_list,
+            const unsigned* exclude=NULL) const;
+
+  /*
+    Print the difference against another config
+   */
+  void print_diff(const Config* other) const;
+
+  /*
+    Print the difference to string buffer
+  */
+  const char* diff2str(const Config* other, BaseString& str) const;
+
+  /*
+    Determine if changing to the other config is illegal
+  */
+  bool illegal_change(const Config* other) const;
+
+  /*
+    Check if the config is equal to another config
+  */
+  bool equal(const Config*, const unsigned* exclude = NULL) const;
+
   struct ndb_mgm_configuration * m_configValues;
+
+private:
+  bool setValue(Uint32 section, Uint32 section_no,
+                Uint32 id, Uint32 new_gen);
+
+  bool illegal_change(const Properties&) const;
+  bool equal(const Properties&) const;
+  const char* diff2str(const Properties&, BaseString& str) const;
 };
 
 class ConfigIter : public ndb_mgm_configuration_iterator {

=== modified file 'storage/ndb/src/mgmsrv/ConfigInfo.cpp'
--- a/storage/ndb/src/mgmsrv/ConfigInfo.cpp	2008-09-12 12:55:29 +0000
+++ b/storage/ndb/src/mgmsrv/ConfigInfo.cpp	2008-09-16 09:37:22 +0000
@@ -4282,6 +4282,8 @@ check_node_vs_replicas(Vector<ConfigInfo
     tmp->get("NodeId", &id);
 
     for (;ng_cnt[next_ng] >= replicas; next_ng++);
+
+    delete tmp;
   }
 
   /**
@@ -4420,6 +4422,7 @@ ConfigInfo::ParamInfoIter::ParamInfoIter
                                          Uint32 section,
                                          Uint32 section_type) :
   m_info(info),
+  m_section_name(NULL),
   m_curr_param(0)
 {
   /* Find the section's name */

=== modified file 'storage/ndb/src/mgmsrv/Makefile.am'
--- a/storage/ndb/src/mgmsrv/Makefile.am	2008-06-09 10:52:24 +0000
+++ b/storage/ndb/src/mgmsrv/Makefile.am	2008-09-16 09:37:22 +0000
@@ -30,6 +30,15 @@ ndb_mgmd_SOURCES = \
 	InitConfigFileParser.cpp \
 	Config.cpp
 
+
+noinst_PROGRAMS = testConfig
+
+testConfig_SOURCES = \
+	testConfig.cpp \
+	InitConfigFileParser.cpp \
+	ConfigInfo.cpp \
+	Config.cpp
+
 INCLUDES_LOC = -I$(top_srcdir)/storage/ndb/src/ndbapi \
                -I$(top_srcdir)/storage/ndb/src/mgmapi \
                -I$(top_srcdir)/storage/ndb/src/common/mgmcommon \

=== modified file 'storage/ndb/src/mgmsrv/MgmtSrvr.cpp'
--- a/storage/ndb/src/mgmsrv/MgmtSrvr.cpp	2008-09-12 12:55:29 +0000
+++ b/storage/ndb/src/mgmsrv/MgmtSrvr.cpp	2008-09-16 18:29:47 +0000
@@ -2900,14 +2900,19 @@ MgmtSrvr::startBackup(Uint32& backupId, 
 
   SimpleSignal ssig;
   BackupReq* req = CAST_PTR(BackupReq, ssig.getDataPtrSend());
+  /*
+   * Single-threaded backup.  Set instance key 1.  In the kernel
+   * this maps to main instance 0 or worker instance 1 (if MT LQH).
+   */
+  BlockNumber backupBlockNo = numberToBlock(BACKUP, 1);
   if(input_backupId > 0)
   {
-    ssig.set(ss, TestOrd::TraceAPI, BACKUP, GSN_BACKUP_REQ, 
+    ssig.set(ss, TestOrd::TraceAPI, backupBlockNo, GSN_BACKUP_REQ, 
 	     BackupReq::SignalLength);
     req->inputBackupId = input_backupId;
   }
   else
-    ssig.set(ss, TestOrd::TraceAPI, BACKUP, GSN_BACKUP_REQ, 
+    ssig.set(ss, TestOrd::TraceAPI, backupBlockNo, GSN_BACKUP_REQ, 
 	     BackupReq::SignalLength - 1);
   
   req->senderData = 19;

=== added file 'storage/ndb/src/mgmsrv/testConfig.cpp'
--- a/storage/ndb/src/mgmsrv/testConfig.cpp	1970-01-01 00:00:00 +0000
+++ b/storage/ndb/src/mgmsrv/testConfig.cpp	2008-09-16 09:37:22 +0000
@@ -0,0 +1,175 @@
+#include <ndb_global.h>
+#include "InitConfigFileParser.hpp"
+#include "ConfigInfo.hpp"
+#include "Config.hpp"
+
+my_bool opt_core= 1;
+my_bool opt_ndb_shm= 0;
+
+
+#define CHECK(x) \
+  if (!(x)) {\
+    fprintf(stderr, "testConfig: '"#x"' failed on line %d\n", __LINE__); \
+    exit(1); \
+  }
+
+
+static const ConfigInfo g_info;
+
+/*
+  Create a small config.ini with the given parameter and run
+  it through InitConfigFileParser
+ */
+bool
+check_param(const ConfigInfo::ParamInfo & param)
+{
+
+  FILE* config_file= tmpfile();
+  CHECK(config_file);
+
+  const char* section= g_info.nameToAlias(param._section);
+  if (section == NULL)
+    section= param._section;
+
+  if (param._type == ConfigInfo::CI_SECTION)
+  {
+    fclose(config_file);
+    return true;
+  }
+
+  if(param._default == MANDATORY)
+  {
+    // Mandatory parameter
+    fclose(config_file);
+    return true;
+  }
+  else
+  {
+    fprintf(config_file, "[%s]\n", section);
+    fprintf(config_file, "%s=%s\n", param._fname, param._default);
+  }
+
+  // Fill in lines needed for a minimal config
+  if (strcmp(section, "NDBD") != 0)
+    fprintf(config_file, "[ndbd]\n");
+  if (strcmp(param._fname, "NoOfReplicas") != 0)
+    fprintf(config_file, "NoOfReplicas=1\n");
+
+  if (strcmp(section, "NDB_MGMD") != 0)
+    fprintf(config_file, "[ndb_mgmd]\n");
+  if (strcmp(param._fname, "Hostname") != 0)
+    fprintf(config_file, "HostName=localhost\n");
+
+  if (strcmp(section, "MYSQLD") != 0)
+    fprintf(config_file, "[mysqld]\n");
+
+  rewind(config_file);
+
+  // Run the config file through InitConfigFileParser
+  // throw away the error messages for now.
+  FILE* err_file= tmpfile();
+  InitConfigFileParser parser(err_file);
+  Config* conf = parser.parseConfig(config_file);
+  fclose(config_file);
+  fclose(err_file);
+
+  if (conf == NULL)
+    return false;
+  delete conf;
+  return true;
+}
+
+
+bool
+check_params(void)
+{
+  bool ok= true;
+  for (int j=0; j<g_info.m_NoOfParams; j++) {
+    const ConfigInfo::ParamInfo & param= g_info.m_ParamInfo[j];
+    if (!check_param(param))
+    {
+      ok= false;
+    }
+  }
+
+  return true; // Ignore ok for now
+}
+
+
+
+Config*
+create_config(const char* first, ...)
+{
+  va_list args;
+
+  FILE* config_file= tmpfile();
+  CHECK(config_file);
+
+  va_start(args, first);
+  const char* str= first;
+  do
+    fprintf(config_file, "%s\n", str);
+  while((str= va_arg(args, const char*)) != NULL);
+  va_end(args);
+
+#if 0
+  rewind(config_file);
+
+  char buf[100];
+  while(fgets(buf, sizeof(buf), config_file))
+    ndbout_c(buf);
+#endif
+
+  rewind(config_file);
+
+  InitConfigFileParser parser;
+  Config* conf = parser.parseConfig(config_file);
+  CHECK(conf);
+  fclose(config_file);
+
+  return conf;
+}
+
+
+
+
+void
+diff_config(void)
+{
+  Config* c1=
+    create_config("[ndbd]", "NoOfReplicas=1",
+                  "[ndb_mgmd]", "HostName=localhost",
+                  "[mysqld]", NULL);
+  Config* c2=
+    create_config("[ndbd]", "NoOfReplicas=1",
+                  "[ndb_mgmd]", "HostName=localhost",
+                  "[mysqld]", "[mysqld]", NULL);
+
+  CHECK(c1->equal(c1));
+
+  CHECK(!c1->equal(c2));
+  CHECK(!c2->equal(c1));
+  CHECK(!c2->illegal_change(c1));
+  CHECK(!c1->illegal_change(c2));
+
+
+  ndbout_c("==================");
+  ndbout_c("c1->print_diff(c2)");
+  c1->print_diff(c2);
+  ndbout_c("==================");
+  ndbout_c("c2->print_diff(c1)");
+  c2->print_diff(c1);
+  ndbout_c("==================");
+  delete c1;
+  delete c2;
+}
+
+
+int
+main(void){
+  ndbout_c("1..1");
+  diff_config();
+  CHECK(check_params());
+  ndbout_c("ok");
+  exit(0);
+}

Thread
bzr commit into mysql-5.1 branch (jonas:2764) Jonas Oreland18 Sep