MySQL Lists are EOL. Please join:

List:Commits« Previous MessageNext Message »
From:Frazer Clement Date:November 18 2009 12:52pm
Subject:bzr commit into mysql-5.1-telco-7.1 branch (frazer:3160)
View as plain text  
#At file:///home/frazer/bzr/mysql-5.1-telco-7.1/

 3160 Frazer Clement	2009-11-18 [merge]
      Merge 7.0->7.1
      added:
        mysql-test/suite/ndb/r/ndb_short_sigs.result
        mysql-test/suite/ndb/t/ndb_short_sigs.cnf
        mysql-test/suite/ndb/t/ndb_short_sigs.test
      modified:
        sql/ha_ndbcluster.cc
        storage/ndb/include/kernel/signaldata/GetTabInfo.hpp
        storage/ndb/include/ndb_version.h.in
        storage/ndb/include/ndbapi/NdbOperation.hpp
        storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp
        storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp
        storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp
        storage/ndb/src/ndbapi/NdbImpl.hpp
        storage/ndb/src/ndbapi/NdbOperationExec.cpp
        storage/ndb/src/ndbapi/NdbScanOperation.cpp
        storage/ndb/src/ndbapi/Ndbinit.cpp
        storage/ndb/src/ndbapi/TransporterFacade.hpp
        storage/ndb/src/ndbapi/ndberror.c
        storage/ndb/test/include/NDBT_Test.hpp
        storage/ndb/test/run-test/daily-basic-tests.txt
        storage/ndb/test/src/CMakeLists.txt
        storage/ndb/test/src/Makefile.am
        storage/ndb/test/src/NDBT_Test.cpp

=== added file 'mysql-test/suite/ndb/r/ndb_short_sigs.result'
--- a/mysql-test/suite/ndb/r/ndb_short_sigs.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/ndb/r/ndb_short_sigs.result	2009-11-18 11:05:02 +0000
@@ -0,0 +1,105 @@
+create table t1 (
+th int primary key, 
+un int, 
+de int, 
+rb varchar(1000), 
+al longtext, 
+key(de),
+unique(rb)) 
+engine=ndb;
+insert into t1 values (1, 1, 1, repeat('O', 1000), repeat('L', 60000));
+insert into t1 values (2, 2, 2, repeat('W',  999), repeat('B', 60001));
+insert into t1 values (3, 3, 3, repeat('P',  998), repeat('P', 60002));
+insert into t1 values (4, 4, 4, repeat('Q',  997), repeat('E', 60003));
+insert into t1 values (5, 5, 5, repeat('E',  996), repeat('A', 60004));
+select th, un, de, length(rb), length(al) 
+from t1 
+where th in (2,4) 
+order by th;
+th	un	de	length(rb)	length(al)
+2	2	2	999	60001
+4	4	4	997	60003
+select th, un, de, length(rb), length(al) 
+from t1 
+where rb 
+in (repeat('O', 1000), repeat('Q', 997))
+order by th;
+th	un	de	length(rb)	length(al)
+1	1	1	1000	60000
+4	4	4	997	60003
+select th, un, de, length(rb), length(al)
+from t1
+where de between 3 and 5
+order by th;
+th	un	de	length(rb)	length(al)
+3	3	3	998	60002
+4	4	4	997	60003
+5	5	5	996	60004
+select th, un, de, length(rb), length(al) 
+from t1 
+order by th;
+th	un	de	length(rb)	length(al)
+1	1	1	1000	60000
+2	2	2	999	60001
+3	3	3	998	60002
+4	4	4	997	60003
+5	5	5	996	60004
+update t1 
+set un=6, de=6, rb= repeat('S', 995), al = repeat('O', 60005)
+where th = 1;
+update t1
+set un=7, de=7, al = repeat('F', 60006)
+where rb = repeat('W', 999);
+update t1
+set un= un + 5, rb = repeat('U', 1000 - un), al = repeat('U', 60000 + un)
+where de >= 3 and de <= 5;
+select th, un, de, length(rb), length(al) 
+from t1 
+order by th;
+th	un	de	length(rb)	length(al)
+1	6	6	995	60005
+2	7	7	999	60006
+3	8	3	992	60008
+4	9	4	991	60009
+5	10	5	990	60010
+alter table t1 add column extra varchar(2000);
+Warnings:
+Warning	1478	Converted FIXED field to DYNAMIC to enable on-line ADD COLUMN
+update t1 set extra = repeat(rb, 2);
+select th, un, de, length(rb), length(al), length(extra)
+from t1 
+order by th;
+th	un	de	length(rb)	length(al)	length(extra)
+1	6	6	995	60005	1990
+2	7	7	999	60006	1998
+3	8	3	992	60008	1984
+4	9	4	991	60009	1982
+5	10	5	990	60010	1980
+select th, un, de, length(rb), length(al), length(extra)
+from t1
+where extra in (
+repeat('U', 2000),
+repeat('U', 1998),
+repeat('U', 1996),
+repeat('U', 1994),
+repeat('U', 1992),
+repeat('U', 1990),
+repeat('U', 1988),
+repeat('U', 1986),
+repeat('U', 1984),
+repeat('U', 1982),
+repeat('U', 1980),
+repeat('U', 1978),
+repeat('U', 1976),
+repeat('U', 1974),
+repeat('U', 1972),
+repeat('U', 1970),
+repeat('U', 1968),
+repeat('U', 1966),
+repeat('U', 1964))
+order by th;
+th	un	de	length(rb)	length(al)	length(extra)
+3	8	3	992	60008	1984
+4	9	4	991	60009	1982
+5	10	5	990	60010	1980
+drop table t1;

=== added file 'mysql-test/suite/ndb/t/ndb_short_sigs.cnf'
--- a/mysql-test/suite/ndb/t/ndb_short_sigs.cnf	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/ndb/t/ndb_short_sigs.cnf	2009-11-18 11:05:02 +0000
@@ -0,0 +1,9 @@
+#
+# Config used when testing short NdbApi request handling
+# functionality
+#
+!include suite/ndb/my.cnf
+
+[ENV]
+# Activate short signal requests
+NDB_FORCE_SHORT_REQUESTS=Y

=== added file 'mysql-test/suite/ndb/t/ndb_short_sigs.test'
--- a/mysql-test/suite/ndb/t/ndb_short_sigs.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/ndb/t/ndb_short_sigs.test	2009-11-18 11:05:02 +0000
@@ -0,0 +1,102 @@
+-- source include/have_ndb.inc
+
+
+# Create table with unique key, ordered index + blob
+
+create table t1 (
+        th int primary key, 
+        un int, 
+        de int, 
+        rb varchar(1000), 
+        al longtext, 
+        key(de),
+        unique(rb)) 
+        engine=ndb;
+
+insert into t1 values (1, 1, 1, repeat('O', 1000), repeat('L', 60000));
+insert into t1 values (2, 2, 2, repeat('W',  999), repeat('B', 60001));
+insert into t1 values (3, 3, 3, repeat('P',  998), repeat('P', 60002));
+insert into t1 values (4, 4, 4, repeat('Q',  997), repeat('E', 60003));
+insert into t1 values (5, 5, 5, repeat('E',  996), repeat('A', 60004));
+
+# Pk lookup
+select th, un, de, length(rb), length(al) 
+        from t1 
+        where th in (2,4) 
+        order by th;
+
+# Uk lookup
+select th, un, de, length(rb), length(al) 
+        from t1 
+        where rb 
+        in (repeat('O', 1000), repeat('Q', 997))
+        order by th;
+
+# Secondary Index scan
+select th, un, de, length(rb), length(al)
+        from t1
+        where de between 3 and 5
+        order by th;
+
+# Table scan
+select th, un, de, length(rb), length(al) 
+        from t1 
+        order by th;
+
+# Update via Pk
+update t1 
+        set un=6, de=6, rb= repeat('S', 995), al = repeat('O', 60005)
+        where th = 1;
+
+# Update via Uk
+update t1
+        set un=7, de=7, al = repeat('F', 60006)
+        where rb = repeat('W', 999);
+
+# Update via Index Scan
+update t1
+        set un= un + 5, rb = repeat('U', 1000 - un), al = repeat('U', 60000 + un)
+        where de >= 3 and de <= 5;
+
+# Table scan
+select th, un, de, length(rb), length(al) 
+        from t1 
+        order by th;
+
+# Online alter table
+alter table t1 add column extra varchar(2000);
+
+# Table scanning update
+update t1 set extra = repeat(rb, 2);
+
+# Table scan
+select th, un, de, length(rb), length(al), length(extra)
+        from t1 
+        order by th;
+
+# Table scan with large pushed filter
+select th, un, de, length(rb), length(al), length(extra)
+        from t1
+        where extra in (
+        repeat('U', 2000),
+        repeat('U', 1998),
+        repeat('U', 1996),
+        repeat('U', 1994),
+        repeat('U', 1992),
+        repeat('U', 1990),
+        repeat('U', 1988),
+        repeat('U', 1986),
+        repeat('U', 1984),
+        repeat('U', 1982),
+        repeat('U', 1980),
+        repeat('U', 1978),
+        repeat('U', 1976),
+        repeat('U', 1974),
+        repeat('U', 1972),
+        repeat('U', 1970),
+        repeat('U', 1968),
+        repeat('U', 1966),
+        repeat('U', 1964))
+        order by th;
+
+drop table t1;

=== modified file 'sql/ha_ndbcluster.cc'
--- a/sql/ha_ndbcluster.cc	2009-11-09 12:23:11 +0000
+++ b/sql/ha_ndbcluster.cc	2009-11-18 12:51:28 +0000
@@ -13057,6 +13057,7 @@ int ha_ndbcluster::alter_table_phase1(TH
     DBUG_PRINT("info", ("Failed to start schema transaction"));
     ERR_PRINT(dict->getNdbError());
     error= ndb_to_mysql_error(&dict->getNdbError());
+    table->file->print_error(error, MYF(0));
     goto err;
   }
 

=== modified file 'storage/ndb/include/kernel/signaldata/GetTabInfo.hpp'
--- a/storage/ndb/include/kernel/signaldata/GetTabInfo.hpp	2009-05-27 15:21:45 +0000
+++ b/storage/ndb/include/kernel/signaldata/GetTabInfo.hpp	2009-11-18 11:05:02 +0000
@@ -74,6 +74,9 @@ class GetTabInfoRef {
   friend bool printGET_TABINFO_REF(FILE *, const Uint32 *, Uint32, Uint16);    
 public:
   STATIC_CONST( SignalLength = 7 );
+  /* 6.3 <-> 7.0 upgrade code */
+  STATIC_CONST( OriginalSignalLength = 5 );
+  STATIC_CONST( OriginalErrorOffset = 4 );
 public:
   Uint32 senderData;
   Uint32 senderRef;

=== modified file 'storage/ndb/include/ndb_version.h.in'
--- a/storage/ndb/include/ndb_version.h.in	2009-11-02 17:15:29 +0000
+++ b/storage/ndb/include/ndb_version.h.in	2009-11-18 11:05:02 +0000
@@ -102,11 +102,15 @@ Uint32 ndbGetOwnVersion();
 #define NDBD_MICRO_GCP_62 NDB_MAKE_VERSION(6,2,5)
 #define NDBD_MICRO_GCP_63 NDB_MAKE_VERSION(6,3,2)
 #define NDBD_RAW_LCP MAKE_VERSION(6,3,11)
+#define NDBD_LONG_TCKEYREQ NDB_MAKE_VERSION(6,4,0)
 #define NDBD_LONG_LQHKEYREQ MAKE_VERSION(6,4,0)
 #define NDBD_MAX_RECVBYTESIZE_32K MAKE_VERSION(6,3,18)
+#define NDBD_LONG_SCANTABREQ NDB_MAKE_VERSION(6,4,0)
 #define NDBD_LONG_SCANFRAGREQ MAKE_VERSION(6,4,0)
 #define NDBD_MT_LQH_VERSION MAKE_VERSION(6,4,0)
 
+#define NDBD_SCHEMA_TRANS_VERSION NDB_MAKE_VERSION(6,4,0)
+
 
 static
 inline

=== modified file 'storage/ndb/include/ndbapi/NdbOperation.hpp'
--- a/storage/ndb/include/ndbapi/NdbOperation.hpp	2009-10-07 03:23:07 +0000
+++ b/storage/ndb/include/ndbapi/NdbOperation.hpp	2009-11-18 12:51:28 +0000
@@ -36,6 +36,7 @@ class NdbBlob;
 class TcKeyReq;
 class NdbRecord;
 class NdbInterpretedCode;
+class GenericSectionPtr;
 
 /**
  * @class NdbOperation
@@ -1208,8 +1209,8 @@ protected:
  * was sent, then the connection object is told about this situation.
  *****************************************************************************/
 
+  int    doSendKeyReq(int processorId, GenericSectionPtr* secs, Uint32 numSecs);
   int    doSend(int ProcessorId, Uint32 lastFlag);
-  int    doSendNdbRecord(int aNodeId);
   virtual int	 prepareSend(Uint32  TC_ConnectPtr,
                              Uint64  TransactionId,
 			     AbortOption);

=== modified file 'storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp'
--- a/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp	2009-09-04 11:39:37 +0000
+++ b/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp	2009-11-18 12:51:28 +0000
@@ -2408,7 +2408,17 @@ NdbDictInterface::execGET_TABINFO_REF(co
   const GetTabInfoRef* ref = CAST_CONSTPTR(GetTabInfoRef, 
 					   signal->getDataPtr());
   
-  m_error.code= ref->errorCode;
+  if (likely(signal->getLength() == GetTabInfoRef::SignalLength))
+  {
+    m_error.code= ref->errorCode;
+  }
+  else
+  {
+    /* 6.3 <-> 7.0 upgrade only */
+    assert (signal->getLength() == GetTabInfoRef::OriginalSignalLength);
+    m_error.code = (*(signal->getDataPtr() + 
+                      GetTabInfoRef::OriginalErrorOffset));
+  }
   m_impl->theWaiter.signal(NO_WAIT);
 }
 
@@ -4709,7 +4719,18 @@ NdbDictInterface::execSUB_START_CONF(con
   }
   }
 
-  m_data.m_sub_start_conf.m_buckets = subStartConf->bucketCount;
+  if (signal->getLength() == SubStartConf::SignalLength)
+  {
+    m_data.m_sub_start_conf.m_buckets = subStartConf->bucketCount;
+  }
+  else
+  {
+    /* 6.3 <-> 7.0 upgrade 
+     * 6.3 doesn't send required bucketCount.  
+     * ~0 indicates no bucketCount received
+     */
+    m_data.m_sub_start_conf.m_buckets = ~0;
+  }
   DBUG_PRINT("info",("subscriptionId=%d,subscriptionKey=%d,subscriberData=%d",
 		     subscriptionId,subscriptionKey,subscriberData));
   m_impl->theWaiter.signal(NO_WAIT);
@@ -7775,6 +7796,13 @@ NdbDictionaryImpl::beginSchemaTrans()
     m_error.code = 4410;
     DBUG_RETURN(-1);
   }
+  if (!m_receiver.checkAllNodeVersionsMin(NDBD_SCHEMA_TRANS_VERSION))
+  {
+    /* Upgrade 6.3 -> 7.0 path */
+    /* Schema transaction not possible until upgrade complete */
+    m_error.code = 4411;
+    DBUG_RETURN(-1);
+  }
   // TODO real transId
   m_tx.m_transId = rand();
   m_tx.m_state = NdbDictInterface::Tx::Started;
@@ -7856,6 +7884,31 @@ committed:
   DBUG_RETURN(0);
 }
 
+bool
+NdbDictInterface::checkAllNodeVersionsMin(Uint32 minNdbVersion) const
+{
+  for (Uint32 nodeId = 1; nodeId < MAX_NODES; nodeId++)
+  {
+    const ClusterMgrNode* cmNode = m_impl->
+      getClientFacade()->getNodeInfo(nodeId);
+    const NodeInfo* nodeInfo = &cmNode->m_info;
+    if (cmNode->defined &&
+        cmNode->compatible &&
+        cmNode->m_alive &&
+        nodeInfo->m_type == NodeInfo::DB &&
+        nodeInfo->m_version < minNdbVersion)
+    {
+      /* At least 1 live data node has lower-than-min
+       * version
+       */
+      return false;
+    }
+  }
+  
+  return true;
+}
+
+
 int
 NdbDictInterface::beginSchemaTrans()
 {

=== modified file 'storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp'
--- a/storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp	2009-09-04 11:39:37 +0000
+++ b/storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp	2009-11-18 12:51:28 +0000
@@ -688,6 +688,8 @@ public:
   int endSchemaTrans(Uint32 flags);
   Tx & m_tx; // shared with NdbDictionaryImpl
 
+  bool checkAllNodeVersionsMin(Uint32 minNdbVersion) const;
+
   const NdbError &getNdbError() const;  
   NdbError & m_error;
 private:

=== modified file 'storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp'
--- a/storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp	2009-08-06 14:51:07 +0000
+++ b/storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp	2009-11-18 12:51:28 +0000
@@ -616,6 +616,12 @@ NdbEventOperationImpl::execute_nolock()
                                                                    buckets);
   if (r == 0) 
   {
+    /* Pre-7.0 kernel nodes do not return the number of buckets
+     * Assume it's == theNoOfDBnodes as was the case in 6.3
+     */
+    if (buckets == ~0)
+      buckets = m_ndb->theImpl->theNoOfDBnodes;
+
     m_ndb->theEventBuffer->set_total_buckets(buckets);
 
     if (theMainOp == NULL) {

=== modified file 'storage/ndb/src/ndbapi/NdbImpl.hpp'
--- a/storage/ndb/src/ndbapi/NdbImpl.hpp	2009-09-30 08:00:49 +0000
+++ b/storage/ndb/src/ndbapi/NdbImpl.hpp	2009-11-18 12:51:28 +0000
@@ -110,6 +110,14 @@ public:
     return;
   }
 
+  bool forceShortRequests;
+
+  static inline void setForceShortRequests(Ndb* ndb, bool val)
+  {
+    ndb->theImpl->forceShortRequests = val;
+  }
+
+
   BaseString m_systemPrefix; // Buffer for preformatted for <sys>/<def>/
 
   // Scan batch configuration parameters

=== modified file 'storage/ndb/src/ndbapi/NdbOperationExec.cpp'
--- a/storage/ndb/src/ndbapi/NdbOperationExec.cpp	2009-10-06 11:32:18 +0000
+++ b/storage/ndb/src/ndbapi/NdbOperationExec.cpp	2009-11-18 12:51:28 +0000
@@ -123,6 +123,128 @@ NdbOperation::setLastFlag(NdbApiSignal* 
   TcKeyReq::setExecuteFlag(req->requestInfo, lastFlag);
 }
 
+int
+NdbOperation::doSendKeyReq(int aNodeId, 
+                           GenericSectionPtr* secs, 
+                           Uint32 numSecs)
+{
+  /* Send a KeyRequest - could be TCKEYREQ or TCINDXREQ
+   *
+   * Normally we send a single long signal with 1 or 2
+   * sections containing KeyInfo and AttrInfo.
+   * For backwards compatibility and testing purposes 
+   * we can send signal trains instead.
+   */
+  NdbApiSignal* request = theTCREQ;
+  TrpClientNdb *tp = theNdb->theImpl->getClientFacade();
+  Uint32 tcNodeVersion = tp->getNodeInfo(aNodeId)->m_info.m_version;
+  bool forceShort = false;
+  forceShort = theNdb->theImpl->forceShortRequests;
+  bool sendLong = ( tcNodeVersion >= NDBD_LONG_TCKEYREQ ) &&
+    ! forceShort;
+  
+  if (sendLong)
+  {
+    return tp->sendSignal(request, aNodeId, secs, numSecs);
+  }
+  else
+  {
+    /* Send signal as short request - either for backwards
+     * compatibility or testing
+     */
+    Uint32 sigCount = 1;
+    Uint32 keyInfoLen  = secs[0].sz;
+    Uint32 attrInfoLen = (numSecs == 2)?
+      secs[1].sz : 
+      0;
+    
+    Uint32 keyInfoInReq = MIN(keyInfoLen, TcKeyReq::MaxKeyInfo);
+    Uint32 attrInfoInReq = MIN(attrInfoLen, TcKeyReq::MaxAttrInfo);
+    TcKeyReq* tcKeyReq = (TcKeyReq*) request->getDataPtrSend();
+    Uint32 connectPtr = tcKeyReq->apiConnectPtr;
+    Uint32 transId1 = tcKeyReq->transId1;
+    Uint32 transId2 = tcKeyReq->transId2;
+    bool indexReq = (request->theVerId_signalNumber == GSN_TCINDXREQ);
+    
+    Uint32 reqLen = request->theLength;
+    
+    /* Set TCKEYREQ flags */
+    TcKeyReq::setKeyLength(tcKeyReq->requestInfo, keyInfoLen);
+    TcKeyReq::setAIInTcKeyReq(tcKeyReq->requestInfo , attrInfoInReq);
+    TcKeyReq::setAttrinfoLen(tcKeyReq->attrLen, attrInfoLen);
+    
+    Uint32* writePtr = request->getDataPtrSend() + reqLen;
+
+    GSIReader keyInfoReader(secs[0].sectionIter);
+    GSIReader attrInfoReader(secs[1].sectionIter);
+    
+    keyInfoReader.copyNWords(writePtr, keyInfoInReq);
+    writePtr += keyInfoInReq;
+    attrInfoReader.copyNWords(writePtr, attrInfoInReq);
+
+    reqLen += keyInfoInReq + attrInfoInReq;
+    assert( reqLen <= TcKeyReq::SignalLength );
+
+    request->setLength(reqLen);
+
+    if (tp->sendSignal(request, aNodeId) == -1)
+      return -1;
+    
+    keyInfoLen -= keyInfoInReq;
+    attrInfoLen -= attrInfoInReq;
+
+    if (keyInfoLen)
+    {
+      request->theVerId_signalNumber = indexReq ? 
+        GSN_INDXKEYINFO : GSN_KEYINFO;
+      KeyInfo* keyInfo = (KeyInfo*) request->getDataPtrSend();
+      keyInfo->connectPtr = connectPtr;
+      keyInfo->transId[0] = transId1;
+      keyInfo->transId[1] = transId2;
+
+      while(keyInfoLen)
+      {
+        Uint32 dataWords = MIN(keyInfoLen, KeyInfo::DataLength);
+
+        keyInfoReader.copyNWords(&keyInfo->keyData[0], dataWords);
+        request->setLength(KeyInfo::HeaderLength + dataWords);
+
+        if (tp->sendSignal(request, aNodeId) == -1)
+          return -1;
+
+        keyInfoLen-= dataWords;
+        sigCount++;
+      }
+    }
+
+    if (attrInfoLen)
+    {
+      request->theVerId_signalNumber = indexReq ? 
+        GSN_INDXATTRINFO : GSN_ATTRINFO;
+      AttrInfo* attrInfo = (AttrInfo*) request->getDataPtrSend();
+      attrInfo->connectPtr = connectPtr;
+      attrInfo->transId[0] = transId1;
+      attrInfo->transId[1] = transId2;
+
+      while(attrInfoLen)
+      {
+        Uint32 dataWords = MIN(attrInfoLen, AttrInfo::DataLength);
+
+        attrInfoReader.copyNWords(&attrInfo->attrData[0], dataWords);
+        request->setLength(AttrInfo::HeaderLength + dataWords);
+
+        if (tp->sendSignal(request, aNodeId) == -1)
+          return -1;
+
+        attrInfoLen-= dataWords;
+        sigCount++;
+      }
+    }
+    
+    return sigCount;
+  }
+}
+
 /******************************************************************************
 int doSend()
 
@@ -137,17 +259,40 @@ NdbOperation::doSend(int aNodeId, Uint32
 {
   assert(theTCREQ != NULL);
   setLastFlag(theTCREQ, lastFlag);
+  Uint32 numSecs= 1;
+  GenericSectionPtr secs[2];
 
   if (m_attribute_record != NULL)
   {
-    /* NdbRecord send - single long signal */
-    if (doSendNdbRecord(aNodeId) == -1 )
+    /*
+     * NdbRecord signal building code puts all KeyInfo and 
+     * AttrInfo into the KeyInfo and AttrInfo signal lists.
+     */
+    SignalSectionIterator keyInfoIter(theTCREQ->next());
+    SignalSectionIterator attrInfoIter(theFirstATTRINFO);
+    
+    /* KeyInfo - always present for TCKEY/INDXREQ*/
+    secs[0].sz= theTupKeyLen;
+    secs[0].sectionIter= &keyInfoIter;
+    
+    /* AttrInfo - not always needed (e.g. Delete) */
+    if (theTotalCurrAI_Len != 0)
+    {
+      secs[1].sz= theTotalCurrAI_Len;
+      secs[1].sectionIter= &attrInfoIter;
+      numSecs++;
+    }
+    
+    if (doSendKeyReq(aNodeId, &secs[0], numSecs) == -1)
       return -1;
   }
   else
   {
-    /* Old Api send - transform signal train to long sections */
-    TrpClientNdb *tp = theNdb->theImpl->getClientFacade();
+    /* 
+     * Old Api signal building code puts first words of KeyInfo
+     * and AttrInfo into the initial request signal
+     * We use special iterators to extract this
+     */
 
     TcKeyReq* tcKeyReq= (TcKeyReq*) theTCREQ->getDataPtrSend();
     const Uint32 inlineKIOffset= Uint32(tcKeyReq->keyInfo - (Uint32*)tcKeyReq);
@@ -157,8 +302,6 @@ NdbOperation::doSend(int aNodeId, Uint32
     const Uint32 inlineAILength= MIN(TcKeyReq::MaxAttrInfo, 
                                      theTotalCurrAI_Len);
     
-    Uint32 numSecs= 1;
-    GenericSectionPtr secs[2];
     /* Create iterators which use the signal train to extract
      * long sections from the short signal trains
      */
@@ -183,7 +326,7 @@ NdbOperation::doSend(int aNodeId, Uint32
       numSecs++;
     }
 
-    if (tp->sendSignal(theTCREQ, aNodeId, &secs[0], numSecs) == -1)
+    if (doSendKeyReq(aNodeId, &secs[0], numSecs) == -1)
       return -1;
   }
 
@@ -197,36 +340,6 @@ NdbOperation::doSend(int aNodeId, Uint32
 }//NdbOperation::doSend()
 
 
-int
-NdbOperation::doSendNdbRecord(int aNodeId)
-{
- /*
-  * Send a long signal to the kernel.
-  * KeyInfo and AttrInfo for NdbRecord are always sent as
-  * separate sections, with none in the TCKEYREQ
-  */
-  TrpClientNdb *tp = theNdb->theImpl->getClientFacade();
-
-  Uint32 numSecs= 1;
-  GenericSectionPtr secs[2];
-  SignalSectionIterator keyInfoIter(theTCREQ->next());
-  SignalSectionIterator attrInfoIter(theFirstATTRINFO);
-  
-  /* KeyInfo - always present for TCKEY/INDXREQ*/
-  secs[0].sz= theTupKeyLen;
-  secs[0].sectionIter= &keyInfoIter;
-
-  /* AttrInfo - not always needed (e.g. Delete) */
-  if (theTotalCurrAI_Len != 0)
-  {
-    secs[1].sz= theTotalCurrAI_Len;
-    secs[1].sectionIter= &attrInfoIter;
-    numSecs++;
-  }
-
-  return tp->sendSignal(theTCREQ, aNodeId, &secs[0], numSecs);
-}
-
 /***************************************************************************
 int prepareSend(Uint32 aTC_ConnectPtr,
                 Uint64 aTransactionId)

=== modified file 'storage/ndb/src/ndbapi/NdbScanOperation.cpp'
--- a/storage/ndb/src/ndbapi/NdbScanOperation.cpp	2009-09-30 08:00:49 +0000
+++ b/storage/ndb/src/ndbapi/NdbScanOperation.cpp	2009-11-18 12:51:28 +0000
@@ -2407,15 +2407,93 @@ NdbScanOperation::doSendScan(int aProces
   }
 
   TrpClientNdb *tp = theNdb->theImpl->getClientFacade();
-  
-  /* Send Fragmented as SCAN_TABREQ can be large */
-  if (tp->sendFragmentedSignal(theSCAN_TABREQ, 
-                               aProcessorId, 
-                               &secs[0], 
-                               numSections) == -1)
+
+  Uint32 tcNodeVersion = tp->getNodeInfo(aProcessorId)->m_info.m_version;
+  bool forceShort = false;
+  forceShort = theNdb->theImpl->forceShortRequests;
+  bool sendLong = ( tcNodeVersion >= NDBD_LONG_SCANTABREQ) &&
+    ! forceShort;
+  
+  if (sendLong)
+  {
+    /* Send Fragmented as SCAN_TABREQ can be large */
+    if (tp->sendFragmentedSignal(theSCAN_TABREQ, 
+                                 aProcessorId, 
+                                 &secs[0], 
+                                 numSections) == -1)
+    {
+      setErrorCode(4002);
+      return -1;
+    }
+  }
+  else
   {
-    setErrorCode(4002);
-    return -1;
+    /* Send a 'short' SCANTABREQ - e.g. long SCANTABREQ
+     * with signalIds as first section, followed by
+     * AttrInfo and KeyInfo trains
+     */
+    Uint32 attrInfoLen = secs[1].sz;
+    Uint32 keyInfoLen = (numSections == 3)? secs[2].sz : 0;
+
+    ScanTabReq* scanTabReq = (ScanTabReq*) theSCAN_TABREQ->getDataPtrSend();
+    Uint32 connectPtr = scanTabReq->apiConnectPtr;
+    Uint32 transId1 = scanTabReq->transId1;
+    Uint32 transId2 = scanTabReq->transId2;
+
+    /* Modify ScanTabReq to carry length of keyinfo and attrinfo */
+    scanTabReq->attrLenKeyLen = (keyInfoLen << 16) | attrInfoLen;
+
+    /* Send with receiver Ids as first and only section */
+    if (tp->sendSignal(theSCAN_TABREQ, aProcessorId, &secs[0], 1) == -1)
+    {
+      setErrorCode(4002);
+      return -1;
+    }
+
+    if (keyInfoLen)
+    {
+      GSIReader keyInfoReader(secs[2].sectionIter);
+      theSCAN_TABREQ->theVerId_signalNumber = GSN_KEYINFO;
+      KeyInfo* keyInfo = (KeyInfo*) theSCAN_TABREQ->getDataPtrSend();
+      keyInfo->connectPtr = connectPtr;
+      keyInfo->transId[0] = transId1;
+      keyInfo->transId[1] = transId2;
+
+      while(keyInfoLen)
+      {
+        Uint32 dataWords = MIN(keyInfoLen, KeyInfo::DataLength);
+        keyInfoReader.copyNWords(&keyInfo->keyData[0], dataWords);
+        theSCAN_TABREQ->setLength(KeyInfo::HeaderLength + dataWords);
+
+        if (tp->sendSignal(theSCAN_TABREQ, aProcessorId) == -1)
+        {
+          setErrorCode(4002);
+          return -1;
+        }
+        keyInfoLen -= dataWords;
+      }
+    }
+
+    GSIReader attrInfoReader(secs[1].sectionIter);
+    theSCAN_TABREQ->theVerId_signalNumber = GSN_ATTRINFO;
+    AttrInfo* attrInfo = (AttrInfo*) theSCAN_TABREQ->getDataPtrSend();
+    attrInfo->connectPtr = connectPtr;
+    attrInfo->transId[0] = transId1;
+    attrInfo->transId[1] = transId2;
+    
+    while(attrInfoLen)
+    {
+      Uint32 dataWords = MIN(attrInfoLen, AttrInfo::DataLength);
+      attrInfoReader.copyNWords(&attrInfo->attrData[0], dataWords);
+      theSCAN_TABREQ->setLength(AttrInfo::HeaderLength + dataWords);
+
+      if (tp->sendSignal(theSCAN_TABREQ, aProcessorId) == -1)
+      {
+        setErrorCode(4002);
+        return -1;
+      }
+      attrInfoLen -= dataWords;
+    }
   }
 
   theStatus = WaitResponse;  

=== modified file 'storage/ndb/src/ndbapi/Ndbinit.cpp'
--- a/storage/ndb/src/ndbapi/Ndbinit.cpp	2009-06-26 14:19:18 +0000
+++ b/storage/ndb/src/ndbapi/Ndbinit.cpp	2009-11-18 12:51:28 +0000
@@ -202,6 +202,11 @@ NdbImpl::NdbImpl(Ndb_cluster_connection 
 
   m_systemPrefix.assfmt("%s%c%s%c", NDB_SYSTEM_DATABASE, table_name_separator,
 			NDB_SYSTEM_SCHEMA, table_name_separator);
+
+  forceShortRequests = false;
+  const char* f= getenv("NDB_FORCE_SHORT_REQUESTS");
+  if (f != 0 && *f != 0 && *f != '0' && *f != 'n' && *f != 'N')
+    forceShortRequests = true;
 }
 
 NdbImpl::~NdbImpl()

=== modified file 'storage/ndb/src/ndbapi/TransporterFacade.hpp'
--- a/storage/ndb/src/ndbapi/TransporterFacade.hpp	2009-07-03 21:11:59 +0000
+++ b/storage/ndb/src/ndbapi/TransporterFacade.hpp	2009-11-18 12:51:28 +0000
@@ -378,4 +378,57 @@ public :
   Uint32* getNextWords(Uint32& sz);
 };
 
+/*
+ * GenericSectionIteratorReader
+ * Helper class to simplify reading data from 
+ * GenericSectionIterator implementations
+ */
+
+class GSIReader
+{
+private :
+  GenericSectionIterator* gsi;
+  const Uint32* chunkPtr;
+  Uint32 chunkRemain;
+public :
+  GSIReader(GenericSectionIterator* _gsi)
+  {
+    gsi = _gsi;
+    chunkPtr = NULL;
+    chunkRemain = 0;
+  }
+
+  void copyNWords(Uint32* dest, Uint32 n)
+  {
+    while (n)
+    {
+      if (chunkRemain == 0)
+      {
+        /* Get next contiguous stretch of words from
+         * the iterator
+         */
+        chunkPtr = gsi->getNextWords(chunkRemain);
+        if (!chunkRemain)
+          abort(); // Must have the words the caller asks for
+      }
+      else
+      {
+        /* Have some words from the iterator, copy some/
+         * all of them
+         */
+        Uint32 wordsToCopy = MIN(chunkRemain, n);
+        memcpy(dest, chunkPtr, wordsToCopy << 2);
+        chunkPtr += wordsToCopy;
+        chunkRemain -= wordsToCopy;
+
+        dest += wordsToCopy;
+        n -= wordsToCopy;
+      }
+    }
+  }
+};
+
+  
+
+
 #endif // TransporterFacade_H

=== modified file 'storage/ndb/src/ndbapi/ndberror.c'
--- a/storage/ndb/src/ndbapi/ndberror.c	2009-11-09 13:33:54 +0000
+++ b/storage/ndb/src/ndbapi/ndberror.c	2009-11-18 12:51:28 +0000
@@ -584,6 +584,7 @@ ErrorBundle ErrorCodes[] = {
   { 4401, DMEC, AE, "Only one schema operation per schema transaction" },
   { 4402, DMEC, AE, "No schema operation defined before calling execute" },
   { 4410, DMEC, AE, "Schema transaction is already started" },
+  { 4411, DMEC, AE, "Schema transaction not possible until upgrade complete" },
 
   { 4501, DMEC, AE, "Insert in hash table failed when getting table information from Ndb" },
   { 4502, DMEC, AE, "GetValue not allowed in Update operation" },

=== modified file 'storage/ndb/test/include/NDBT_Test.hpp'
--- a/storage/ndb/test/include/NDBT_Test.hpp	2009-09-16 12:40:24 +0000
+++ b/storage/ndb/test/include/NDBT_Test.hpp	2009-11-18 11:05:02 +0000
@@ -380,6 +380,8 @@ public:
   void setLogging(bool val);
   bool getLogging() const;
 
+  bool getForceShort() const;
+
   int createTables(Ndb_cluster_connection&) const;
   int dropTables(Ndb_cluster_connection&) const;
 
@@ -417,6 +419,7 @@ private:
   bool m_logging;
   NDBT_DriverType m_driverType;
   bool m_noddl;
+  bool m_forceShort;
 };
 
 

=== modified file 'storage/ndb/test/run-test/daily-basic-tests.txt'
--- a/storage/ndb/test/run-test/daily-basic-tests.txt	2009-11-02 17:17:01 +0000
+++ b/storage/ndb/test/run-test/daily-basic-tests.txt	2009-11-18 12:51:28 +0000
@@ -1472,6 +1472,22 @@ max-time: 300
 cmd: testNdbApi
 args: -n FragmentedApiFailure T1
 
+# Series of short (signal train) request generation/handling tests
+# Start
+max-time: 500
+cmd: testBasic
+args: --forceshortreqs -n PkUpdate
+
+max-time: 300
+cmd: testIndex
+args: --forceshortreqs -n InsertDelete T2
+
+max-time: 2500
+cmd: testPartitioning
+args: --forceshortreqs
+
+# End of short (signal train) handling tests
+
 max-time: 500
 cmd: testNativeDefault
 args:

=== modified file 'storage/ndb/test/src/CMakeLists.txt'
--- a/storage/ndb/test/src/CMakeLists.txt	2009-10-07 06:35:51 +0000
+++ b/storage/ndb/test/src/CMakeLists.txt	2009-11-18 12:51:28 +0000
@@ -17,7 +17,9 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/
                     ${CMAKE_SOURCE_DIR}/storage/ndb/src/common/mgmcommon
                     ${CMAKE_SOURCE_DIR}/storage/ndb/include/mgmcommon
                     ${CMAKE_SOURCE_DIR}/storage/ndb/include/kernel
-                    ${CMAKE_SOURCE_DIR}/storage/ndb/src/mgmapi)
+                    ${CMAKE_SOURCE_DIR}/storage/ndb/src/mgmapi
+                    ${CMAKE_SOURCE_DIR}/storage/ndb/include/debugger
+                    $(CMAKE_SOURCE_DIR)/storage/ndb/include/transporter)
 INCLUDE(${CMAKE_SOURCE_DIR}/storage/ndb/config/type_ndbapitest.cmake)
 
 ADD_LIBRARY(ndbNDBT STATIC

=== modified file 'storage/ndb/test/src/Makefile.am'
--- a/storage/ndb/test/src/Makefile.am	2009-09-16 12:53:49 +0000
+++ b/storage/ndb/test/src/Makefile.am	2009-11-18 12:51:28 +0000
@@ -30,7 +30,7 @@ libNDBT_a_SOURCES = \
 	CpcClient.cpp NdbMixRestarter.cpp NDBT_Thread.cpp DbUtil.cpp \
 	SocketInputStream2.cpp NDBT_Find.cpp
 
-INCLUDES_LOC = -I$(top_srcdir)/storage/ndb/src/common/mgmcommon -I$(top_srcdir)/storage/ndb/include/mgmcommon -I$(top_srcdir)/storage/ndb/include/kernel -I$(top_srcdir)/storage/ndb/src/mgmapi -I$(top_srcdir)/include
+INCLUDES_LOC = -I$(top_srcdir)/storage/ndb/src/common/mgmcommon -I$(top_srcdir)/storage/ndb/include/mgmcommon -I$(top_srcdir)/storage/ndb/include/kernel -I$(top_srcdir)/storage/ndb/src/mgmapi -I$(top_srcdir)/include -I$(top_srcdir)/storage/ndb/include/debugger -I$(top_srcdir)/storage/ndb/include/transporter
 
 include $(top_srcdir)/storage/ndb/config/common.mk.am
 include $(top_srcdir)/storage/ndb/config/type_ndbapitest.mk.am

=== modified file 'storage/ndb/test/src/NDBT_Test.cpp'
--- a/storage/ndb/test/src/NDBT_Test.cpp	2009-11-11 18:04:01 +0000
+++ b/storage/ndb/test/src/NDBT_Test.cpp	2009-11-18 11:05:02 +0000
@@ -268,6 +268,7 @@ NDBT_Step::NDBT_Step(NDBT_TestCase* ptes
 {
 }
 
+#include <storage/ndb/src/ndbapi/NdbImpl.hpp>
 
 int
 NDBT_Step::setUp(Ndb_cluster_connection& con){
@@ -282,6 +283,9 @@ NDBT_Step::setUp(Ndb_cluster_connection&
     m_ndb = new Ndb(&con, "TEST_DB" );
     m_ndb->init(1024);
 
+    NdbImpl::setForceShortRequests(m_ndb, 
+                                   m_ctx->suite->getForceShort());
+
     int result = m_ndb->waitUntilReady(300); // 5 minutes
     if (result != 0){
       g_err << "Ndb was not ready" << endl;
@@ -792,6 +796,7 @@ NDBT_TestSuite::NDBT_TestSuite(const cha
    temporaryTables = false;
    runonce = false;
    m_noddl = false;
+   m_forceShort = false;
 }
 
 
@@ -833,6 +838,10 @@ bool NDBT_TestSuite::getLogging() const 
   return m_logging;
 }
 
+bool NDBT_TestSuite::getForceShort() const {
+  return m_forceShort;
+}
+
 bool NDBT_TestSuite::timerIsOn(){
   return (timer != 0);
 }
@@ -927,6 +936,8 @@ NDBT_TestSuite::executeOneCtx(Ndb_cluste
     Ndb ndb(&con, "TEST_DB");
     ndb.init(1024);
 
+    NdbImpl::setForceShortRequests(&ndb, m_forceShort);
+
     int result = ndb.waitUntilReady(300); // 5 minutes
     if (result != 0){
       g_err << name <<": Ndb was not ready" << endl;
@@ -1276,6 +1287,7 @@ static int opt_seed = 0;
 static int opt_nologging = 0;
 static int opt_temporary = 0;
 static int opt_noddl = 0;
+static int opt_forceShort = 0;
 
 static struct my_option my_long_options[] =
 {
@@ -1316,6 +1328,9 @@ static struct my_option my_long_options[
   { "noddl", 0, "Don't create/drop tables as part of running tests",
     (uchar**) &opt_noddl, (uchar**) &opt_noddl, 0,
     GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
+  { "forceshortreqs", 0, "Use short signals for NdbApi requests",
+    (uchar**) &opt_forceShort, (uchar**) &opt_forceShort, 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}
 };
 
@@ -1386,6 +1401,7 @@ int NDBT_TestSuite::execute(int argc, co
     setLogging(false);
   temporaryTables = opt_temporary;
   m_noddl = opt_noddl;
+  m_forceShort = opt_forceShort;
 
   if (opt_seed == 0)
   {

Thread
bzr commit into mysql-5.1-telco-7.1 branch (frazer:3160)Frazer Clement18 Nov