List:Commits« Previous MessageNext Message »
From:Tomas Ulin Date:March 24 2009 1:49pm
Subject:bzr push into mysql-6.0-telco-7.1 branch (tomas.ulin:2859 to 2861)
View as plain text  
 2861 Tomas Ulin	2009-03-24 [merge]
      merge

 2860 Tomas Ulin	2009-03-24 [merge]
      merge from telco-7.0
      removed:
        mysql-test/ndb/
      modified:
        mysql-test/suite/ndb/r/ndb_config.result
        mysql-test/suite/ndb/t/ndb_config.test
        mysql-test/t/mysqltest.test
        storage/ndb/include/kernel/signaldata/SumaImpl.hpp
        storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp
        storage/ndb/src/kernel/blocks/dblqh/DblqhProxy.cpp
        storage/ndb/src/kernel/blocks/dbtc/Dbtc.hpp
        storage/ndb/src/kernel/blocks/dbtc/DbtcInit.cpp
        storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp
        storage/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp
        storage/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp
        storage/ndb/src/kernel/blocks/dbtup/DbtupProxy.cpp
        storage/ndb/src/kernel/blocks/lgman.cpp
        storage/ndb/src/kernel/blocks/lgman.hpp
        storage/ndb/src/kernel/blocks/suma/Suma.cpp
        storage/ndb/src/kernel/vm/LongSignal.cpp
        storage/ndb/src/kernel/vm/TransporterCallback.cpp
        storage/ndb/src/mgmsrv/ConfigInfo.cpp
        storage/ndb/src/mgmsrv/ConfigInfo.hpp
        storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp
        storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp
        storage/ndb/src/ndbapi/NdbEventOperationImpl.hpp
        storage/ndb/src/ndbapi/NdbOperationExec.cpp
        storage/ndb/src/ndbapi/NdbReceiver.cpp
        storage/ndb/test/ndbapi/testBlobs.cpp
        storage/ndb/test/ndbapi/testLimits.cpp
        storage/ndb/test/ndbapi/test_event.cpp
        storage/ndb/tools/ndb_config.cpp

 2859 Tomas Ulin	2009-03-24
      fix result file
      modified:
        mysql-test/suite/ndb/r/ndb_restore_undolog.result

=== removed directory 'mysql-test/ndb'
=== modified file 'mysql-test/suite/ndb/r/ndb_config.result'
--- a/mysql-test/suite/ndb/r/ndb_config.result	2009-03-12 10:59:57 +0000
+++ b/mysql-test/suite/ndb/r/ndb_config.result	2009-03-24 13:48:39 +0000
@@ -25,3 +25,5 @@ tcp,3,4,55,3 tcp,3,5,55,3 tcp,3,6,55,3 t
 
 == 13 ==
 3 1 2
+== 14 == ndb_config --configinfo
+== 15 == ndb_config --configinfo --xml

=== modified file 'mysql-test/suite/ndb/t/ndb_config.test'
--- a/mysql-test/suite/ndb/t/ndb_config.test	2009-03-12 10:59:57 +0000
+++ b/mysql-test/suite/ndb/t/ndb_config.test	2009-03-24 13:48:39 +0000
@@ -39,3 +39,10 @@ echo == 12 ==;
 
 echo == 13 ==;
 --exec $NDB_CONFIG --no-defaults --query=nodeid --host=127.0.0.1 --config-file=$MYSQL_TEST_DIR/std_data/ndb_config_config.ini 2> /dev/null
+
+echo == 14 == ndb_config --configinfo;
+--exec $NDB_CONFIG --configinfo > /dev/null
+
+echo == 15 == ndb_config --configinfo --xml;
+--exec $NDB_CONFIG --configinfo --xml > /dev/null
+

=== modified file 'mysql-test/t/mysqltest.test'
--- a/mysql-test/t/mysqltest.test	2009-03-06 20:33:52 +0000
+++ b/mysql-test/t/mysqltest.test	2009-03-24 13:46:34 +0000
@@ -603,6 +603,9 @@ echo ;
 
 # Illegal use of exec
 --error 1
+--exec echo "--exec false" | $MYSQL_TEST > /dev/null 2>&1
+
+--error 1
 --exec echo "--exec " | $MYSQL_TEST 2>&1
 
 # ----------------------------------------------------------------------------

=== modified file 'storage/ndb/include/kernel/signaldata/SumaImpl.hpp'
--- a/storage/ndb/include/kernel/signaldata/SumaImpl.hpp	2008-10-01 07:53:50 +0000
+++ b/storage/ndb/include/kernel/signaldata/SumaImpl.hpp	2009-03-20 08:36:40 +0000
@@ -222,7 +222,8 @@ struct SubStopConf {
    */
 
   friend bool printSUB_STOP_CONF(FILE *, const Uint32 *, Uint32, Uint16);
-  STATIC_CONST( SignalLength = 7 );
+  STATIC_CONST( SignalLengthWithGci = 9 );
+  STATIC_CONST( SignalLength = 9 );
 
   Uint32 senderRef;
   Uint32 senderData;
@@ -231,6 +232,9 @@ struct SubStopConf {
   Uint32 part;  // SubscriptionData::Part
   Uint32 subscriberData;
   Uint32 subscriberRef;
+  //
+  Uint32 gci_hi;
+  Uint32 gci_lo;
 };
 
 struct SubSyncReq {

=== modified file 'storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp'
--- a/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp	2009-03-19 07:34:39 +0000
+++ b/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp	2009-03-24 08:42:42 +0000
@@ -404,7 +404,6 @@ void Dbdict::execCONTINUEB(Signal* signa
       Uint32* data = &signal->theData[0];
       Uint32 masterRef = data[1];
       memmove(&data[0], &data[2], SchemaTransImplConf::SignalLength << 2);
-      g_eventLogger->info("QQQ(%u) - GSN_SCHEMA_TRANS_IMPL_CONF", __LINE__);
       sendSignal(masterRef, GSN_SCHEMA_TRANS_IMPL_CONF, signal,
                  SchemaTransImplConf::SignalLength, JBB);
     }
@@ -6498,7 +6497,6 @@ Dbdict::execDROP_TABLE_REQ(Signal* signa
   ref->tableId = req->tableId;
   ref->tableVersion = req->tableVersion;
   getError(error, ref);
-
   sendSignal(req->clientRef, GSN_DROP_TABLE_REF, signal,
              DropTableRef::SignalLength, JBB);
 }
@@ -6733,7 +6731,6 @@ Dbdict::prepDropTab_nextStep(Signal* sig
     ref->senderData = op_ptr.p->op_key;
     ref->tableId = impl_req->tableId;
     ref->errorCode = 9131;
-
     sendSignal(reference(), GSN_PREP_DROP_TAB_REF, signal,
                PrepDropTabRef::SignalLength, JBB);
     return;
@@ -7025,7 +7022,6 @@ Dbdict::dropTab_complete(Signal* signal,
     }
     conf->senderData = op_key;
     conf->tableId = tableId;
-
     sendSignal(SUMA_REF, GSN_DROP_TAB_CONF, signal,
                DropTabConf::SignalLength, JBB);
   }
@@ -7147,14 +7143,10 @@ Dbdict::execALTER_TABLE_REQ(Signal* sign
   jamEntry();
 
   if (!assembleFragments(signal)) {
-    g_eventLogger->info("QQQ(%u) - Dbdict::execALTER_TABLE_REQ", __LINE__);
     jam();
     return;
   }
   SectionHandle handle(this, signal);
-
-  g_eventLogger->info("QQQ(%u) - Dbdict::execALTER_TABLE_REQ", __LINE__);
-
   const AlterTableReq req_copy =
     *(const AlterTableReq*)signal->getDataPtr();
   const AlterTableReq* req = &req_copy;
@@ -7192,8 +7184,6 @@ Dbdict::execALTER_TABLE_REQ(Signal* sign
   ref->clientData = req->clientData;
   ref->transId = req->transId;
   getError(error, ref);
-
-  g_eventLogger->info("QQQ(%u) - GSN_ALTER_TABLE_REF", __LINE__);
   sendSignal(req->clientRef, GSN_ALTER_TABLE_REF, signal,
              AlterTableRef::SignalLength, JBB);
 }
@@ -7988,7 +7978,6 @@ Dbdict::alterTable_reply(Signal* signal,
     conf->newTableVersion = impl_req->newTableVersion;
 
     Uint32 clientRef = op_ptr.p->m_clientRef;
-    g_eventLogger->info("QQQ(%u) - GSN_ALTER_TABLE_CONF", __LINE__);
     sendSignal(clientRef, GSN_ALTER_TABLE_CONF, signal,
                AlterTableConf::SignalLength, JBB);
   } else {
@@ -8002,7 +7991,6 @@ Dbdict::alterTable_reply(Signal* signal,
     ref->errorKey = error.errorKey;
 
     Uint32 clientRef = op_ptr.p->m_clientRef;
-    g_eventLogger->info("QQQ(%u) - GSN_ALTER_TABLE_REF", __LINE__);
     sendSignal(clientRef, GSN_ALTER_TABLE_REF, signal,
                AlterTableRef::SignalLength, JBB);
   }
@@ -8042,8 +8030,6 @@ Dbdict::alterTable_toSumaSync(Signal* si
     jamLine(step);
     ndbrequire(false);
   }
-
-  g_eventLogger->info("QQQ(%u) - GSN_ALTER_TABLE_REQ", __LINE__);
   sendSignal(reference(), GSN_ALTER_TABLE_REQ, signal,
              AlterTableReq::SignalLength, JBB);
 }
@@ -8941,7 +8927,6 @@ void
 Dbdict::execALTER_TABLE_CONF(Signal* signal)
 {
   jamEntry();
-  g_eventLogger->info("QQQ(%u) - execALTER_TABLE_CONF", __LINE__);
   const AlterTableConf* conf = (const AlterTableConf*)signal->getDataPtr();
   ndbrequire(refToNode(conf->senderRef) == getOwnNodeId());
   handleDictConf(signal, conf);
@@ -8951,7 +8936,6 @@ void
 Dbdict::execALTER_TABLE_REF(Signal* signal)
 {
   jamEntry();
-  g_eventLogger->info("QQQ(%u) - execALTER_TABLE_REF", __LINE__);
   const AlterTableRef* ref = (const AlterTableRef*)signal->getDataPtr();
   ndbrequire(refToNode(ref->senderRef) == getOwnNodeId());
   handleDictRef(signal, ref);
@@ -10890,7 +10874,6 @@ Dbdict::dropIndex_toDropTable(Signal* si
   req->requestInfo = requestInfo;
   req->tableId = impl_req->indexId;
   req->tableVersion = impl_req->indexVersion;
-
   sendSignal(reference(), GSN_DROP_TABLE_REQ, signal,
              DropTableReq::SignalLength, JBB);
 }
@@ -13470,6 +13453,15 @@ Dbdict::execCREATE_EVNT_REQ(Signal* sign
     jam();
     EVENT_TRACE;
     releaseSections(handle);
+
+    if (ERROR_INSERTED(6023))
+    {
+      jam();
+      signal->theData[0] = 9999;
+      sendSignalWithDelay(CMVMI_REF, GSN_NDB_TAMPER, signal, 1000, 1);
+      return;
+    }
+
     createEvent_RT_DICT_AFTER_GET(signal, evntRecPtr);
     return;
   }
@@ -14143,15 +14135,44 @@ void Dbdict::execCREATE_EVNT_REF(Signal*
   ndbout_c("DBDICT(Coordinator) got GSN_CREATE_EVNT_REF evntRecPtr.i = (%d)", evntRecPtr.i);
 #endif
 
-  if (ref->errorCode == CreateEvntRef::NF_FakeErrorREF){
+  LinearSectionPtr ptr[1];
+
+  int noLSP = 0;
+  LinearSectionPtr *ptr0 = NULL;
+  if (ref->errorCode == CreateEvntRef::NF_FakeErrorREF)
+  {
     jam();
-    evntRecPtr.p->m_reqTracker.ignoreRef(c_counterMgr, refToNode(ref->senderRef));
-  } else {
+    evntRecPtr.p->m_reqTracker.ignoreRef(c_counterMgr, 
+                                         refToNode(ref->senderRef));
+
+    /**
+     * If a CREATE_EVNT_REF finishes request,
+     *   we need to make sure that table name is sent
+     *   same as it is if a CREATE_EVNT_CONF finishes request
+     */
+    if (evntRecPtr.p->m_reqTracker.done())
+    {
+      jam();
+      /**
+       * Add "extra" check if tracker is done...
+       *   (strictly not necessary...)
+       *   but makes case more explicit
+       */
+      ptr[0].p = (Uint32 *)evntRecPtr.p->m_eventRec.TABLE_NAME;
+      ptr[0].sz = (strlen(evntRecPtr.p->m_eventRec.TABLE_NAME)+4)/4;
+      ptr0 = ptr;
+      noLSP = 1;
+    }
+  }
+  else 
+  {
     jam();
     evntRecPtr.p->m_errorCode = ref->errorCode;
-    evntRecPtr.p->m_reqTracker.reportRef(c_counterMgr, refToNode(ref->senderRef));
+    evntRecPtr.p->m_reqTracker.reportRef(c_counterMgr, 
+                                         refToNode(ref->senderRef));
   }
-  createEvent_sendReply(signal, evntRecPtr);
+
+  createEvent_sendReply(signal, evntRecPtr, ptr0, noLSP);
 
   return;
 }
@@ -14729,6 +14750,7 @@ busy:
     subbPtr.p->m_subscriptionKey = req->subscriptionKey;
     subbPtr.p->m_subscriberRef = req->subscriberRef;
     subbPtr.p->m_subscriberData = req->subscriberData;
+    bzero(&subbPtr.p->m_sub_stop_conf, sizeof(subbPtr.p->m_sub_stop_conf));
 
     if (signal->getLength() < SubStopReq::SignalLength)
     {
@@ -14873,7 +14895,24 @@ void Dbdict::execSUB_STOP_CONF(Signal* s
    * Coordinator
    */
   ndbrequire(refToBlock(senderRef) == DBDICT);
+  Uint64 old_gci, new_gci = 0;
+  {
+    Uint32 old_gci_hi = subbPtr.p->m_sub_stop_conf.gci_hi;
+    Uint32 old_gci_lo = subbPtr.p->m_sub_stop_conf.gci_lo;
+    old_gci = old_gci_lo | (Uint64(old_gci_hi) << 32);
+    if (signal->getLength() >= SubStopConf::SignalLengthWithGci)
+    {
+      Uint32 new_gci_hi = conf->gci_hi;
+      Uint32 new_gci_lo = conf->gci_lo;
+      new_gci = new_gci_lo | (Uint64(new_gci_hi) << 32);
+    }
+  }
   subbPtr.p->m_sub_stop_conf = *conf;
+  if (old_gci > new_gci)
+  {
+    subbPtr.p->m_sub_stop_conf.gci_hi= Uint32(old_gci>>32);
+    subbPtr.p->m_sub_stop_conf.gci_lo= Uint32(old_gci);
+  }
   subbPtr.p->m_reqTracker.reportConf(c_counterMgr, refToNode(senderRef));
   completeSubStopReq(signal,subbPtr.i,0);
 }
@@ -22187,9 +22226,6 @@ void
 Dbdict::execSCHEMA_TRANS_BEGIN_REQ(Signal* signal)
 {
   jamEntry();
-
-  g_eventLogger->info("QQQ(%u) - Dbdict::execSCHEMA_TRANS_BEGIN_REQ", __LINE__);
-
   const SchemaTransBeginReq* req =
     (const SchemaTransBeginReq*)signal->getDataPtr();
   Uint32 clientRef = req->clientRef;
@@ -22299,7 +22335,6 @@ Dbdict::execSCHEMA_TRANS_BEGIN_REQ(Signa
       req->requestInfo = SchemaTransImplReq::RT_START;
       req->start.clientRef = trans_ptr.p->m_clientRef;
       req->transId = trans_ptr.p->m_transId;
-      g_eventLogger->info("QQQ(%u) - GSN_SCHEMA_TRANS_IMPL_REQ", __LINE__);
       sendSignal(rg, GSN_SCHEMA_TRANS_IMPL_REQ, signal,
                  SchemaTransImplReq::SignalLength, JBB);
     }
@@ -22363,9 +22398,6 @@ void
 Dbdict::execSCHEMA_TRANS_END_REQ(Signal* signal)
 {
   jamEntry();
-
-  g_eventLogger->info("QQQ(%u) - execSCHEMA_TRANS_END_REQ", __LINE__);
-
   const SchemaTransEndReq* req =
     (const SchemaTransEndReq*)signal->getDataPtr();
   Uint32 clientRef = req->clientRef;
@@ -22566,7 +22598,6 @@ Dbdict::handleClientReq(Signal* signal, 
   req->requestInfo = requestInfo;
   req->transId = trans_ptr.p->m_transId;
   req->parse.gsn = gsn;
-  g_eventLogger->info("QQQ(%u) - GSN_SCHEMA_TRANS_IMPL_REQ", __LINE__);
   sendFragmentedSignal(rg, GSN_SCHEMA_TRANS_IMPL_REQ, signal,
                        SchemaTransImplReq::SignalLength + extra_length, JBB,
                        &handle);
@@ -22611,7 +22642,6 @@ void
 Dbdict::execSCHEMA_TRANS_IMPL_CONF(Signal* signal)
 {
   jamEntry();
-  g_eventLogger->info("QQQ(%u) - execSCHEMA_TRANS_IMPL_CONF", __LINE__);
   ndbrequire(signal->getNoOfSections() == 0);
 
   const SchemaTransImplConf* conf =
@@ -22638,7 +22668,6 @@ void
 Dbdict::execSCHEMA_TRANS_IMPL_REF(Signal* signal)
 {
   jamEntry();
-  g_eventLogger->info("QQQ(%u) - execSCHEMA_TRANS_IMPL_REF", __LINE__);
   ndbrequire(signal->getNoOfSections() == 0);
 
   const SchemaTransImplRef* ref =
@@ -22966,7 +22995,6 @@ Dbdict::trans_prepare_start(Signal* sign
   req->opKey = RNIL;
   req->requestInfo = SchemaTransImplReq::RT_FLUSH_PREPARE;
   req->transId = trans_ptr.p->m_transId;
-  g_eventLogger->info("QQQ(%u) - GSN_SCHEMA_TRANS_IMPL_REQ", __LINE__);
   sendSignal(rg, GSN_SCHEMA_TRANS_IMPL_REQ, signal,
              SchemaTransImplReq::SignalLength, JBB);
 }
@@ -23052,7 +23080,6 @@ Dbdict::trans_prepare_next(Signal* signa
   req->opKey = op_ptr.p->op_key;
   req->requestInfo = SchemaTransImplReq::RT_PREPARE;
   req->transId = trans_ptr.p->m_transId;
-  g_eventLogger->info("QQQ(%u) - GSN_SCHEMA_TRANS_IMPL_REQ", __LINE__);
   sendSignal(rg, GSN_SCHEMA_TRANS_IMPL_REQ, signal,
              SchemaTransImplReq::SignalLength, JBB);
 }
@@ -23258,7 +23285,6 @@ Dbdict::trans_abort_parse_next(Signal* s
   req->opKey = op_ptr.p->op_key;
   req->requestInfo = SchemaTransImplReq::RT_ABORT_PARSE;
   req->transId = trans_ptr.p->m_transId;
-  g_eventLogger->info("QQQ(%u) - GSN_SCHEMA_TRANS_IMPL_REQ", __LINE__);
   sendSignal(rg, GSN_SCHEMA_TRANS_IMPL_REQ, signal,
              SchemaTransImplReq::SignalLength, JBB);
 }
@@ -23447,7 +23473,6 @@ Dbdict::trans_abort_prepare_next(Signal*
   req->opKey = op_ptr.p->op_key;
   req->requestInfo = SchemaTransImplReq::RT_ABORT_PREPARE;
   req->transId = trans_ptr.p->m_transId;
-  g_eventLogger->info("QQQ(%u) - GSN_SCHEMA_TRANS_IMPL_REQ", __LINE__);
   sendSignal(rg, GSN_SCHEMA_TRANS_IMPL_REQ, signal,
              SchemaTransImplReq::SignalLength, JBB);
 }
@@ -23582,7 +23607,6 @@ Dbdict::trans_rollback_sp_next(Signal* s
   req->opKey = op_ptr.p->op_key;
   req->requestInfo = SchemaTransImplReq::RT_ABORT_PARSE;
   req->transId = trans_ptr.p->m_transId;
-  g_eventLogger->info("QQQ(%u) - GSN_SCHEMA_TRANS_IMPL_REQ", __LINE__);
   sendSignal(rg, GSN_SCHEMA_TRANS_IMPL_REQ, signal,
              SchemaTransImplReq::SignalLength, JBB);
 
@@ -23691,7 +23715,6 @@ Dbdict::trans_commit_start(Signal* signa
   req->opKey = RNIL;
   req->requestInfo = SchemaTransImplReq::RT_FLUSH_COMMIT;
   req->transId = trans_ptr.p->m_transId;
-  g_eventLogger->info("QQQ(%u) - GSN_SCHEMA_TRANS_IMPL_REQ", __LINE__);
   sendSignal(rg, GSN_SCHEMA_TRANS_IMPL_REQ, signal,
              SchemaTransImplReq::SignalLength, JBB);
 }
@@ -23886,7 +23909,6 @@ Dbdict::trans_commit_next(Signal* signal
     */
     rg.m_nodes.clear(getOwnNodeId());
 
-    g_eventLogger->info("QQQ(%u) - GSN_SCHEMA_TRANS_IMPL_REQ", __LINE__);
     sendSignal(rg, GSN_SCHEMA_TRANS_IMPL_REQ, signal,
                SchemaTransImplReq::SignalLength, JBB);
     sendSignal(reference(), GSN_SCHEMA_TRANS_IMPL_REQ, signal,
@@ -23897,7 +23919,6 @@ Dbdict::trans_commit_next(Signal* signal
     /*
       New master had already committed operation
      */
-    g_eventLogger->info("QQQ(%u) - GSN_SCHEMA_TRANS_IMPL_REQ", __LINE__);
     sendSignal(rg, GSN_SCHEMA_TRANS_IMPL_REQ, signal,
                SchemaTransImplReq::SignalLength, JBB);
   }
@@ -24072,7 +24093,6 @@ Dbdict::trans_complete_start(Signal* sig
   req->opKey = RNIL;
   req->requestInfo = SchemaTransImplReq::RT_FLUSH_COMPLETE;
   req->transId = trans_ptr.p->m_transId;
-  g_eventLogger->info("QQQ(%u) - GSN_SCHEMA_TRANS_IMPL_REQ", __LINE__);
   sendSignal(rg, GSN_SCHEMA_TRANS_IMPL_REQ, signal,
              SchemaTransImplReq::SignalLength, JBB);
 }
@@ -24154,7 +24174,6 @@ Dbdict::trans_complete_next(Signal* sign
   req->opKey = op_ptr.p->op_key;
   req->requestInfo = SchemaTransImplReq::RT_COMPLETE;
   req->transId = trans_ptr.p->m_transId;
-  g_eventLogger->info("QQQ(%u) - GSN_SCHEMA_TRANS_IMPL_REQ", __LINE__);
   sendSignal(rg, GSN_SCHEMA_TRANS_IMPL_REQ, signal,
              SchemaTransImplReq::SignalLength, JBB);  
 }
@@ -24243,7 +24262,6 @@ Dbdict::trans_end_start(Signal* signal, 
   req->opKey = RNIL;
   req->requestInfo = SchemaTransImplReq::RT_END;
   req->transId = trans_ptr.p->m_transId;
-  g_eventLogger->info("QQQ(%u) - GSN_SCHEMA_TRANS_IMPL_REQ", __LINE__);
   sendSignal(rg, GSN_SCHEMA_TRANS_IMPL_REQ, signal,
              SchemaTransImplReq::SignalLength, JBB);  
 }
@@ -24460,11 +24478,8 @@ Dbdict::execSCHEMA_TRANS_IMPL_REQ(Signal
   jamEntry();
   if (!assembleFragments(signal)) {
     jam();
-    g_eventLogger->info("QQQ(%u) - execSCHEMA_TRANS_IMPL_REQ", __LINE__);
     return;
   }
-  g_eventLogger->info("QQQ(%u) - execSCHEMA_TRANS_IMPL_REQ", __LINE__);
-
   SchemaTransImplReq reqCopy =
     *(const SchemaTransImplReq*)signal->getDataPtr();
   const SchemaTransImplReq *req = &reqCopy;
@@ -25003,7 +25018,6 @@ Dbdict::sendTransConf(Signal* signal, Sc
     return;
   }
 
-  g_eventLogger->info("QQQ(%u) - GSN_SCHEMA_TRANS_IMPL_CONF", __LINE__);
   sendSignal(masterRef, GSN_SCHEMA_TRANS_IMPL_CONF, signal,
              SchemaTransImplConf::SignalLength, JBB);
 }
@@ -25039,7 +25053,6 @@ Dbdict::sendTransRef(Signal* signal, Sch
   resetError(trans_ptr.p->m_error);
 
   const Uint32 masterRef = trans_ptr.p->m_masterRef;
-  g_eventLogger->info("QQQ(%u) - GSN_SCHEMA_TRANS_IMPL_REF", __LINE__);
   sendSignal(masterRef, GSN_SCHEMA_TRANS_IMPL_REF, signal,
              SchemaTransImplRef::SignalLength, JBB);
 }
@@ -25230,7 +25243,6 @@ Dbdict::sendTransClientReply(Signal* sig
       conf->senderRef = reference();
       conf->transId = transId;
       conf->transKey = trans_ptr.p->trans_key;
-      g_eventLogger->info("QQQ(%u) - GSN_SCHEMA_TRANS_BEGIN_CONF", __LINE__);
       sendSignal(receiverRef, GSN_SCHEMA_TRANS_BEGIN_CONF, signal,
                  SchemaTransBeginConf::SignalLength, JBB);
     } else {
@@ -25240,7 +25252,6 @@ Dbdict::sendTransClientReply(Signal* sig
       ref->senderRef = reference();
       ref->transId = transId;
       getError(trans_ptr.p->m_error, ref);
-      g_eventLogger->info("QQQ(%u) - GSN_SCHEMA_TRANS_BEGIN_REF", __LINE__);
       sendSignal(receiverRef, GSN_SCHEMA_TRANS_BEGIN_REF, signal,
                  SchemaTransBeginRef::SignalLength, JBB);
     }
@@ -25256,7 +25267,6 @@ Dbdict::sendTransClientReply(Signal* sig
         (SchemaTransEndConf*)signal->getDataPtrSend();
       conf->senderRef = reference();
       conf->transId = transId;
-      g_eventLogger->info("QQQ(%u) - GSN_SCHEMA_TRANS_END_CONF", __LINE__);
       sendSignal(receiverRef, GSN_SCHEMA_TRANS_END_CONF, signal,
                  SchemaTransEndConf::SignalLength, JBB);
     } else {
@@ -25267,8 +25277,6 @@ Dbdict::sendTransClientReply(Signal* sig
       ref->transId = transId;
       getError(trans_ptr.p->m_error, ref);
       ref->masterNodeId = c_masterNodeId;
-
-      g_eventLogger->info("QQQ(%u) - GSN_SCHEMA_TRANS_END_REF", __LINE__);
       sendSignal(receiverRef, GSN_SCHEMA_TRANS_END_REF, signal,
                  SchemaTransEndRef::SignalLength, JBB);
     }
@@ -25309,7 +25317,6 @@ Dbdict::sendTransClientReply(Signal* sig
 #ifdef VM_TRACE
       ndbout_c("Dbdict::sendTransClientReply: sending GSN_SCHEMA_TRANS_END_REP to 0x%8x", receiverRef);
 #endif
-      g_eventLogger->info("QQQ(%u) - GSN_SCHEMA_TRANS_END_REP", __LINE__);
       sendSignal(receiverRef, GSN_SCHEMA_TRANS_END_REP, signal,
                  SchemaTransEndRep::SignalLength, JBB);
     }
@@ -25384,8 +25391,6 @@ Dbdict::beginSchemaTrans(Signal* signal,
   req->clientRef = reference();
   req->transId = tx_ptr.p->m_transId;
   req->requestInfo = requestInfo;
-
-  g_eventLogger->info("QQQ(%u) - GSN_SCHEMA_TRANS_BEGIN_REQ", __LINE__);
   sendSignal(reference(), GSN_SCHEMA_TRANS_BEGIN_REQ, signal,
              SchemaTransBeginReq::SignalLength, JBB);
 }
@@ -25416,8 +25421,6 @@ Dbdict::endSchemaTrans(Signal* signal, T
   req->transKey = tx_ptr.p->m_transKey;
   req->requestInfo = requestInfo;
   req->flags = flags;
-
-  g_eventLogger->info("QQQ(%u) - GSN_SCHEMA_TRANS_END_REQ", __LINE__);
   sendSignal(reference(), GSN_SCHEMA_TRANS_END_REQ, signal,
              SchemaTransEndReq::SignalLength, JBB);
 }
@@ -25426,7 +25429,6 @@ void
 Dbdict::execSCHEMA_TRANS_BEGIN_CONF(Signal* signal)
 {
   jamEntry(); 
-  g_eventLogger->info("QQQ(%u) - execSCHEMA_TRANS_BEGIN_CONF", __LINE__);
   const SchemaTransBeginConf* conf =
     (const SchemaTransBeginConf*)signal->getDataPtr();
 
@@ -25444,7 +25446,6 @@ void
 Dbdict::execSCHEMA_TRANS_BEGIN_REF(Signal* signal)
 {
   jamEntry();
-  g_eventLogger->info("QQQ(%u) - execSCHEMA_TRANS_BEGIN_REF", __LINE__);
   const SchemaTransBeginRef* ref =
     (const SchemaTransBeginRef*)signal->getDataPtr();
 
@@ -25461,7 +25462,6 @@ void
 Dbdict::execSCHEMA_TRANS_END_CONF(Signal* signal)
 {
   jamEntry();
-  g_eventLogger->info("QQQ(%u) - execSCHEMA_TRANS_END_CONF", __LINE__);
   const SchemaTransEndConf* conf =
     (const SchemaTransEndConf*)signal->getDataPtr();
 
@@ -25476,7 +25476,6 @@ void
 Dbdict::execSCHEMA_TRANS_END_REF(Signal* signal)
 {
   jamEntry();
-  g_eventLogger->info("QQQ(%u) - execSCHEMA_TRANS_END_REF", __LINE__);
   const SchemaTransEndRef* ref =
     (const SchemaTransEndRef*)signal->getDataPtr();
 
@@ -25493,7 +25492,6 @@ void
 Dbdict::execSCHEMA_TRANS_END_REP(Signal* signal)
 {
   jamEntry();
-  g_eventLogger->info("QQQ(%u) - execSCHEMA_TRANS_END_REP", __LINE__);
   const SchemaTransEndRep* rep =
     (const SchemaTransEndRep*)signal->getDataPtr();
 

=== modified file 'storage/ndb/src/kernel/blocks/dblqh/DblqhProxy.cpp'
--- a/storage/ndb/src/kernel/blocks/dblqh/DblqhProxy.cpp	2009-03-16 17:05:07 +0000
+++ b/storage/ndb/src/kernel/blocks/dblqh/DblqhProxy.cpp	2009-03-20 09:58:04 +0000
@@ -228,6 +228,15 @@ DblqhProxy::execLQHADDATTREQ(Signal* sig
   memcpy(&ss.m_req, req, reqlength << 2);
   ss.m_reqlength = reqlength;
 
+  /**
+   * Count LQHFRAGREQ, 
+   *   so that I can release CREATE_TAB_REQ after last attribute has been
+   *   processed
+   */
+  Ss_CREATE_TAB_REQ& ss_main = ssFind<Ss_CREATE_TAB_REQ>(ssId);
+  ndbrequire(ss_main.m_req.noOfAttributes >= req->noOfAttributes);
+  ss_main.m_req.noOfAttributes -= req->noOfAttributes;
+
   sendREQ(signal, ss);
 }
 
@@ -276,13 +285,27 @@ DblqhProxy::sendLQHADDATTCONF(Signal* si
   if (!lastReply(ss))
     return;
 
-  if (ss.m_error == 0) {
+  if (ss.m_error == 0) 
+  {
+    jam();
     LqhAddAttrConf* conf = (LqhAddAttrConf*)signal->getDataPtrSend();
     conf->senderData = ss.m_req.senderData;
     conf->senderAttrPtr = ss.m_req.senderAttrPtr;
     sendSignal(dictRef, GSN_LQHADDATTCONF,
                signal, LqhAddAttrConf::SignalLength, JBB);
-  } else {
+
+    if (ss_main.m_req.noOfAttributes == 0)
+    {
+      jam();
+      /**
+       * All the attributes has been processed
+       *   release create_table object
+       */
+      ssRelease<Ss_CREATE_TAB_REQ>(ssId);
+    }
+  }
+  else 
+  {
     jam();
     LqhAddAttrRef* ref = (LqhAddAttrRef*)signal->getDataPtrSend();
     ref->senderData = ss.m_req.senderData;
@@ -357,8 +380,7 @@ void
 DblqhProxy::sendTAB_COMMITCONF(Signal* signal, Uint32 ssId)
 {
   Ss_TAB_COMMITREQ& ss = ssFind<Ss_TAB_COMMITREQ>(ssId);
-  Ss_CREATE_TAB_REQ& ss_main = ssFind<Ss_CREATE_TAB_REQ>(ssId);
-  BlockReference dictRef = ss_main.m_req.senderRef;
+  BlockReference dictRef = ss.m_req.senderRef;
 
   if (!lastReply(ss))
     return;
@@ -382,7 +404,6 @@ DblqhProxy::sendTAB_COMMITCONF(Signal* s
     return;
   }
 
-  ssRelease<Ss_CREATE_TAB_REQ>(ssId);
   ssRelease<Ss_TAB_COMMITREQ>(ssId);
 }
 

=== modified file 'storage/ndb/src/kernel/blocks/dbtc/Dbtc.hpp'
--- a/storage/ndb/src/kernel/blocks/dbtc/Dbtc.hpp	2009-03-02 09:28:26 +0000
+++ b/storage/ndb/src/kernel/blocks/dbtc/Dbtc.hpp	2009-03-20 15:10:06 +0000
@@ -246,10 +246,11 @@ public:
    * from index table lookup
    */
   enum IndexTransIdAIState {
-    ITAS_WAIT_HEADER = 0,     // Initial state
-    ITAS_WAIT_FRAGID = 1,     // Waiting for fragment id word
-    ITAS_WAIT_KEY = 2,        // Waiting for (more) key information
-    ITAS_ALL_RECEIVED = 3     // All TransIdAI info received
+    ITAS_WAIT_HEADER   = 0,     // Initial state
+    ITAS_WAIT_FRAGID   = 1,     // Waiting for fragment id word
+    ITAS_WAIT_KEY      = 2,     // Waiting for (more) key information
+    ITAS_ALL_RECEIVED  = 3,     // All TransIdAI info received
+    ITAS_WAIT_KEY_FAIL = 4     // Failed collecting key
   };
   
 
@@ -1876,9 +1877,6 @@ private:
   bool testFragmentDrop(Signal* signal);
 #endif
 
-  // For Error inserts
-  Uint32 errorInsertHoardedSegments;
-
   /************************** API CONNECT RECORD ***********************/
   /* *******************************************************************/
   /* THE API CONNECT RECORD CONTAINS THE CONNECTION RECORD TO WHICH THE*/

=== modified file 'storage/ndb/src/kernel/blocks/dbtc/DbtcInit.cpp'
--- a/storage/ndb/src/kernel/blocks/dbtc/DbtcInit.cpp	2008-12-03 19:51:33 +0000
+++ b/storage/ndb/src/kernel/blocks/dbtc/DbtcInit.cpp	2009-03-20 15:10:06 +0000
@@ -331,8 +331,6 @@ Dbtc::Dbtc(Block_context& ctx):
   tcFailRecord = 0;
   c_apiConTimer = 0;
   c_apiConTimer_line = 0;
-
-  errorInsertHoardedSegments= RNIL;
 }//Dbtc::Dbtc()
 
 Dbtc::~Dbtc() 

=== modified file 'storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp'
--- a/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp	2009-03-12 10:59:57 +0000
+++ b/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp	2009-03-24 13:46:34 +0000
@@ -161,6 +161,9 @@ operator<<(NdbOut& out, Dbtc::ScanFragRe
 }
 #endif
 
+extern int ErrorSignalReceive;
+extern int ErrorMaxSegmentsToSeize;
+
 void
 Dbtc::updateBuddyTimer(ApiConnectRecordPtr apiPtr)
 {
@@ -2597,44 +2600,33 @@ void Dbtc::execTCKEYREQ(Signal* signal) 
   UintR TapiConnectptrIndex = apiConnectptr.i;
   UintR TsenderData = tcKeyReq->senderData;
 
-  if (ERROR_INSERTED(8065) || 
-      ERROR_INSERTED(8066) ||
-      ERROR_INSERTED(8067))
-  {
-    /* Consume all but 10(8065) or all but 1 (8066) or all (8067) of 
-     * the SegmentedSection buffers to allow testing of what happens 
-     * when they're exhausted, either in this signal or one to follow
-     * 8068 frees all 'hoarded' segments
-     */
-    Uint32 segmentsToLeave= ERROR_INSERTED(8065)? 
-      10 : 
-      ERROR_INSERTED(8066) ? 
-      1 :
-      0;
-    Uint32 freeSegments= g_sectionSegmentPool.getNoOfFree();
-    DEBUG("Hoarding all but " << segmentsToLeave << 
-          " of " << freeSegments << " free segments");
-    if (freeSegments >= segmentsToLeave)
-    {
-      Uint32 numToAlloc= (g_sectionSegmentPool.getNoOfFree() - segmentsToLeave);
-      Uint32 segmentsIVal= errorInsertHoardedSegments;
-      Uint32 space[SectionSegment::DataLength];
-      
-      while (numToAlloc-- > 0)
-        appendToSection(segmentsIVal, space, SectionSegment::DataLength);
-      
-      errorInsertHoardedSegments= segmentsIVal;
-    }
+  if (ERROR_INSERTED(8065))
+  {
+    ErrorSignalReceive= 1;
+    ErrorMaxSegmentsToSeize= 10;
   }
-
-  if (ERROR_INSERTED(8068) && 
-      (errorInsertHoardedSegments != RNIL))
-  {
-    /* Free the SegmentedSection buffers taken previously */
-    DEBUG("Freeing hoarded segments");
-    releaseSection(errorInsertHoardedSegments);
-    errorInsertHoardedSegments= RNIL;
-  }   
+  if (ERROR_INSERTED(8066))
+  {
+    ErrorSignalReceive= 1;
+    ErrorMaxSegmentsToSeize= 5;
+  }
+  if (ERROR_INSERTED(8067))
+  {
+    ErrorSignalReceive= 1;
+    ErrorMaxSegmentsToSeize= 0;
+  }
+  if (ERROR_INSERTED(8068))
+  {
+    ErrorSignalReceive= 0;
+    ErrorMaxSegmentsToSeize= 0;
+    CLEAR_ERROR_INSERT_VALUE;
+    DEBUG("Max segments to seize cleared");
+  }
+#ifdef ERROR_INSERT
+  if (ErrorSignalReceive)
+    DEBUG("Max segments to seize : " 
+          << ErrorMaxSegmentsToSeize);
+#endif
 
   /* Key and attribute lengths are passed in the header for 
    * short TCKEYREQ and  passed as section lengths for long 
@@ -13424,12 +13416,18 @@ bool  Dbtc::saveTRANSID_AI(Signal* signa
    *                                   -> ITAS_WAIT_KEY
    *
    *   [2..N]   Base table primary    ITAS_WAIT_KEY
-   *            key info               -> [ ITAS_WAIT_KEY ]
+   *            key info               -> [ ITAS_WAIT_KEY |
+   *                                        ITAS_WAIT_KEY_FAIL ]
    *                                   -> ITAS_ALL_RECEIVED
    *
    * The outgoing KeyInfo section contains the base
    * table primary key info, with the fragment id passed
    * as the distribution key.
+   * ITAS_WAIT_KEY_FAIL state is entered when there is no 
+   * space to store received TRANSID_AI information and
+   * key collection must fail.  Transaction abort is performed
+   * once all TRANSID_AI is received, and the system waits in
+   * ITAS_WAIT_KEY_FAIL state until then.
    *
    */
   Uint32 remain= len;
@@ -13469,24 +13467,46 @@ bool  Dbtc::saveTRANSID_AI(Signal* signa
     {
       jam();
       /* Add key information to long section */
-      if (!appendToSection(indexOp->transIdAISectionIVal,
-                           src,
-                           remain))
+      if (appendToSection(indexOp->transIdAISectionIVal,
+                          src,
+                          remain))
+      {
+        jam();
+        remain= 0;
+        break;
+      }
+      else
       {
         jam();
 #ifdef VM_TRACE
-        ndbout_c("Dbtc::saveTRANSID_AI: Failed to seize beffer for TRANSID_AI\n");
+        ndbout_c("Dbtc::saveTRANSID_AI: Failed to seize buffer for TRANSID_AI\n");
 #endif
-        apiConnectptr.i = indexOp->connectionIndex;
-        ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
-        releaseIndexOperation(apiConnectptr.p, indexOp);
-        terrorCode = ZGET_DATAREC_ERROR;
-        abortErrorLab(signal);
-        return false;
+        indexOp->transIdAIState= ITAS_WAIT_KEY_FAIL;
+        /* Fall through to ITAS_WAIT_KEY_FAIL state handling */
       }
+    }
 
-      remain= 0;
-      break;
+    case ITAS_WAIT_KEY_FAIL:
+    {
+      /* Failed when collecting key previously - if we have all the
+       * TRANSID_AI now then we abort
+       */
+      if (indexOp->pendingTransIdAI > len)
+      {
+        /* Still some TransIdAI to arrive, keep waiting as if we had
+         * stored it
+         */
+        remain= 0;
+        break;
+      }
+
+      /* All TransIdAI has arrived, abort */
+      apiConnectptr.i = indexOp->connectionIndex;
+      ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
+      releaseIndexOperation(apiConnectptr.p, indexOp);
+      terrorCode = ZGET_DATAREC_ERROR;
+      abortErrorLab(signal);
+      return false;
     }
 
     case ITAS_ALL_RECEIVED:
@@ -13789,7 +13809,7 @@ void Dbtc::execTRANSID_AI(Signal* signal
       tcIndxRef->connectPtr = indexOp->tcIndxReq.senderData;
       tcIndxRef->transId[0] = regApiPtr->transid[0];
       tcIndxRef->transId[1] = regApiPtr->transid[1];
-      tcIndxRef->errorCode = 4000;
+      tcIndxRef->errorCode = ZGET_DATAREC_ERROR;
       tcIndxRef->errorData = 0;
       sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
                  TcKeyRef::SignalLength, JBB);

=== modified file 'storage/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp'
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp	2009-02-11 15:07:28 +0000
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp	2009-03-24 08:42:42 +0000
@@ -33,6 +33,9 @@
 #include <signaldata/DropTab.hpp>
 #include <SLList.hpp>
 
+#include <EventLogger.hpp>
+extern EventLogger * g_eventLogger;
+
 #define DEBUG(x) { ndbout << "TUP::" << x << endl; }
 
 void Dbtup::initData() 
@@ -231,6 +234,7 @@ void Dbtup::execCONTINUEB(Signal* signal
   jamEntry();
   Uint32 actionType = signal->theData[0];
   Uint32 dataPtr = signal->theData[1];
+
   switch (actionType) {
   case ZINITIALISE_RECORDS:
     jam();
@@ -256,7 +260,6 @@ void Dbtup::execCONTINUEB(Signal* signal
   case ZFREE_EXTENT:
   {
     jam();
-    
     TablerecPtr tabPtr;
     tabPtr.i= dataPtr;
     FragrecordPtr fragPtr;
@@ -269,7 +272,6 @@ void Dbtup::execCONTINUEB(Signal* signal
   case ZUNMAP_PAGES:
   {
     jam();
-    
     TablerecPtr tabPtr;
     tabPtr.i= dataPtr;
     FragrecordPtr fragPtr;

=== modified file 'storage/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp'
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp	2008-11-16 12:29:39 +0000
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp	2009-03-24 08:42:42 +0000
@@ -36,6 +36,9 @@
 #include <my_sys.h>
 #include <signaldata/LqhFrag.hpp>
 
+#include <EventLogger.hpp>
+extern EventLogger * g_eventLogger;
+
 void
 Dbtup::execCREATE_TAB_REQ(Signal* signal)
 {

=== modified file 'storage/ndb/src/kernel/blocks/dbtup/DbtupProxy.cpp'
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupProxy.cpp	2009-03-16 17:05:07 +0000
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupProxy.cpp	2009-03-24 08:42:42 +0000
@@ -21,6 +21,9 @@
 #include <pgman.hpp>
 #include <signaldata/LgmanContinueB.hpp>
 
+#include <EventLogger.hpp>
+extern EventLogger * g_eventLogger;
+
 DbtupProxy::DbtupProxy(Block_context& ctx) :
   LocalProxy(DBTUP, ctx),
   c_pgman(0),

=== modified file 'storage/ndb/src/kernel/blocks/lgman.cpp'
--- a/storage/ndb/src/kernel/blocks/lgman.cpp	2009-03-14 20:42:04 +0000
+++ b/storage/ndb/src/kernel/blocks/lgman.cpp	2009-03-24 08:42:42 +0000
@@ -1151,6 +1151,7 @@ Logfile_client::Logfile_client(Simulated
 {
   Uint32 bno = block->number();
   Uint32 ino = block->instance();
+  m_client_block= block;
   m_block= numberToBlock(bno, ino);
   m_lgman= lgman;
   m_lock = lock;
@@ -1210,8 +1211,8 @@ Logfile_client::sync_lsn(Signal* signal,
       signal->theData[1] = ptr.i;
       signal->theData[2] = (Uint32)(lsn >> 32);
       signal->theData[3] = (Uint32)(lsn & 0xFFFFFFFF);
-      m_lgman->sendSignalWithDelay(m_lgman->reference(), 
-				   GSN_CONTINUEB, signal, 10, 4);
+      m_client_block->sendSignalWithDelay(m_lgman->reference(), 
+                                          GSN_CONTINUEB, signal, 10, 4);
     }
     return 0;
   }

=== modified file 'storage/ndb/src/kernel/blocks/lgman.hpp'
--- a/storage/ndb/src/kernel/blocks/lgman.hpp	2008-11-16 15:29:16 +0000
+++ b/storage/ndb/src/kernel/blocks/lgman.hpp	2009-03-24 08:33:25 +0000
@@ -321,6 +321,7 @@ private:
 };
 
 class Logfile_client {
+  SimulatedBlock *m_client_block;
   Uint32 m_block; // includes instance
   Lgman * m_lgman;
   bool m_lock;

=== modified file 'storage/ndb/src/kernel/blocks/suma/Suma.cpp'
--- a/storage/ndb/src/kernel/blocks/suma/Suma.cpp	2009-03-14 20:42:04 +0000
+++ b/storage/ndb/src/kernel/blocks/suma/Suma.cpp	2009-03-20 08:36:40 +0000
@@ -3468,8 +3468,11 @@ Suma::report_sub_stop_conf(Signal* signa
   }
   
   SubStopConf * const conf = (SubStopConf*)signal->getDataPtrSend();
+  const Uint64 gci = m_max_seen_gci;
   conf->senderRef= reference();
   conf->senderData= senderData;
+  conf->gci_hi= Uint32(gci>>32);
+  conf->gci_lo= Uint32(gci);
   sendSignal(senderRef, GSN_SUB_STOP_CONF, signal,
 	     SubStopConf::SignalLength, JBB);
 

=== modified file 'storage/ndb/src/kernel/vm/LongSignal.cpp'
--- a/storage/ndb/src/kernel/vm/LongSignal.cpp	2008-10-08 19:09:05 +0000
+++ b/storage/ndb/src/kernel/vm/LongSignal.cpp	2009-03-20 17:03:34 +0000
@@ -179,6 +179,9 @@ dupSection(SPC_ARG Uint32& copyFirstIVal
   return true;
 }
 
+extern int ErrorSignalReceive;
+extern int ErrorMaxSegmentsToSeize;
+
 /**
  * appendToSection
  * Append supplied words to the chain of section segments
@@ -211,6 +214,15 @@ appendToSection(SPC_ARG Uint32& firstSeg
 
   if (firstSegmentIVal == RNIL)
   {
+#ifdef ERROR_INSERT
+    /* Simulate running out of segments */
+    if ((ErrorSignalReceive == 1) && 
+        (ErrorMaxSegmentsToSeize == 0))
+    {
+      ndbout_c("append exhausted on first segment");
+      return false;
+    }
+#endif
     /* First data to be added to this section */
     bool result= g_sectionSegmentPool.seize(SPC_SEIZE_ARG firstPtr);
 
@@ -245,6 +257,10 @@ appendToSection(SPC_ARG Uint32& firstSeg
 
   firstPtr.p->m_sz+= len;
 
+#ifdef ERROR_INSERT
+  Uint32 remainSegs= (Uint32) ErrorMaxSegmentsToSeize - 1;
+#endif
+
   while(len > remain) {
     /* Fill this segment, and link in another one
      * Note that we can memcpy to a bad address with size 0
@@ -253,6 +269,18 @@ appendToSection(SPC_ARG Uint32& firstSeg
     src += remain;
     len -= remain;
     Ptr<SectionSegment> prevPtr= currPtr;
+
+#ifdef ERROR_INSERT
+    /* Simulate running out of segments */
+    if ((ErrorSignalReceive == 1) && 
+        (0 == remainSegs--))
+    {
+      ndbout_c("Append exhausted on segment %d", ErrorMaxSegmentsToSeize);
+      firstPtr.p->m_lastSegment= prevPtr.i;
+      firstPtr.p->m_sz-= len;
+      return false;
+    }
+#endif
     bool result = g_sectionSegmentPool.seize(SPC_SEIZE_ARG currPtr);
     if (!result)
     {
@@ -282,6 +310,16 @@ appendToSection(SPC_ARG Uint32& firstSeg
 bool
 import(SPC_ARG Ptr<SectionSegment> & first, const Uint32 * src, Uint32 len){
 
+#ifdef ERROR_INSERT
+  /* Simulate running out of segments */
+  if ((ErrorSignalReceive == 1) &&
+      (ErrorMaxSegmentsToSeize == 0))
+  {
+    ndbout_c("Import exhausted on first segment");
+    return false;
+  }
+#endif
+
   first.p = 0;
   if(g_sectionSegmentPool.seize(SPC_SEIZE_ARG first)){
     ;
@@ -295,11 +333,30 @@ import(SPC_ARG Ptr<SectionSegment> & fir
 
   Ptr<SectionSegment> currPtr = first;
 
+#ifdef ERROR_INSERT
+  Uint32 remainSegs= (Uint32) ErrorMaxSegmentsToSeize - 1;
+#endif
+
   while(len > SectionSegment::DataLength){
     memcpy(&currPtr.p->theData[0], src, 4 * SectionSegment::DataLength);
     src += SectionSegment::DataLength;
     len -= SectionSegment::DataLength;
     Ptr<SectionSegment> prevPtr = currPtr;
+
+#ifdef ERROR_INSERT
+    /* Simulate running out of segments */
+    if ((ErrorSignalReceive == 1) &&
+        (0 == remainSegs--))
+    {
+      ndbout_c("Import exhausted on segment %d", 
+               ErrorMaxSegmentsToSeize);
+      first.p->m_lastSegment= prevPtr.i;
+      first.p->m_sz-= len;
+      prevPtr.p->m_nextSegment = RNIL;
+      return false;
+    }
+#endif
+
     if(g_sectionSegmentPool.seize(SPC_SEIZE_ARG currPtr)){
       prevPtr.p->m_nextSegment = currPtr.i;
       ;

=== modified file 'storage/ndb/src/kernel/vm/TransporterCallback.cpp'
--- a/storage/ndb/src/kernel/vm/TransporterCallback.cpp	2009-03-14 20:42:04 +0000
+++ b/storage/ndb/src/kernel/vm/TransporterCallback.cpp	2009-03-20 17:03:34 +0000
@@ -39,6 +39,12 @@
  */
 SectionSegmentPool g_sectionSegmentPool;
 
+/* Instance debugging vars
+ * Set from DBTC
+ */
+int ErrorSignalReceive= 0;
+int ErrorMaxSegmentsToSeize= 0;
+
 struct ConnectionError
 {
   enum TransporterError err;

=== modified file 'storage/ndb/src/mgmsrv/ConfigInfo.cpp'
--- a/storage/ndb/src/mgmsrv/ConfigInfo.cpp	2009-03-19 14:12:15 +0000
+++ b/storage/ndb/src/mgmsrv/ConfigInfo.cpp	2009-03-24 13:48:39 +0000
@@ -25,6 +25,7 @@
 #include <m_string.h>
 #include <Bitmask.hpp>
 #include <ndb_opts.h>
+#include <ndb_version.h>
 
 #else
 #include "ConfigInfo.hpp"
@@ -2800,10 +2801,6 @@ ConfigInfo::ConfigInfo()
     pinfo.put("Type",        param._type);
     pinfo.put("Status",      param._status);
 
-    if(param._default == MANDATORY){
-      pinfo.put("Mandatory", (Uint32)1);
-    }
-
     switch (param._type) {
       case CI_BOOL:
       {
@@ -2812,6 +2809,16 @@ ConfigInfo::ConfigInfo()
 	pinfo.put64("Min", tmp_bool);
 	require(InitConfigFileParser::convertStringToBool(param._max, tmp_bool));
 	pinfo.put64("Max", tmp_bool);
+
+        if(param._default == MANDATORY)
+          pinfo.put("Mandatory", (Uint32)1);
+        else if(param._default != UNDEFINED)
+        {
+          require(InitConfigFileParser::convertStringToBool(param._default,
+                                                            tmp_bool));
+          pinfo.put("Default", tmp_bool);
+        }
+
 	break;
       }
       case CI_INT:
@@ -2822,12 +2829,25 @@ ConfigInfo::ConfigInfo()
 	pinfo.put64("Min", tmp_uint64);
 	require(InitConfigFileParser::convertStringToUint64(param._max, tmp_uint64));
 	pinfo.put64("Max", tmp_uint64);
+
+        if(param._default == MANDATORY)
+          pinfo.put("Mandatory", (Uint32)1);
+        else if(param._default != UNDEFINED)
+        {
+          require(InitConfigFileParser::convertStringToUint64(param._default,
+                                                              tmp_uint64));
+          pinfo.put64("Default", tmp_uint64);
+        }
 	break;
       }
       case CI_SECTION:
 	pinfo.put("SectionType", (Uint32)UintPtr(param._default));
 	break;
       case CI_STRING:
+        if(param._default == MANDATORY)
+          pinfo.put("Mandatory", (Uint32)1);
+        else if(param._default != UNDEFINED)
+          pinfo.put("Default", param._default);
 	break;
     }
 
@@ -2864,6 +2884,7 @@ ConfigInfo::ConfigInfo()
 	    {
 	      require(InitConfigFileParser::convertStringToBool(param._default, default_bool));
 	      require(p->put(param._fname, default_bool));
+
 	      break;
 	    }
 	  case CI_INT:
@@ -2984,8 +3005,28 @@ ConfigInfo::getDefault(const Properties 
 }
 
 const char*
-ConfigInfo::getDescription(const Properties * section, 
-			   const char* fname) const {
+ConfigInfo::getDefaultString(const Properties * section,
+                             const char* fname) const {
+  return getInfoString(section, fname, "Default");
+}
+
+bool
+ConfigInfo::hasDefault(const Properties * section, const char* fname) const {
+  const Properties * p;
+  require(section->get(fname, &p));
+  return p->contains("Default");
+}
+
+bool
+ConfigInfo::getMandatory(const Properties * section, const char* fname) const {
+  const Properties * p;
+  require(section->get(fname, &p));
+  return p->contains("Mandatory");
+}
+
+const char*
+ConfigInfo::getDescription(const Properties * section,
+                           const char* fname) const {
   return getInfoString(section, fname, "Description");
 }
 
@@ -3094,77 +3135,268 @@ ConfigInfo::getStatus(const Properties *
  * Printers
  ****************************************************************************/
 
-void ConfigInfo::print() const {
-  Properties::Iterator it(&m_info);
-  for (const char* n = it.first(); n != NULL; n = it.next()) {
-    print(n);
+class ConfigPrinter {
+protected:
+  FILE* m_out;
+public:
+  ConfigPrinter(FILE* out = stdout) :
+    m_out(out)
+    {}
+  virtual ~ConfigPrinter() {};
+
+  virtual void start() {}
+  virtual void end() {}
+
+  virtual void section_start(const char* name, const char* alias) {}
+  virtual void section_end(const char* name) {}
+
+  virtual void parameter(const char* section_name,
+                         const Properties* section,
+                         const char* param_name,
+                         const ConfigInfo& info){}
+};
+
+
+class PrettyPrinter : public ConfigPrinter {
+public:
+  PrettyPrinter(FILE* out = stdout) : ConfigPrinter(out) {}
+  virtual ~PrettyPrinter() {}
+
+  virtual void section_start(const char* name, const char* alias) {
+    fprintf(m_out, "****** %s ******\n\n", name);
+  }
+
+  virtual void parameter(const char* section_name,
+                         const Properties* section,
+                         const char* param_name,
+                         const ConfigInfo& info){
+    switch (info.getType(section, param_name)) {
+    case ConfigInfo::CI_BOOL:
+      fprintf(m_out, "%s (Boolean value)\n", param_name);
+      fprintf(m_out, "%s\n", info.getDescription(section, param_name));
+
+      if (info.getMandatory(section, param_name))
+        fprintf(m_out, "MANDATORY (Legal values: Y, N)\n");
+      else if (info.hasDefault(section, param_name))
+      {
+        if (info.getDefault(section, param_name) == false)
+          fprintf(m_out, "Default: N (Legal values: Y, N)\n");
+        else if (info.getDefault(section, param_name) == true)
+          fprintf(m_out, "Default: Y (Legal values: Y, N)\n");
+        else
+          fprintf(m_out, "UNKNOWN\n");
+      }
+      fprintf(m_out, "\n");
+      break;
+
+    case ConfigInfo::CI_INT:
+    case ConfigInfo::CI_INT64:
+      fprintf(m_out, "%s (Non-negative Integer)\n", param_name);
+      fprintf(m_out, "%s\n", info.getDescription(section, param_name));
+      if (info.getMandatory(section, param_name))
+        fprintf(m_out, "MANDATORY (");
+      else if (info.hasDefault(section, param_name))
+        fprintf(m_out, "Default: %llu (",
+                info.getDefault(section, param_name));
+      else
+        fprintf(m_out, "(");
+      fprintf(m_out, "Min: %llu, ", info.getMin(section, param_name));
+      fprintf(m_out, "Max: %llu)\n", info.getMax(section, param_name));
+      fprintf(m_out, "\n");
+      break;
+
+    case ConfigInfo::CI_STRING:
+      fprintf(m_out, "%s (String)\n", param_name);
+      fprintf(m_out, "%s\n", info.getDescription(section, param_name));
+      if (info.getMandatory(section, param_name))
+        fprintf(m_out, "MANDATORY\n");
+      else if (info.hasDefault(section, param_name))
+        fprintf(m_out, "Default: %s\n",
+              info.getDefaultString(section, param_name));
+      fprintf(m_out, "\n");
+      break;
+    case ConfigInfo::CI_SECTION:
+      break;
+    }
   }
-}
+};
+
+
+class XMLPrinter : public ConfigPrinter {
+  int m_indent;
+
+  void print_xml(const char* name, const Properties& pairs,
+                 bool close = true) {
+    const char* value;
+    Properties::Iterator it(&pairs);
+    for (int i= 0; i < m_indent; i++)
+      fprintf(m_out, "  ");
+    fprintf(m_out, "<%s", name);
+    for (const char* name = it.first(); name != NULL; name = it.next()) {
+      require(pairs.get(name, &value));
+      fprintf(m_out, " %s=\"%s\"", name, value);
+    }
+    if (close)
+      fprintf(m_out, "/");
+    fprintf(m_out, ">\n");
+  }
+
+public:
+  XMLPrinter(FILE* out = stdout) : ConfigPrinter(out), m_indent(0) {}
+  virtual ~XMLPrinter() {
+    assert(m_indent == 0);
+  }
+
+  virtual void start() {
+    BaseString buf;
+    Properties pairs;
+    pairs.put("protocolversion", "1");
+    pairs.put("ndbversionstring", ndbGetOwnVersionString());
+    Uint32 ndbversion = ndbGetOwnVersion();
+    buf.assfmt("%u", ndbversion);
+    pairs.put("ndbversion", buf.c_str());
+    buf.assfmt("%u", ndbGetMajor(ndbversion));
+    pairs.put("ndbversionmajor", buf.c_str());
+    buf.assfmt("%u", ndbGetMinor(ndbversion));
+    pairs.put("ndbversionminor", buf.c_str());
+    buf.assfmt("%u", ndbGetBuild(ndbversion));
+    pairs.put("ndbversionbuild", buf.c_str());
+
+    print_xml("configvariables", pairs, false);
+    m_indent++;
+  }
+  virtual void end() {
+    m_indent--;
+    Properties pairs;
+    print_xml("/configvariables", pairs, false);
+  }
+
+  virtual void section_start(const char* name, const char* alias) {
+    Properties pairs;
+    pairs.put("name", alias ? alias : name);
+    print_xml("section", pairs, false);
+    m_indent++;
+  }
+  virtual void section_end(const char* name) {
+    m_indent--;
+    Properties pairs;
+    print_xml("/section", pairs, false);
+  }
+
+  virtual void parameter(const char* section_name,
+                         const Properties* section,
+                         const char* param_name,
+                         const ConfigInfo& info){
+    BaseString buf;
+    Properties pairs;
+    pairs.put("name", param_name);
+    pairs.put("comment", info.getDescription(section, param_name));
+
+    switch (info.getType(section, param_name)) {
+    case ConfigInfo::CI_BOOL:
+      pairs.put("type", "bool");
+
+      if (info.getMandatory(section, param_name))
+        pairs.put("mandatory", "true");
+      else if (info.hasDefault(section, param_name))
+      {
+        if (info.getDefault(section, param_name) == false)
+          pairs.put("default", "false");
+        else if (info.getDefault(section, param_name) == true)
+          pairs.put("default", "true");
+      }
+      break;
+
+    case ConfigInfo::CI_INT:
+    case ConfigInfo::CI_INT64:
+      pairs.put("type", "unsigned");
+
+      if (info.getMandatory(section, param_name))
+        pairs.put("mandatory", "true");
+      else if (info.hasDefault(section, param_name))
+      {
+        buf.assfmt("%llu", info.getDefault(section, param_name));
+        pairs.put("default", buf.c_str());
+      }
+      buf.assfmt("%llu", info.getMin(section, param_name));
+      pairs.put("min", buf.c_str());
+      buf.assfmt("%llu", info.getMax(section, param_name));
+      pairs.put("max", buf.c_str());
+    break;
+
+    case ConfigInfo::CI_STRING:
+      pairs.put("type", "string");
+
+      if (info.getMandatory(section, param_name))
+        pairs.put("mandatory", "true");
+      else if (info.hasDefault(section, param_name))
+        pairs.put("default", info.getDefaultString(section, param_name));
+      break;
+
+    case ConfigInfo::CI_SECTION:
+      return; // Don't print anything for the section itself
+    }
+    print_xml("param", pairs);
+  }
+};
 
 void ConfigInfo::print(const char* section) const {
-  ndbout << "****** " << section << " ******" << endl << endl;
-  const Properties * sec = getInfo(section);
+  PrettyPrinter pretty_printer;
+  print_impl(section, pretty_printer);
+}
+
+void ConfigInfo::print_xml(const char* section) const {
+  XMLPrinter xml_printer;
+  print_impl(section, xml_printer);
+}
+
+
+bool
+ConfigInfo::is_internal_section(const Properties* sec) const
+{
+  /* Check if the section is marked as internal */
   Properties::Iterator it(sec);
   for (const char* n = it.first(); n != NULL; n = it.next()) {
-    // Skip entries with different F- and P-names
-    if (getStatus(sec, n) == ConfigInfo::CI_INTERNAL) continue;
-    if (getStatus(sec, n) == ConfigInfo::CI_DEPRICATED) continue;
-    if (getStatus(sec, n) == ConfigInfo::CI_NOTIMPLEMENTED) continue;
-    print(sec, n);
+    if (getStatus(sec, n) == ConfigInfo::CI_INTERNAL &&
+        getType(sec, n) == ConfigInfo:: CI_SECTION)
+      return true;
   }
+  return false;
 }
 
-void ConfigInfo::print(const Properties * section, 
-		       const char* parameter) const {
-  ndbout << parameter;
-  //  ndbout << getDescription(section, parameter) << endl;
-  switch (getType(section, parameter)) {
-  case ConfigInfo::CI_BOOL:
-    ndbout << " (Boolean value)" << endl;
-    ndbout << getDescription(section, parameter) << endl;
-    if (getDefault(section, parameter) == false) {
-      ndbout << "Default: N (Legal values: Y, N)" << endl; 
-    } else if (getDefault(section, parameter) == true) {
-      ndbout << "Default: Y (Legal values: Y, N)" << endl;
-    } else if (getDefault(section, parameter) == (UintPtr)MANDATORY) {
-      ndbout << "MANDATORY (Legal values: Y, N)" << endl;
-    } else {
-      ndbout << "UNKNOWN" << endl;
-    }
-    ndbout << endl;
-    break;    
-    
-  case ConfigInfo::CI_INT:
-  case ConfigInfo::CI_INT64:
-    ndbout << " (Non-negative Integer)" << endl;
-    ndbout << getDescription(section, parameter) << endl;
-    if (getDefault(section, parameter) == (UintPtr)MANDATORY) {
-      ndbout << "MANDATORY (";
-    } else if (getDefault(section, parameter) == (UintPtr)UNDEFINED) {
-      ndbout << "UNDEFINED (";
-    } else {
-      ndbout << "Default: " << getDefault(section, parameter) << " (";
-    }
-    ndbout << "Min: " << getMin(section, parameter) << ", ";
-    ndbout << "Max: " << getMax(section, parameter) << ")" << endl;
-    ndbout << endl;
-    break;
-    
-  case ConfigInfo::CI_STRING:
-    ndbout << " (String)" << endl;
-    ndbout << getDescription(section, parameter) << endl;
-    if (getDefault(section, parameter) == (UintPtr)MANDATORY) {
-      ndbout << "MANDATORY" << endl;
-    } else {
-      ndbout << "No default value" << endl;
+
+void ConfigInfo::print_impl(const char* section_filter,
+                            ConfigPrinter& printer) const {
+  printer.start();
+  /* Iterate through all sections */
+  Properties::Iterator it(&m_info);
+  for (const char* s = it.first(); s != NULL; s = it.next()) {
+    if (section_filter && strcmp(section_filter, s))
+      continue; // Skip this section
+
+    const Properties * sec = getInfo(s);
+
+    if (is_internal_section(sec))
+      continue; // Skip whole section
+
+    printer.section_start(s, nameToAlias(s));
+
+    /* Iterate through all parameters in section */
+    Properties::Iterator it(sec);
+    for (const char* n = it.first(); n != NULL; n = it.next()) {
+      // Skip entries with different F- and P-names
+      if (getStatus(sec, n) == ConfigInfo::CI_INTERNAL) continue;
+      if (getStatus(sec, n) == ConfigInfo::CI_DEPRICATED) continue;
+      if (getStatus(sec, n) == ConfigInfo::CI_NOTIMPLEMENTED) continue;
+      printer.parameter(s, sec, n, *this);
     }
-    ndbout << endl;
-    break;
-  case ConfigInfo::CI_SECTION:
-    break;
+    printer.section_end(s);
   }
+  printer.end();
 }
 
+
+
 /****************************************************************************
  * Section Rules
  ****************************************************************************/

=== modified file 'storage/ndb/src/mgmsrv/ConfigInfo.hpp'
--- a/storage/ndb/src/mgmsrv/ConfigInfo.hpp	2008-11-10 14:43:52 +0000
+++ b/storage/ndb/src/mgmsrv/ConfigInfo.hpp	2009-03-20 09:57:27 +0000
@@ -156,17 +156,23 @@ public:
   Status       getStatus(const Properties* section, const char* fname) const;
   Uint64       getMin(const Properties * section, const char* fname) const;
   Uint64       getMax(const Properties * section, const char* fname) const;
-  Uint64       getDefault(const Properties * section, const char* fname) const;
-  
+  Uint64 getDefault(const Properties * section, const char* fname) const;
+  const char* getDefaultString(const Properties * section,
+                               const char* fname) const;
+  bool getMandatory(const Properties * section, const char* fname) const;
+  bool hasDefault(const Properties * section, const char* fname) const;
+
   const Properties * getInfo(const char * section) const;
   const Properties * getDefaults(const char * section) const;
-  
-  void print() const;
-  void print(const char* section) const;
-  void print(const Properties * section, const char* parameter) const;
 
-  const char* sectionName(Uint32 section, Uint32 type) const;
+  const char* sectionName(Uint32 section_type, Uint32 type) const;
 
+  void print(const char* section= NULL) const;
+  void print_xml(const char* section= NULL) const;
+private:
+  bool is_internal_section(const Properties* sec) const;
+  void print_impl(const char* section,
+                  class ConfigPrinter& printer) const;
 private:
   Properties               m_info;
   Properties               m_systemDefaults;

=== modified file 'storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp'
--- a/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp	2009-03-19 14:28:31 +0000
+++ b/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp	2009-03-24 13:48:39 +0000
@@ -4325,11 +4325,17 @@ NdbDictInterface::stopSubscribeEvent(cla
                      SubStartRef::BusyWithNR,
                      SubStartRef::NotMaster,
                      0 };
-  DBUG_RETURN(dictSignal(&tSignal,NULL,0,
-			 0 /*use masternode id*/,
-			 WAIT_CREATE_INDX_REQ /*WAIT_SUB_STOP__REQ*/,
-			 -1, 100,
-			 errCodes, -1));
+  int ret= dictSignal(&tSignal,NULL,0,
+                      0 /*use masternode id*/,
+                      WAIT_CREATE_INDX_REQ /*WAIT_SUB_STOP__REQ*/,
+                      -1, 100,
+                      errCodes, -1);
+  if (ret == 0)
+  {
+    Uint32 *data = (Uint32*)m_buffer.get_data();
+    ev_op.m_stop_gci = data[1] | (Uint64(data[0]) << 32);
+  }
+  DBUG_RETURN(ret);
 }
 
 NdbEventImpl * 
@@ -4519,6 +4525,20 @@ NdbDictInterface::execSUB_STOP_CONF(NdbA
 
   DBUG_PRINT("info",("subscriptionId=%d,subscriptionKey=%d,subscriberData=%d",
 		     subscriptionId,subscriptionKey,subscriberData));
+
+  Uint32 gci_hi= 0;
+  Uint32 gci_lo= 0;
+  if (SubStopConf::SignalLength >= SubStopConf::SignalLengthWithGci)
+  {
+    gci_hi= subStopConf->gci_hi;
+    gci_lo= subStopConf->gci_lo;
+  }
+
+  m_buffer.grow(4 * 2); // 2 words
+  Uint32* data = (Uint32*)m_buffer.get_data();
+  data[0] = gci_hi;
+  data[1] = gci_lo;
+
   m_waiter.signal(NO_WAIT);
   DBUG_VOID_RETURN;
 }
@@ -5878,8 +5898,9 @@ ndb_set_record_specification(Uint32 stor
   }
   else
   {
-    spec->nullbit_byte_offset= 0;
-    spec->nullbit_bit_in_byte= 0;
+    /* For non-nullable columns, use visibly bad offsets */
+    spec->nullbit_byte_offset= ~0;
+    spec->nullbit_bit_in_byte= ~0;
   }
 
   return storageOffset + sizeOfElement;

=== modified file 'storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp'
--- a/storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp	2009-03-19 14:12:15 +0000
+++ b/storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp	2009-03-24 13:48:39 +0000
@@ -182,7 +182,7 @@ NdbEventOperationImpl::init(NdbEventImpl
 
   m_state= EO_CREATED;
 
-  m_node_bit_mask.clear();
+  m_stop_gci = 0;
 #ifdef ndb_event_stores_merge_events_flag
   m_mergeEvents = m_eventImpl->m_mergeEvents;
 #else
@@ -606,7 +606,7 @@ NdbEventOperationImpl::execute_nolock()
   // add kernel reference
   // removed on TE_STOP, TE_CLUSTER_FAILURE, or error below
   m_ref_count++;
-  m_node_bit_mask.set(0u);
+  m_stop_gci= ~(Uint64)0;
   DBUG_PRINT("info", ("m_ref_count: %u for op: %p", m_ref_count, this));
   Uint32 buckets = 0;
   int r= NdbDictionaryImpl::getImpl(*myDict).executeSubscribeEvent(*this,
@@ -628,10 +628,6 @@ NdbEventOperationImpl::execute_nolock()
           m_error.code= myDict->getNdbError().code;
           DBUG_RETURN(r);
         }
-        // add blob reference to main op
-        // removed by TE_STOP or TE_CLUSTER_FAILURE
-        m_ref_count++;
-        DBUG_PRINT("info", ("m_ref_count: %u for op: %p", m_ref_count, this));
         blob_op = blob_op->m_next;
       }
     }
@@ -644,7 +640,7 @@ NdbEventOperationImpl::execute_nolock()
   // remove kernel reference
   // added above
   m_ref_count--;
-  m_node_bit_mask.clear(0u);
+  m_stop_gci = 0;
   DBUG_PRINT("info", ("m_ref_count: %u for op: %p", m_ref_count, this));
   m_state= EO_ERROR;
   mi_type= 0;
@@ -696,6 +692,23 @@ NdbEventOperationImpl::stop()
   m_state= EO_DROPPED;
   mi_type= 0;
   if (r == 0) {
+    if (m_stop_gci == 0)
+    {
+      // response from old kernel
+      Uint64 gci= m_ndb->theEventBuffer->m_highest_sub_gcp_complete_GCI;
+      if (gci)
+      {
+        // calculate a "safe" gci in the future to remove event op.
+        gci += Uint64(3) << 32;
+      }
+      else
+      {
+        // set highest value to ensure that operation does not get dropped
+        // too early. Note '-1' as ~Uint64(0) indicates active event
+        gci = ~Uint64(0)-1;
+      }
+      m_stop_gci = gci;
+    }
     m_ndb->theEventBuffer->add_drop_unlock();
     DBUG_RETURN(0);
   }
@@ -1051,6 +1064,8 @@ NdbEventBuffer::NdbEventBuffer(Ndb *ndb)
   m_max_gci_index(0),
   m_ndb(ndb),
   m_latestGCI(0), m_latest_complete_GCI(0),
+  m_highest_sub_gcp_complete_GCI(0),
+  m_latest_poll_GCI(0),
   m_total_alloc(0),
   m_free_thresh(0),
   m_min_free_thresh(0),
@@ -1145,7 +1160,7 @@ NdbEventBuffer::init_gci_containers()
 {
   m_startup_hack = true;
   bzero(&m_complete_data, sizeof(m_complete_data));
-  m_latest_complete_GCI = m_latestGCI = 0;
+  m_latest_complete_GCI = m_latestGCI = m_latest_poll_GCI = 0;
   m_active_gci.clear();
   m_active_gci.fill(3, g_empty_gci_container);
   m_min_gci_index = m_max_gci_index = 1;
@@ -1201,8 +1216,7 @@ NdbEventBuffer::pollEvents(int aMillisec
     if (unlikely(ev_op == 0))
       ret= 0;
   }
-  if (latestGCI)
-    *latestGCI= m_latestGCI;
+  m_latest_poll_GCI= m_latestGCI;
 #ifdef VM_TRACE
   if (ev_op)
   {
@@ -1213,7 +1227,19 @@ NdbEventBuffer::pollEvents(int aMillisec
   }
   m_latest_command= m_latest_command_save;
 #endif
+  if (unlikely(ev_op == 0))
+  {
+    /*
+      gci's consumed up until m_latest_poll_GCI, so we can free all
+      dropped event operations stopped up until that gci
+    */
+    deleteUsedEventOperations(m_latest_poll_GCI);
+  }
   NdbMutex_Unlock(m_mutex); // we have moved the data
+
+  if (latestGCI)
+    *latestGCI= m_latest_poll_GCI;
+
   return ret;
 }
 
@@ -1332,11 +1358,6 @@ NdbEventBuffer::nextEvent()
          EventBufData_list::Gci_ops *gci_ops = m_available_data.first_gci_ops();
          while (gci_ops && op->getGCI() > gci_ops->m_gci)
          {
-           // moved to next gci, check if any references have been
-           // released when completing the last gci
-           NdbMutex_Lock(m_mutex);
-           deleteUsedEventOperations();
-           NdbMutex_Unlock(m_mutex);
            gci_ops = m_available_data.delete_next_gci_ops();
          }
          if (!gci_ops->m_consistent)
@@ -1364,17 +1385,21 @@ NdbEventBuffer::nextEvent()
   m_latest_command= m_latest_command_save;
 #endif
 
-  // free all "per gci unique" collected operations
-  // completed gci, check if any references have been
-  // released when completing the gci
-  NdbMutex_Lock(m_mutex);
   EventBufData_list::Gci_ops *gci_ops = m_available_data.first_gci_ops();
   while (gci_ops)
   {
-    deleteUsedEventOperations();
     gci_ops = m_available_data.delete_next_gci_ops();
   }
-  NdbMutex_Unlock(m_mutex);
+  /*
+    gci's consumed up until m_latest_poll_GCI, so we can free all
+    dropped event operations stopped up until that gci
+  */
+  if (m_dropped_ev_op)
+  {
+    NdbMutex_Lock(m_mutex);
+    deleteUsedEventOperations(m_latest_poll_GCI);
+    NdbMutex_Unlock(m_mutex);
+  }
   DBUG_RETURN_EVENT(0);
 }
 
@@ -1431,30 +1456,33 @@ NdbEventBuffer::getGCIEventOperations(Ui
 }
 
 void
-NdbEventBuffer::deleteUsedEventOperations()
+NdbEventBuffer::deleteUsedEventOperations(Uint64 last_consumed_gci)
 {
-  Uint32 iter= 0;
-  const NdbEventOperation *op_f;
-  while ((op_f= getGCIEventOperations(&iter, NULL)) != NULL)
-  {
-    NdbEventOperationImpl *op = &op_f->m_impl;
-    DBUG_ASSERT(op->m_ref_count > 0);
-    // remove gci reference
-    // added in inserDataL
-    op->m_ref_count--;
-    DBUG_PRINT("info", ("m_ref_count: %u for op: %p", op->m_ref_count, op));
-    if (op->m_ref_count == 0)
-    {
-      DBUG_PRINT("info", ("deleting op: %p", op));
-      DBUG_ASSERT(op->m_node_bit_mask.isclear());
-      if (op->m_next)
-        op->m_next->m_prev = op->m_prev;
-      if (op->m_prev)
-        op->m_prev->m_next = op->m_next;
-      else
-        m_dropped_ev_op = op->m_next;
-      delete op->m_facade;
+  NdbEventOperationImpl *op= m_dropped_ev_op;
+  while (op && op->m_stop_gci)
+  {
+    if (last_consumed_gci > op->m_stop_gci)
+    {
+      while (op)
+      {
+        NdbEventOperationImpl *next_op= op->m_next;
+        op->m_stop_gci= 0;
+        op->m_ref_count--;
+        if (op->m_ref_count == 0)
+        {
+          if (op->m_next)
+            op->m_next->m_prev = op->m_prev;
+          if (op->m_prev)
+            op->m_prev->m_next = op->m_next;
+          else
+            m_dropped_ev_op = op->m_next;
+          delete op->m_facade;
+        }
+        op = next_op;
+      }
+      break;
     }
+    op = op->m_next;
   }
 }
 
@@ -1851,6 +1879,18 @@ void
 NdbEventBuffer::execSUB_GCP_COMPLETE_REP(const SubGcpCompleteRep * const rep,
                                          Uint32 len, int complete_cluster_failure)
 {
+  Uint32 gci_hi = rep->gci_hi;
+  Uint32 gci_lo = rep->gci_lo;
+
+  if (unlikely(len < SubGcpCompleteRep::SignalLength))
+  {
+    gci_lo = 0;
+  }
+
+  const Uint64 gci= gci_lo | (Uint64(gci_hi) << 32);
+  if (gci > m_highest_sub_gcp_complete_GCI)
+    m_highest_sub_gcp_complete_GCI = gci;
+
   if (!complete_cluster_failure)
   {
     m_alive_node_bit_mask.set(refToNode(rep->senderRef));
@@ -1863,15 +1903,6 @@ NdbEventBuffer::execSUB_GCP_COMPLETE_REP
   
   DBUG_ENTER_EVENT("NdbEventBuffer::execSUB_GCP_COMPLETE_REP");
 
-  Uint32 gci_hi = rep->gci_hi;
-  Uint32 gci_lo = rep->gci_lo;
-
-  if (unlikely(len < SubGcpCompleteRep::SignalLength))
-  {
-    gci_lo = 0;
-  }
-
-  const Uint64 gci= gci_lo | (Uint64(gci_hi) << 32);
   const Uint32 cnt= rep->gcp_complete_rep_count;
 
   Gci_container *bucket = find_bucket(gci);
@@ -2029,31 +2060,25 @@ NdbEventBuffer::insert_event(NdbEventOpe
                              LinearSectionPtr *ptr,
                              Uint32 &oid_ref)
 {
-  NdbEventOperationImpl *dropped_ev_op = m_dropped_ev_op;
   DBUG_PRINT("info", ("gci{hi/lo}: %u/%u", data.gci_hi, data.gci_lo));
   do
   {
-    do
+    if (impl->m_stop_gci == ~Uint64(0))
     {
-      if (impl->m_node_bit_mask.get(0u))
-      {
-        oid_ref = impl->m_oid;
-        insertDataL(impl, &data, SubTableData::SignalLength, ptr);
-      }
-      NdbEventOperationImpl* blob_op = impl->theBlobOpList;
-      while (blob_op != NULL)
+      oid_ref = impl->m_oid;
+      insertDataL(impl, &data, SubTableData::SignalLength, ptr);
+    }
+    NdbEventOperationImpl* blob_op = impl->theBlobOpList;
+    while (blob_op != NULL)
+    {
+      if (blob_op->m_stop_gci == ~Uint64(0))
       {
-        if (blob_op->m_node_bit_mask.get(0u))
-        {
-          oid_ref = blob_op->m_oid;
-          insertDataL(blob_op, &data, SubTableData::SignalLength, ptr);
-        }
-        blob_op = blob_op->m_next;
+        oid_ref = blob_op->m_oid;
+        insertDataL(blob_op, &data, SubTableData::SignalLength, ptr);
       }
-    } while((impl = impl->m_next));
-    impl = dropped_ev_op;
-    dropped_ev_op = NULL;
-  } while (impl);
+      blob_op = blob_op->m_next;
+    }
+  } while((impl = impl->m_next));
 }
 
 bool
@@ -2249,38 +2274,7 @@ NdbEventBuffer::set_total_buckets(Uint32
 void
 NdbEventBuffer::report_node_connected(Uint32 node_id)
 {
-  NdbEventOperation* op= m_ndb->getEventOperation(0);
-  if (op == 0)
-  {
-    return;
-  }
-  
-  DBUG_ENTER("NdbEventBuffer::report_node_connected");
-  SubTableData data;
-  LinearSectionPtr ptr[3];
-  bzero(&data, sizeof(data));
-  bzero(ptr, sizeof(ptr));
-
-  data.tableId = ~0;
-  data.requestInfo = 0;
-  SubTableData::setOperation(data.requestInfo,
-			     NdbDictionary::Event::_TE_ACTIVE);
-  SubTableData::setReqNodeId(data.requestInfo, node_id);
-  SubTableData::setNdbdNodeId(data.requestInfo, node_id);
-  data.flags = SubTableData::LOG;
-
-  Uint64 gci = Uint64((m_latestGCI >> 32) + 1) << 32;
-  find_max_known_gci(&gci);
-
-  data.gci_hi = Uint32(gci >> 32);
-  data.gci_lo = Uint32(gci);
-
-  /**
-   * Insert this event for each operation
-   */
-  // no need to lock()/unlock(), receive thread calls this
-  insert_event(&op->m_impl, data, ptr, data.senderData);
-  DBUG_VOID_RETURN;
+  return;
 }
 
 void
@@ -2432,74 +2426,29 @@ NdbEventBuffer::insertDataL(NdbEventOper
 
   if (!is_data_event)
   {
-    switch (operation)
+    if (operation == NdbDictionary::Event::_TE_CLUSTER_FAILURE)
     {
-    case NdbDictionary::Event::_TE_NODE_FAILURE:
-      DBUG_ASSERT(op->m_node_bit_mask.get(0u) != 0);
-      op->m_node_bit_mask.clear(SubTableData::getNdbdNodeId(ri));
+      /*
+        Mark event as stopping.  Subsequent dropEventOperation
+        will add the event to the dropped list for delete
+      */
+      op->m_stop_gci = gci;
+    }
+    else if (operation == NdbDictionary::Event::_TE_ACTIVE)
+    {
+      // internal event, do not relay to user
       DBUG_PRINT("info",
-                 ("_TE_NODE_FAILURE: m_ref_count: %u for op: %p id: %u",
+                 ("_TE_ACTIVE: m_ref_count: %u for op: %p id: %u",
                   op->m_ref_count, op, SubTableData::getNdbdNodeId(ri)));
-      break;
-    case NdbDictionary::Event::_TE_ACTIVE:
-      DBUG_ASSERT(op->m_node_bit_mask.get(0u) != 0);
-      op->m_node_bit_mask.set(SubTableData::getNdbdNodeId(ri));
+      DBUG_RETURN_EVENT(0);
+    }
+    else if (operation == NdbDictionary::Event::_TE_STOP)
+    {
       // internal event, do not relay to user
       DBUG_PRINT("info",
-                 ("_TE_ACTIVE: m_ref_count: %u for op: %p id: %u",
+                 ("_TE_STOP: m_ref_count: %u for op: %p id: %u",
                   op->m_ref_count, op, SubTableData::getNdbdNodeId(ri)));
       DBUG_RETURN_EVENT(0);
-      break;
-    case NdbDictionary::Event::_TE_CLUSTER_FAILURE:
-      DBUG_ASSERT(op->m_node_bit_mask.get(0u) != 0);
-      op->m_node_bit_mask.clear();
-      DBUG_ASSERT(op->m_ref_count > 0);
-      // remove kernel reference
-      // added in execute_nolock
-      op->m_ref_count--;
-      DBUG_PRINT("info", ("_TE_CLUSTER_FAILURE: m_ref_count: %u for op: %p",
-                          op->m_ref_count, op));
-      if (op->theMainOp)
-      {
-        DBUG_ASSERT(op->m_ref_count == 0);
-        DBUG_ASSERT(op->theMainOp->m_ref_count > 0);
-        // remove blob reference in main op
-        // added in execute_no_lock
-        op->theMainOp->m_ref_count--;
-        DBUG_PRINT("info", ("m_ref_count: %u for op: %p",
-                            op->theMainOp->m_ref_count, op->theMainOp));
-      }
-      break;
-    case NdbDictionary::Event::_TE_STOP:
-      DBUG_ASSERT(op->m_node_bit_mask.get(0u) != 0);
-      op->m_node_bit_mask.clear(0u);
-      op->m_node_bit_mask.clear(SubTableData::getNdbdNodeId(ri));
-      if (op->m_node_bit_mask.isclear())
-      {
-        DBUG_ASSERT(op->m_ref_count > 0);
-        // remove kernel reference
-        // added in execute_no_lock
-        op->m_ref_count--;
-        DBUG_PRINT("info", ("_TE_STOP: m_ref_count: %u for op: %p",
-                            op->m_ref_count, op));
-        if (op->theMainOp)
-        {
-          DBUG_ASSERT(op->m_ref_count == 0);
-          DBUG_ASSERT(op->theMainOp->m_ref_count > 0);
-          // remove blob reference in main op
-          // added in execute_no_lock
-          op->theMainOp->m_ref_count--;
-          DBUG_PRINT("info", ("m_ref_count: %u for op: %p",
-                              op->theMainOp->m_ref_count, op->theMainOp));
-        }
-      }
-      else
-      {
-        op->m_node_bit_mask.set(0u);
-      }
-      break;
-    default:
-      break;
     }
   }
   
@@ -3285,10 +3234,6 @@ EventBufData_list::add_gci_op(Gci_op g)
 #ifndef DBUG_OFF
     i = m_gci_op_count;
 #endif
-    // add gci reference
-    // removed in deleteUsedOperations
-    g.op->m_ref_count++;
-    DBUG_PRINT("info", ("m_ref_count: %u for op: %p", g.op->m_ref_count, g.op));
     m_gci_op_list[m_gci_op_count++] = g;
   }
   DBUG_PRINT_EVENT("exit", ("m_gci_op_list[%u].event_types: %x", i, m_gci_op_list[i].event_types));
@@ -3392,12 +3337,23 @@ NdbEventBuffer::dropEventOperation(NdbEv
   // stop blob event ops
   if (op->theMainOp == NULL)
   {
+    Uint64 max_stop_gci = op->m_stop_gci;
     NdbEventOperationImpl* tBlobOp = op->theBlobOpList;
     while (tBlobOp != NULL)
     {
       tBlobOp->stop();
+      Uint64 stop_gci = tBlobOp->m_stop_gci;
+      if (stop_gci > max_stop_gci)
+        max_stop_gci = stop_gci;
+      tBlobOp = tBlobOp->m_next;
+    }
+    tBlobOp = op->theBlobOpList;
+    while (tBlobOp != NULL)
+    {
+      tBlobOp->m_stop_gci = max_stop_gci;
       tBlobOp = tBlobOp->m_next;
     }
+    op->m_stop_gci = max_stop_gci;
   }
 
   /**
@@ -3435,7 +3391,6 @@ NdbEventBuffer::dropEventOperation(NdbEv
   {
     NdbMutex_Unlock(m_mutex);
     DBUG_PRINT("info", ("deleting op: %p", op));
-    DBUG_ASSERT(op->m_node_bit_mask.isclear());
     delete op->m_facade;
   }
   else

=== modified file 'storage/ndb/src/ndbapi/NdbEventOperationImpl.hpp'
--- a/storage/ndb/src/ndbapi/NdbEventOperationImpl.hpp	2008-12-16 21:21:55 +0000
+++ b/storage/ndb/src/ndbapi/NdbEventOperationImpl.hpp	2009-03-20 08:36:40 +0000
@@ -415,30 +415,10 @@ public:
   Uint32 m_oid;
 
   /*
-    m_node_bit_mask keeps track of which ndb nodes have reference to
-    an event op
-
-    - add    - TE_ACTIVE
-    - remove - TE_STOP, TE_NODE_FAILURE, TE_CLUSTER_FAILURE
-
-    TE_NODE_FAILURE and TE_CLUSTER_FAILURE are created as events
-    and added to all event ops listed as active or pending delete
-    in m_dropped_ev_op using insertDataL, includeing the blob
-    event ops referenced by a regular event op.
-    - NdbEventBuffer::report_node_failure_completed
-
-    TE_ACTIVE is sent from the kernel on initial execute/start of the
-    event op, but is also internally generetad on node connect like
-    TE_NODE_FAILURE and TE_CLUSTER_FAILURE
-    - NdbEventBuffer::report_node_connected
-
-    when m_node_bit_mask becomes clear, the kernel reference is
-    removed from m_ref_count
-
-    node id 0 is used to denote that cluster has a reference
-   */
-
-  Bitmask<(unsigned int)_NDB_NODE_BITMASK_SIZE> m_node_bit_mask;
+    when parsed gci > m_stop_gci it is safe to drop operation
+    as kernel will not have any more references
+  */
+  Uint64 m_stop_gci;
 
   /*
     m_ref_count keeps track of outstanding references to an event
@@ -546,7 +526,7 @@ public:
 
   NdbEventOperationImpl* getGCIEventOperations(Uint32* iter,
                                                Uint32* event_types);
-  void deleteUsedEventOperations();
+  void deleteUsedEventOperations(Uint64 last_consumed_gci);
 
   NdbEventOperationImpl *move_data();
 
@@ -585,8 +565,14 @@ public:
 #endif
 
   Ndb *m_ndb;
-  Uint64 m_latestGCI;           // latest "handover" GCI
+
+  // "latest gci" variables updated in receiver thread
+  Uint64 m_latestGCI;           // latest GCI completed in order
   Uint64 m_latest_complete_GCI; // latest complete GCI (in case of outof order)
+  Uint64 m_highest_sub_gcp_complete_GCI; // highest gci seen in api
+  // "latest gci" variables updated in user thread
+  Uint64 m_latest_poll_GCI; // latest gci handed over to user thread
+
   bool m_startup_hack;
 
   NdbMutex *m_mutex;

=== modified file 'storage/ndb/src/ndbapi/NdbOperationExec.cpp'
--- a/storage/ndb/src/ndbapi/NdbOperationExec.cpp	2009-03-17 01:17:21 +0000
+++ b/storage/ndb/src/ndbapi/NdbOperationExec.cpp	2009-03-23 18:27:58 +0000
@@ -974,8 +974,17 @@ NdbOperation::buildSignalsNdbRecord(Uint
 
       if (likely(!(col->flags & (NdbRecord::IsBlob|NdbRecord::IsMysqldBitfield))))
       {
-        if (( ! (col->flags & NdbRecord::IsKey)) ||
-            ( isScanTakeover ) )
+        int idxColNum= -1;
+        const NdbRecord::Attr* idxCol= NULL;
+        
+        /* Take data from the key row for key columns, attr row otherwise 
+         * Always attr row for scan takeover
+         */
+        if (( isScanTakeover ) ||
+            ( ( key_rec->m_attrId_indexes_length <= attrId) ||
+              ( (idxColNum= key_rec->m_attrId_indexes[attrId]) == -1 )   ||
+              ( ! (idxCol= &key_rec->columns[idxColNum] )) ||
+              ( ! (idxCol->flags & NdbRecord::IsKey)) ) )
         {
           /* Normal path where we get data from the attr row 
            * Always get ATTRINFO data from the attr row for ScanTakeover
@@ -995,17 +1004,18 @@ NdbOperation::buildSignalsNdbRecord(Uint
         }
         else
         {
-          /* For Insert/Write where user provides PK columns,
+          /* For Insert/Write where user provides key columns,
            * take them from the key record row to avoid sending different
            * values in KeyInfo and AttrInfo
            * Need the correct Attr struct from the key
            * record
+           * Note that the key record could be for a unique index.
            */
           assert(key_rec != 0); /* Not scan takeover */
           assert(key_rec->m_attrId_indexes_length > attrId);
-          int keyColIdx= key_rec->m_attrId_indexes[attrId];
-          assert(keyColIdx != -1);
-          col= &key_rec->columns[keyColIdx];
+          assert(key_rec->m_attrId_indexes[attrId] != -1);
+          assert(idxCol != NULL);
+          col= idxCol;
           assert(col->attrId == attrId);
           assert(col->flags & NdbRecord::IsKey);
           

=== modified file 'storage/ndb/src/ndbapi/NdbReceiver.cpp'
--- a/storage/ndb/src/ndbapi/NdbReceiver.cpp	2009-03-16 15:19:53 +0000
+++ b/storage/ndb/src/ndbapi/NdbReceiver.cpp	2009-03-23 14:35:33 +0000
@@ -442,9 +442,12 @@ handle_bitfield_ndbrecord(const NdbRecor
                           Uint32& len,
                           char* row)
 {
-  /* Clear nullbit in row */
-  row[col->nullbit_byte_offset] &=
-    ~(1 << col->nullbit_bit_in_byte);
+  if (col->flags & NdbRecord::IsNullable)
+  {
+    /* Clear nullbit in row */
+    row[col->nullbit_byte_offset] &=
+      ~(1 << col->nullbit_bit_in_byte);
+  }
 
   char* dest;
   Uint64 mysqldSpace;

=== modified file 'storage/ndb/test/ndbapi/testBlobs.cpp'
--- a/storage/ndb/test/ndbapi/testBlobs.cpp	2009-03-17 00:18:16 +0000
+++ b/storage/ndb/test/ndbapi/testBlobs.cpp	2009-03-23 15:44:44 +0000
@@ -3199,6 +3199,7 @@ bugtest_4088()
       CHK((g_opr = g_con->getNdbOperation(name)) != 0);
       CHK(g_opr->readTuple() == 0);
       CHK(g_opr->equal("PK2", tup.m_pk2) == 0);
+      setUDpartId(tup, g_opr);
       CHK(g_opr->getValue("NDB$PK", (char*)&pktup[i].m_pk1) != 0);
     }
     // read blob inline via index as an index
@@ -3247,8 +3248,15 @@ bugtest_27018()
       memcpy(&tup.m_key_row[g_pk2_offset], tup.m_pk2, g_opt.m_pk2chr.m_totlen);
       memcpy(&tup.m_key_row[g_pk3_offset], &tup.m_pk3, sizeof(tup.m_pk3));
     }
+    NdbOperation::OperationOptions opts;
+    setUDpartIdNdbRecord(tup,
+                         g_ndb->getDictionary()->getTable(g_opt.m_tname),
+                         opts);
     CHK((g_const_opr= g_con->updateTuple(g_key_record, tup.m_key_row,
-                                         g_blob_record, tup.m_row)) != 0);
+                                         g_blob_record, tup.m_row,
+                                         NULL, // mask
+                                         &opts,
+                                         sizeof(opts))) != 0);
     CHK(getBlobHandles(g_const_opr) == 0);
     CHK(g_con->execute(NoCommit) == 0);
 
@@ -3260,7 +3268,11 @@ bugtest_27018()
 
     CHK((g_con= g_ndb->startTransaction()) != 0);
     CHK((g_const_opr= g_con->readTuple(g_key_record, tup.m_key_row,
-                                       g_blob_record, tup.m_row)) != 0);
+                                       g_blob_record, tup.m_row,
+                                       NdbOperation::LM_Read,
+                                       NULL, // mask
+                                       &opts,
+                                       sizeof(opts))) != 0);
     CHK(getBlobHandles(g_const_opr) == 0);
 
     CHK(g_bh1->getValue(tup.m_bval1.m_buf, tup.m_bval1.m_len) == 0);
@@ -3295,6 +3307,7 @@ struct bug27370_data {
   char *m_read_row;
   char *m_write_row;
   bool m_thread_stop;
+  NdbOperation::OperationOptions* opts;
 };
 
 void *bugtest_27370_thread(void *arg)
@@ -3312,7 +3325,10 @@ void *bugtest_27370_thread(void *arg)
     const NdbOperation *opr;
     memcpy(data->m_write_row, data->m_key_row, g_rowsize);
     if ((opr= con->writeTuple(g_key_record, data->m_key_row,
-                              g_full_record, data->m_write_row)) == 0)
+                              g_full_record, data->m_write_row,
+                              NULL, //mask
+                              data->opts,
+                              sizeof(NdbOperation::OperationOptions))) == 0)
       return (void *)"Failed to create operation";
     NdbBlob *bh;
     if ((bh= opr->getBlobHandle("BL1")) == 0)
@@ -3346,6 +3362,19 @@ bugtest_27370()
   data.m_blob1_size= g_blob1.m_inline + 10 * g_blob1.m_partsize;
   CHK((data.m_writebuf= new char [data.m_blob1_size]) != 0);
   Uint32 pk1_value= 27370;
+
+  const NdbDictionary::Table* t= g_ndb->getDictionary()->getTable(g_opt.m_tname);
+  bool isUserDefined= (t->getFragmentType() == NdbDictionary::Object::UserDefined); 
+  Uint32 partCount= t->getFragmentCount();
+  Uint32 udPartId= pk1_value % partCount;
+  NdbOperation::OperationOptions opts;
+  opts.optionsPresent= 0;
+  data.opts= &opts;
+  if (isUserDefined)
+  {
+    opts.optionsPresent= NdbOperation::OperationOptions::OO_PARTITION_ID;
+    opts.partitionId= udPartId;
+  }
   memcpy(&data.m_key_row[g_pk1_offset], &pk1_value, sizeof(pk1_value));
   if (g_opt.m_pk2chr.m_len != 0)
   {
@@ -3363,7 +3392,10 @@ bugtest_27370()
   CHK((g_con= g_ndb->startTransaction()) != 0);
   memcpy(data.m_write_row, data.m_key_row, g_rowsize);
   CHK((g_const_opr= g_con->writeTuple(g_key_record, data.m_key_row,
-                                      g_full_record, data.m_write_row)) != 0);
+                                      g_full_record, data.m_write_row,
+                                      NULL, // mask
+                                      &opts,
+                                      sizeof(opts))) != 0);
   CHK((g_bh1= g_const_opr->getBlobHandle("BL1")) != 0);
   CHK(g_bh1->setValue(data.m_writebuf, data.m_blob1_size) == 0);
   CHK(g_con->execute(Commit) == 0);
@@ -3380,7 +3412,10 @@ bugtest_27370()
     CHK((g_con= g_ndb->startTransaction()) != 0);
     CHK((g_const_opr= g_con->readTuple(g_key_record, data.m_key_row,
                                        g_blob_record, data.m_read_row,
-                                       NdbOperation::LM_CommittedRead)) != 0);
+                                       NdbOperation::LM_CommittedRead,
+                                       NULL, // mask
+                                       &opts,
+                                       sizeof(opts))) != 0);
     CHK((g_bh1= g_const_opr->getBlobHandle("BL1")) != 0);
     CHK(g_con->execute(NoCommit, AbortOnError, 1) == 0);
 

=== modified file 'storage/ndb/test/ndbapi/testLimits.cpp'
--- a/storage/ndb/test/ndbapi/testLimits.cpp	2008-12-09 17:15:12 +0000
+++ b/storage/ndb/test/ndbapi/testLimits.cpp	2009-03-22 23:11:46 +0000
@@ -20,12 +20,14 @@
 #define CHECKNOTNULL(p) if ((p) == NULL) {          \
     ndbout << "Error at line " << __LINE__ << endl; \
     ERR(trans->getNdbError());                      \
+    trans->close();                                 \
     return NDBT_FAILED; }
 
 #define CHECKEQUAL(v, e) if ((e) != (v)) {            \
     ndbout << "Error at line " << __LINE__ <<         \
       " expected " << v << endl;                      \
     ERR(trans->getNdbError());                        \
+    trans->close();                                   \
     return NDBT_FAILED; }
 
 
@@ -52,8 +54,17 @@ int activateErrorInsert(NdbTransaction* 
                         NdbRestarter* restarter, 
                         Uint32 val)
 {
+  /* We insert the error twice to avoid what appear to be
+   * races between the error insert and the subsequent
+   * tests
+   * Alternatively we could sleep here.
+   */
+  if (restarter->insertErrorInAllNodes(val) != 0){
+    g_err << "error insert 1 (" << val << ") failed" << endl;
+    return NDBT_FAILED;
+  }
   if (restarter->insertErrorInAllNodes(val) != 0){
-    g_err << "error insert (val) failed" << endl;
+    g_err << "error insert 2 (" << val << ") failed" << endl;
     return NDBT_FAILED;
   }
 
@@ -83,7 +94,6 @@ int activateErrorInsert(NdbTransaction* 
     
 /* Test for correct behaviour using primary key operations
  * when an NDBD node's SegmentedSection pool is exhausted.
- * Long and Short TCKEYREQ variants are tested
  */
 int testSegmentedSectionPk(NDBT_Context* ctx, NDBT_Step* step){
   /*
@@ -94,11 +104,9 @@ int testSegmentedSectionPk(NDBT_Context*
    *                     TCKEYREQ in batch      Consume + send
    * Long TCKEYREQ     Initial import, not last
    *                     TCKEYREQ in batch      Consume + send
-   * Short TCKEYREQ    KeyInfo accumulate       Consume + send long
-   *                     (TCKEYREQ + KEYINFO)
-   * Short TCKEYREQ    AttrInfo accumulate      Consume + send short key
-   *                                             + long AI
-   *                      (TCKEYREQ + ATTRINFO)
+   * No testing of short TCKEYREQ variants as they cannot be
+   * generated in mysql-5.1-telco-6.4+
+   * TODO : Add short variant testing to testUpgrade.
    */
 
   /* We just run on one table */
@@ -309,6 +317,16 @@ int testSegmentedSectionPk(NDBT_Context*
 
   trans->close();
 
+  // TODO : Add code to testUpgrade
+  // Change error insert to get 1 segment left.
+#if 0
+  /*
+   * Short TCKEYREQ    KeyInfo accumulate       Consume + send long
+   *                     (TCKEYREQ + KEYINFO)
+   * Short TCKEYREQ    AttrInfo accumulate      Consume + send short key
+   *                                             + long AI
+   *                      (TCKEYREQ + ATTRINFO)
+   */
   /* Change error insert so that next TCKEYREQ will grab
    * all but one SegmentedSection so that we can then test SegmentedSection
    * exhaustion when importing the Key/AttrInfo words from the
@@ -376,7 +394,7 @@ int testSegmentedSectionPk(NDBT_Context*
   CHECKEQUAL(218, trans->getNdbError().code)
 
   trans->close();  
-
+#endif
 
   /* Finished with error insert, cleanup the error insertion
    * Error insert 8068 will free the hoarded segments
@@ -403,7 +421,6 @@ int testSegmentedSectionPk(NDBT_Context*
   
 /* Test for correct behaviour using unique key operations
  * when an NDBD node's SegmentedSection pool is exhausted.
- * Long and Short TCKEYREQ variants are tested
  */
 int testSegmentedSectionIx(NDBT_Context* ctx, NDBT_Step* step){
   /* 
@@ -412,23 +429,13 @@ int testSegmentedSectionIx(NDBT_Context*
    * Long TCINDXREQ    Initial import           Consume + send 
    * Long TCINDXREQ    Build second TCKEYREQ    Consume + send short
    *                                             w. long base key
-   * Short TCINDXREQ   KeyInfo accumulate       Consume + send long
-   *                     (TCINDXREQ + KEYINFO)
-   * Short TCINDXREQ   AttrInfo accumulate      Consume + send short key
-   *                                             + long AI
-   *                     (TCINDXREQ + ATTRINFO)
    */
   /* We will generate : 
    *   10 SS left : 
    *     Long IndexReq with too long Key/AttrInfo
+   *    5 SS left :
    *     Long IndexReq read with short Key + Attrinfo to long 
    *       base table Key
-   *     Short IndexReq with long Keyinfo
-   *     Short IndexReq with long AttrInfo
-   *   1 SS left
-   *     Short IndexReq with any AttrInfo
-   *   0 SS left
-   *     Short IndexReq with any key info 
    */
   /* We just run on one table */
   if (strcmp(ctx->getTab()->getName(), "WIDE_2COL_IX") != 0)
@@ -643,6 +650,17 @@ int testSegmentedSectionIx(NDBT_Context*
                                              &smallKey[0],
                                              smallKeySize));
 
+  /* Activate error insert 8066 in this transaction, consumes
+   * all but 5 SectionSegments
+   */
+  CHECKEQUAL(NDBT_OK, activateErrorInsert(trans, 
+                                          baseRecord, 
+                                          ctx->getTab(),
+                                          smallRowBuf, 
+                                          &restarter, 
+                                          8066));
+  CHECKEQUAL(0, trans->execute(NdbTransaction::NoCommit));
+  
   CHECKNOTNULL(bigRead= trans->readTuple(ixRecord,
                                          bigAttrIxBuf,
                                          baseRecord,
@@ -655,6 +673,16 @@ int testSegmentedSectionIx(NDBT_Context*
 
   trans->close();
 
+  // TODO Move short signal testing to testUpgrade
+  // Change error insert to get 1 segment left.
+#if 0
+  /*
+   * Short TCINDXREQ   KeyInfo accumulate       Consume + send long
+   *                     (TCINDXREQ + KEYINFO)
+   * Short TCINDXREQ   AttrInfo accumulate      Consume + send short key
+   *                                             + long AI
+   *                     (TCINDXREQ + ATTRINFO)
+   */
   /* Now try with a 'short' TCINDXREQ, generated using the old Api 
    * with a big index key value
    */
@@ -786,6 +814,8 @@ int testSegmentedSectionIx(NDBT_Context*
 
   trans->close();
 
+#endif  
+
   /* Finished with error insert, cleanup the error insertion */
   CHECKNOTNULL(trans= pNdb->startTransaction(ctx->getTab(),
                                              &smallKey[0],
@@ -854,18 +884,18 @@ int testSegmentedSectionScan(NDBT_Contex
                                                 smallKeySize);
   CHECKNOTNULL(trans);
 
-  /* Activate error insert 8065 in this transaction, consumes
-   * all but 10 SectionSegments
+  /* Activate error insert 8066 in this transaction, consumes
+   * all but 5 SectionSegments
    */
   CHECKEQUAL(NDBT_OK, activateErrorInsert(trans, 
                                           record, 
                                           ctx->getTab(),
                                           smallRowBuf, 
                                           &restarter, 
-                                          8065));
+                                          8066));
 
-  /* Ok, now the chosen TC's node should have only 10 
-   * SegmentedSection buffers = ~ 60 words * 10 = 2400 bytes
+  /* Ok, now the chosen TC's node should have only 5 
+   * SegmentedSection buffers = ~ 60 words * 5 = 1200 bytes
    * A scan will always send 2 long sections (Receiver Ids
    * + AttrInfo), so let's start a scan with > 2400 bytes of
    * ATTRINFO and see what happens
@@ -968,6 +998,12 @@ int testDropSignalFragments(NDBT_Context
 
     Uint32 errorInsertVal= subcase.errorInsertCode;
     // printf("Inserting error : %u\n", errorInsertVal);
+    /* We insert the error twice, to bias races between
+     * error-insert propagation and the succeeding scan
+     * in favour of error insert winning!
+     * This problem needs a more general fix
+     */
+    CHECKEQUAL(0, restarter.insertErrorInAllNodes(errorInsertVal));
     CHECKEQUAL(0, restarter.insertErrorInAllNodes(errorInsertVal));
 
     NdbScanOperation* scan= trans->getNdbScanOperation(ctx->getTab());

=== modified file 'storage/ndb/test/ndbapi/test_event.cpp'
--- a/storage/ndb/test/ndbapi/test_event.cpp	2009-03-13 13:18:41 +0000
+++ b/storage/ndb/test/ndbapi/test_event.cpp	2009-03-20 08:36:40 +0000
@@ -1857,6 +1857,13 @@ runSubscribeUnsubscribe(NDBT_Context* ct
       return NDBT_FAILED;
     }
     
+    // consume events to make sure dropped events are deleted
+    if (ndb->pollEvents(0))
+    {
+      while (ndb->nextEvent())
+        ;
+    }
+
     if (ndb->dropEventOperation(pOp))
     {
       g_err << "pOp->execute(): "
@@ -2411,13 +2418,14 @@ runNFSubscribe(NDBT_Context* ctx, NDBT_S
   }
 
   int codes[] = {
-    13013,
-    13019,
-    13020,
-    13041,
-    0,
+    6023,  (int)NdbRestarter::NS_NON_MASTER,
+    13013, (int)NdbRestarter::NS_RANDOM,
+    13019, (int)NdbRestarter::NS_RANDOM,
+    13020, (int)NdbRestarter::NS_RANDOM,
+    13041, (int)NdbRestarter::NS_RANDOM,
+    0
   };
-
+  
   int nr_codes[] = {
     13039,
     13040,
@@ -2431,13 +2439,14 @@ runNFSubscribe(NDBT_Context* ctx, NDBT_S
     int i = 0;
     while (codes[i] != 0)
     {
-      int nodeId = restarter.getDbNodeId(rand() % restarter.getNumDbNodes());
+      int code = codes[i++];
+      int nodeId = restarter.getNode((NdbRestarter::NodeSelector)codes[i++]);
       int val2[] = { DumpStateOrd::CmvmiSetRestartOnErrorInsert, 1 };
       if (restarter.dumpStateOneNode(nodeId, val2, 2))
         return NDBT_FAILED;
       
-      ndbout_c("Node %u error: %u", nodeId, codes[i]);
-      if (restarter.insertErrorInNode(nodeId, codes[i]))
+      ndbout_c("Node %u error: %u", nodeId, code);
+      if (restarter.insertErrorInNode(nodeId, code))
         return NDBT_FAILED;
       
       if (restarter.waitNodesNoStart(&nodeId, 1))
@@ -2448,8 +2457,6 @@ runNFSubscribe(NDBT_Context* ctx, NDBT_S
       
       if (restarter.waitClusterStarted())
         return NDBT_FAILED;
-      
-      i++;
     }
     
     int nodeId = restarter.getDbNodeId(rand() % restarter.getNumDbNodes());

=== modified file 'storage/ndb/tools/ndb_config.cpp'
--- a/storage/ndb/tools/ndb_config.cpp	2009-01-23 12:50:40 +0000
+++ b/storage/ndb/tools/ndb_config.cpp	2009-03-20 09:57:27 +0000
@@ -43,6 +43,8 @@ static const char * g_field_delimiter=",
 static const char * g_row_delimiter=" ";
 static const char * g_config_file = 0;
 static int g_mycnf = 0;
+static int g_configinfo = 0;
+static int g_xml = 0;
 
 const char *load_default_groups[]= { "mysql_cluster",0 };
 
@@ -86,6 +88,12 @@ static struct my_option my_long_options[
   { "mycnf", 256, "Read config from my.cnf",
     (uchar**) &g_mycnf, (uchar**) &g_mycnf,
     0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
+  { "configinfo", 256, "Print configinfo",
+    (uchar**) &g_configinfo, (uchar**) &g_configinfo,
+    0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
+  { "xml", 256, "Print configinfo in xml format",
+    (uchar**) &g_xml, (uchar**) &g_xml,
+    0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
   { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
 };
 
@@ -148,6 +156,7 @@ static int apply(const Iter&, const Vect
 static ndb_mgm_configuration* fetch_configuration();
 static ndb_mgm_configuration* load_configuration();
 
+
 int
 main(int argc, char** argv){
   NDB_INIT(argv[0]);
@@ -158,6 +167,16 @@ main(int argc, char** argv){
 			       ndb_std_get_one_option)))
     return -1;
 
+  if (g_configinfo)
+  {
+    ConfigInfo info;
+    if (g_xml)
+      info.print_xml();
+    else
+      info.print();
+    exit(0);
+  }
+
   if (g_nodes && g_connections)
   {
     fprintf(stderr,

Thread
bzr push into mysql-6.0-telco-7.1 branch (tomas.ulin:2859 to 2861) Tomas Ulin24 Mar