=== added file 'mysql-test/suite/ndb/r/ndb_short_sigs.result' --- mysql-test/suite/ndb/r/ndb_short_sigs.result 1970-01-01 00:00:00 +0000 +++ mysql-test/suite/ndb/r/ndb_short_sigs.result 2009-11-17 17:14:21 +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' --- mysql-test/suite/ndb/t/ndb_short_sigs.cnf 1970-01-01 00:00:00 +0000 +++ mysql-test/suite/ndb/t/ndb_short_sigs.cnf 2009-11-17 16:29:10 +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' --- mysql-test/suite/ndb/t/ndb_short_sigs.test 1970-01-01 00:00:00 +0000 +++ mysql-test/suite/ndb/t/ndb_short_sigs.test 2009-11-17 17:05:10 +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 'storage/ndb/include/kernel/signaldata/GetTabInfo.hpp' --- storage/ndb/include/kernel/signaldata/GetTabInfo.hpp 2009-05-27 15:21:45 +0000 +++ storage/ndb/include/kernel/signaldata/GetTabInfo.hpp 2009-11-17 16:14:07 +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' --- storage/ndb/include/ndb_version.h.in 2009-11-02 17:15:29 +0000 +++ storage/ndb/include/ndb_version.h.in 2009-11-17 16:14:07 +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' --- storage/ndb/include/ndbapi/NdbOperation.hpp 2009-10-07 02:56:19 +0000 +++ storage/ndb/include/ndbapi/NdbOperation.hpp 2009-11-17 16:14:07 +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' --- storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp 2009-09-04 11:33:38 +0000 +++ storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp 2009-11-17 16:14:07 +0000 @@ -2432,7 +2432,17 @@ NdbDictInterface::execGET_TABINFO_REF(Nd 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_waiter.signal(NO_WAIT); } @@ -4713,7 +4723,18 @@ NdbDictInterface::execSUB_START_CONF(Ndb } } - m_sub_start_conf.m_buckets = subStartConf->bucketCount; + if (signal->getLength() == SubStartConf::SignalLength) + { + 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_sub_start_conf.m_buckets = ~0; + } DBUG_PRINT("info",("subscriptionId=%d,subscriptionKey=%d,subscriberData=%d", subscriptionId,subscriptionKey,subscriberData)); m_waiter.signal(NO_WAIT); @@ -7758,6 +7779,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; @@ -7839,6 +7867,27 @@ committed: DBUG_RETURN(0); } +bool +NdbDictInterface::checkAllNodeVersionsMin(Uint32 minNdbVersion) const +{ + for (Uint32 nodeId = 1; nodeId < MAX_NODES; nodeId++) + { + if (m_transporter->getIsDbNode(nodeId) && + m_transporter->getIsNodeSendable(nodeId) && + (m_transporter->getNodeNdbVersion(nodeId) < + minNdbVersion)) + { + /* At least 1 sendable data node has lower-than-min + * version + */ + return false; + } + } + + return true; +} + + int NdbDictInterface::beginSchemaTrans() { === modified file 'storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp' --- storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp 2009-09-04 11:33:38 +0000 +++ storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp 2009-11-17 16:14:07 +0000 @@ -689,6 +689,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' --- storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp 2009-08-06 13:51:18 +0000 +++ storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp 2009-11-17 16:14:07 +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' --- storage/ndb/src/ndbapi/NdbImpl.hpp 2009-09-30 06:58:07 +0000 +++ storage/ndb/src/ndbapi/NdbImpl.hpp 2009-11-17 16:14:07 +0000 @@ -110,6 +110,18 @@ public: return; } +#ifdef ERROR_INSERT + bool forceShortRequests; +#endif + + static inline void setForceShortRequests(Ndb* ndb, bool val) + { +#ifdef ERROR_INSERT + ndb->theImpl->forceShortRequests = val; +#endif + } + + BaseString m_systemPrefix; // Buffer for preformatted for // /** === modified file 'storage/ndb/src/ndbapi/NdbOperationExec.cpp' --- storage/ndb/src/ndbapi/NdbOperationExec.cpp 2009-10-06 11:19:40 +0000 +++ storage/ndb/src/ndbapi/NdbOperationExec.cpp 2009-11-17 16:14:07 +0000 @@ -130,6 +130,130 @@ 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; + TransporterFacade *tp = theNdb->theImpl->m_transporter_facade; + Uint32 tcNodeVersion = tp->getNodeNdbVersion(aNodeId); + bool forceShort = false; +#ifdef ERROR_INSERT + forceShort = theNdb->theImpl->forceShortRequests; +#endif + 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() @@ -144,17 +268,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 */ - TransporterFacade *tp = theNdb->theImpl->m_transporter_facade; + /* + * 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); @@ -164,8 +311,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 */ @@ -190,7 +335,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; } @@ -204,36 +349,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 - */ - TransporterFacade *tp = theNdb->theImpl->m_transporter_facade; - - 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' --- storage/ndb/src/ndbapi/NdbScanOperation.cpp 2009-09-30 07:59:42 +0000 +++ storage/ndb/src/ndbapi/NdbScanOperation.cpp 2009-11-17 16:14:07 +0000 @@ -2420,15 +2420,95 @@ NdbScanOperation::doSendScan(int aProces } TransporterFacade *tp = theNdb->theImpl->m_transporter_facade; - - /* Send Fragmented as SCAN_TABREQ can be large */ - if (tp->sendFragmentedSignal(theSCAN_TABREQ, - aProcessorId, - &secs[0], - numSections) == -1) + + Uint32 tcNodeVersion = tp->getNodeNdbVersion(aProcessorId); + bool forceShort = false; +#ifdef ERROR_INSERT + forceShort = theNdb->theImpl->forceShortRequests; +#endif + 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' --- storage/ndb/src/ndbapi/Ndbinit.cpp 2009-05-26 18:53:34 +0000 +++ storage/ndb/src/ndbapi/Ndbinit.cpp 2009-11-17 17:23:54 +0000 @@ -219,6 +219,14 @@ NdbImpl::NdbImpl(Ndb_cluster_connection m_systemPrefix.assfmt("%s%c%s%c", NDB_SYSTEM_DATABASE, table_name_separator, NDB_SYSTEM_SCHEMA, table_name_separator); + +#ifdef ERROR_INSERT + forceShortRequests = false; + const char* f= getenv("NDB_FORCE_SHORT_REQUESTS"); + if (f != 0 && *f != 0 && *f != '0' && *f != 'n' && *f != 'N') + forceShortRequests = true; +#endif + } NdbImpl::~NdbImpl() === modified file 'storage/ndb/src/ndbapi/TransporterFacade.hpp' --- storage/ndb/src/ndbapi/TransporterFacade.hpp 2009-07-03 06:34:01 +0000 +++ storage/ndb/src/ndbapi/TransporterFacade.hpp 2009-11-17 16:14:07 +0000 @@ -95,6 +95,7 @@ public: bool getIsNodeSendable(NodeId nodeId) const; Uint32 getNodeGrp(NodeId nodeId) const; Uint32 getNodeSequence(NodeId nodeId) const; + Uint32 getNodeNdbVersion(NodeId nodeId) const; // Is there space in sendBuffer to send messages bool check_send_size(Uint32 node_id, Uint32 send_size); @@ -439,6 +440,13 @@ TransporterFacade::getNodeSequence(NodeI inline Uint32 +TransporterFacade::getNodeNdbVersion(NodeId n) const +{ + return theClusterMgr->getNodeInfo(n).m_info.m_version; +} + +inline +Uint32 TransporterFacade::get_scan_batch_size() { return m_scan_batch_size; } @@ -534,4 +542,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' --- storage/ndb/src/ndbapi/ndberror.c 2009-11-09 13:29:20 +0000 +++ storage/ndb/src/ndbapi/ndberror.c 2009-11-17 16:14:07 +0000 @@ -582,6 +582,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' --- storage/ndb/test/include/NDBT_Test.hpp 2009-09-16 12:40:24 +0000 +++ storage/ndb/test/include/NDBT_Test.hpp 2009-11-17 16:14:07 +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' --- storage/ndb/test/run-test/daily-basic-tests.txt 2009-11-02 17:15:29 +0000 +++ storage/ndb/test/run-test/daily-basic-tests.txt 2009-11-17 16:15:23 +0000 @@ -1472,3 +1472,19 @@ 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 + === modified file 'storage/ndb/test/src/CMakeLists.txt' --- storage/ndb/test/src/CMakeLists.txt 2009-10-07 06:35:51 +0000 +++ storage/ndb/test/src/CMakeLists.txt 2009-11-17 16:14:07 +0000 @@ -17,7 +17,8 @@ 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) INCLUDE(${CMAKE_SOURCE_DIR}/storage/ndb/config/type_ndbapitest.cmake) ADD_LIBRARY(ndbNDBT STATIC === modified file 'storage/ndb/test/src/Makefile.am' --- storage/ndb/test/src/Makefile.am 2009-09-16 12:53:49 +0000 +++ storage/ndb/test/src/Makefile.am 2009-11-17 16:14:07 +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 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' --- storage/ndb/test/src/NDBT_Test.cpp 2009-11-11 18:04:01 +0000 +++ storage/ndb/test/src/NDBT_Test.cpp 2009-11-17 16:14:07 +0000 @@ -268,6 +268,7 @@ NDBT_Step::NDBT_Step(NDBT_TestCase* ptes { } +#include 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) {