From 4c90c593af42920263c79718b98dc726123788f5 Mon Sep 17 00:00:00 2001 From: "joreland@mysql.com" <> Date: Wed, 26 May 2004 13:24:14 +0200 Subject: [PATCH] wl1671 - Sorted scan --- .../kernel/signaldata/CreateFragmentation.hpp | 2 +- ndb/include/kernel/signaldata/DictTabInfo.hpp | 2 + ndb/include/kernel/signaldata/DropTab.hpp | 3 +- ndb/include/kernel/signaldata/KeyInfo.hpp | 1 + ndb/include/kernel/signaldata/PrepDropTab.hpp | 6 +- ndb/include/kernel/signaldata/ScanTab.hpp | 81 +- ndb/include/kernel/signaldata/TcCommit.hpp | 1 + ndb/include/kernel/signaldata/TcKeyReq.hpp | 1 + ndb/include/ndbapi/Ndb.hpp | 18 +- ndb/include/ndbapi/NdbApi.hpp | 2 + ndb/include/ndbapi/NdbConnection.hpp | 149 +- ndb/include/ndbapi/NdbCursorOperation.hpp | 73 - ndb/include/ndbapi/NdbIndexOperation.hpp | 2 +- ndb/include/ndbapi/NdbIndexScanOperation.hpp | 140 ++ ndb/include/ndbapi/NdbOperation.hpp | 238 +-- ndb/include/ndbapi/NdbRecAttr.hpp | 51 +- ndb/include/ndbapi/NdbReceiver.hpp | 69 +- ndb/include/ndbapi/NdbResultSet.hpp | 49 +- ndb/include/ndbapi/NdbScanOperation.hpp | 227 +-- .../debugger/signaldata/DictTabInfo.cpp | 2 + .../common/debugger/signaldata/ScanTab.cpp | 49 +- ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp | 2 + ndb/src/kernel/blocks/dbdict/Dbdict.cpp | 57 +- ndb/src/kernel/blocks/dbdict/Dbdict.hpp | 2 +- ndb/src/kernel/blocks/dbdih/DbdihInit.cpp | 1 + ndb/src/kernel/blocks/dbdih/DbdihMain.cpp | 19 + ndb/src/kernel/blocks/dblqh/DblqhMain.cpp | 179 +- ndb/src/kernel/blocks/dbtc/Dbtc.hpp | 253 ++- ndb/src/kernel/blocks/dbtc/DbtcInit.cpp | 38 +- ndb/src/kernel/blocks/dbtc/DbtcMain.cpp | 1458 +++++---------- ndb/src/kernel/blocks/dbtup/Dbtup.hpp | 9 +- ndb/src/kernel/blocks/dbtup/DbtupBuffer.cpp | 295 ++- .../kernel/blocks/dbtup/DbtupExecQuery.cpp | 50 +- ndb/src/kernel/blocks/dbtup/DbtupGen.cpp | 2 - ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp | 2 +- ndb/src/ndbapi/Makefile | 14 +- ndb/src/ndbapi/Ndb.cpp | 53 +- ndb/src/ndbapi/NdbApiSignal.cpp | 3 +- ndb/src/ndbapi/NdbConnection.cpp | 492 ++--- ndb/src/ndbapi/NdbConnectionScan.cpp | 532 +----- ndb/src/ndbapi/NdbCursorOperation.cpp | 6 - ndb/src/ndbapi/NdbDictionaryImpl.cpp | 9 +- ndb/src/ndbapi/NdbDictionaryImpl.hpp | 4 +- ndb/src/ndbapi/NdbEventOperationImpl.cpp | 26 +- ndb/src/ndbapi/NdbImpl.hpp | 11 +- ndb/src/ndbapi/NdbIndexOperation.cpp | 6 +- ndb/src/ndbapi/NdbOperation.cpp | 59 +- ndb/src/ndbapi/NdbOperationDefine.cpp | 121 +- ndb/src/ndbapi/NdbOperationExec.cpp | 379 +--- ndb/src/ndbapi/NdbOperationInt.cpp | 28 +- ndb/src/ndbapi/NdbOperationScan.cpp | 560 ------ ndb/src/ndbapi/NdbRecAttr.cpp | 18 + ndb/src/ndbapi/NdbReceiver.cpp | 172 +- ndb/src/ndbapi/NdbResultSet.cpp | 31 +- ndb/src/ndbapi/NdbScanOperation.cpp | 1653 ++++++++++++----- ndb/src/ndbapi/Ndbif.cpp | 264 ++- ndb/src/ndbapi/Ndblist.cpp | 39 +- ndb/src/ndbapi/ObjectMap.hpp | 41 +- ndb/src/ndbapi/ScanOperation.txt | 46 + ndb/test/include/HugoTransactions.hpp | 30 +- ndb/test/include/UtilTransactions.hpp | 14 +- ndb/test/ndbapi/Makefile | 4 +- ndb/test/ndbapi/testBackup/Makefile | 1 - ndb/test/ndbapi/testBackup/testBackup.cpp | 5 +- .../testDataBuffers/testDataBuffers.cpp | 10 +- ndb/test/ndbapi/testGrep/Makefile | 1 - ndb/test/ndbapi/testGrep/testGrep.cpp | 7 +- ndb/test/ndbapi/testGrep/verify/Makefile | 1 - ndb/test/ndbapi/testIndex/testIndex.cpp | 2 +- ndb/test/ndbapi/testOIBasic/testOIBasic.cpp | 20 +- ndb/test/ndbapi/testScan/ScanFunctions.hpp | 72 +- .../testScanInterpreter/ScanInterpretTest.hpp | 52 +- ndb/test/src/HugoOperations.cpp | 4 + ndb/test/src/HugoTransactions.cpp | 174 +- ndb/test/src/NDBT_Tables.cpp | 2 +- ndb/test/src/UtilTransactions.cpp | 270 +-- ndb/tools/create_index/create_index.cpp | 20 +- ndb/tools/select_all/select_all.cpp | 64 +- 78 files changed, 3523 insertions(+), 5330 deletions(-) create mode 100644 ndb/include/ndbapi/NdbIndexScanOperation.hpp diff --git a/ndb/include/kernel/signaldata/CreateFragmentation.hpp b/ndb/include/kernel/signaldata/CreateFragmentation.hpp index a2f45a9580d..7d53dd91154 100644 --- a/ndb/include/kernel/signaldata/CreateFragmentation.hpp +++ b/ndb/include/kernel/signaldata/CreateFragmentation.hpp @@ -88,7 +88,7 @@ class CreateFragmentationConf { friend bool printCREATE_FRAGMENTATION_CONF(FILE *, const Uint32 *, Uint32, Uint16); public: - STATIC_CONST( SignalLength = 3 ); + STATIC_CONST( SignalLength = 4 ); SECTION( FRAGMENTS = 0 ); private: diff --git a/ndb/include/kernel/signaldata/DictTabInfo.hpp b/ndb/include/kernel/signaldata/DictTabInfo.hpp index 791388d5df8..813b0063d35 100644 --- a/ndb/include/kernel/signaldata/DictTabInfo.hpp +++ b/ndb/include/kernel/signaldata/DictTabInfo.hpp @@ -100,6 +100,7 @@ public: CustomTriggerId = 25, FrmLen = 26, FrmData = 27, + FragmentCount = 128, // No of fragments in table (!fragment replicas) TableEnd = 999, AttributeName = 1000, // String, Mandatory @@ -277,6 +278,7 @@ public: Uint32 CustomTriggerId; Uint32 FrmLen; char FrmData[MAX_FRM_DATA_SIZE]; + Uint32 FragmentCount; void init(); }; diff --git a/ndb/include/kernel/signaldata/DropTab.hpp b/ndb/include/kernel/signaldata/DropTab.hpp index 906f952d852..dd3946d8cc0 100644 --- a/ndb/include/kernel/signaldata/DropTab.hpp +++ b/ndb/include/kernel/signaldata/DropTab.hpp @@ -101,7 +101,8 @@ public: NoSuchTable = 1, DropWoPrep = 2, // Calling Drop with first calling PrepDrop PrepDropInProgress = 3, - DropInProgress = 4 + DropInProgress = 4, + NF_FakeErrorREF = 5 }; private: diff --git a/ndb/include/kernel/signaldata/KeyInfo.hpp b/ndb/include/kernel/signaldata/KeyInfo.hpp index b839a2c2035..a4c698f89b2 100644 --- a/ndb/include/kernel/signaldata/KeyInfo.hpp +++ b/ndb/include/kernel/signaldata/KeyInfo.hpp @@ -25,6 +25,7 @@ class KeyInfo { */ friend class DbUtil; friend class NdbOperation; + friend class NdbScanOperation; /** * Reciver(s) diff --git a/ndb/include/kernel/signaldata/PrepDropTab.hpp b/ndb/include/kernel/signaldata/PrepDropTab.hpp index e9cc28fed0c..c54b2474aa3 100644 --- a/ndb/include/kernel/signaldata/PrepDropTab.hpp +++ b/ndb/include/kernel/signaldata/PrepDropTab.hpp @@ -88,7 +88,8 @@ public: NoSuchTable = 1, PrepDropInProgress = 2, DropInProgress = 3, - InvalidTableState = 4 + InvalidTableState = 4, + NF_FakeErrorREF = 5 }; private: @@ -137,7 +138,8 @@ public: enum ErrorCode { NoSuchTable = 1, IllegalTableState = 2, - DropInProgress = 3 + DropInProgress = 3, + NF_FakeErrorREF = 4 }; Uint32 tableId; diff --git a/ndb/include/kernel/signaldata/ScanTab.hpp b/ndb/include/kernel/signaldata/ScanTab.hpp index efd8a4918ab..6cef4381c07 100644 --- a/ndb/include/kernel/signaldata/ScanTab.hpp +++ b/ndb/include/kernel/signaldata/ScanTab.hpp @@ -33,8 +33,8 @@ class ScanTabReq { /** * Sender(s) */ - friend class NdbOperation; friend class NdbConnection; + friend class NdbScanOperation; /** * For printing @@ -73,6 +73,7 @@ private: static Uint8 getHoldLockFlag(const UintR & requestInfo); static Uint8 getReadCommittedFlag(const UintR & requestInfo); static Uint8 getRangeScanFlag(const UintR & requestInfo); + static Uint8 getScanBatch(const UintR & requestInfo); /** * Set:ers for requestInfo @@ -83,7 +84,7 @@ private: static void setHoldLockFlag(UintR & requestInfo, Uint32 flag); static void setReadCommittedFlag(UintR & requestInfo, Uint32 flag); static void setRangeScanFlag(UintR & requestInfo, Uint32 flag); - + static void setScanBatch(Uint32& requestInfo, Uint32 sz); }; /** @@ -94,10 +95,11 @@ private: h = Hold lock mode - 1 Bit 10 c = Read Committed - 1 Bit 11 x = Range Scan (TUX) - 1 Bit 15 + b = Scan batch - 5 Bit 16-19 (max 15) 1111111111222222222233 01234567890123456789012345678901 - ppppppppl hc x + ppppppppl hc xbbbbb */ #define PARALLELL_SHIFT (0) @@ -115,6 +117,9 @@ private: #define RANGE_SCAN_SHIFT (15) #define RANGE_SCAN_MASK (1) +#define SCAN_BATCH_SHIFT (16) +#define SCAN_BATCH_MASK (31) + inline Uint8 ScanTabReq::getParallelism(const UintR & requestInfo){ @@ -145,6 +150,12 @@ ScanTabReq::getRangeScanFlag(const UintR & requestInfo){ return (Uint8)((requestInfo >> RANGE_SCAN_SHIFT) & RANGE_SCAN_MASK); } +inline +Uint8 +ScanTabReq::getScanBatch(const Uint32 & requestInfo){ + return (Uint8)((requestInfo >> SCAN_BATCH_SHIFT) & SCAN_BATCH_MASK); +} + inline void ScanTabReq::clearRequestInfo(UintR & requestInfo){ @@ -186,6 +197,12 @@ ScanTabReq::setRangeScanFlag(UintR & requestInfo, Uint32 flag){ requestInfo |= (flag << RANGE_SCAN_SHIFT); } +inline +void +ScanTabReq::setScanBatch(Uint32 & requestInfo, Uint32 flag){ + ASSERT_MAX(flag, SCAN_BATCH_MASK, "ScanTabReq::setScanBatch"); + requestInfo |= (flag << SCAN_BATCH_SHIFT); +} /** * @@ -213,7 +230,8 @@ public: * Length of signal */ STATIC_CONST( SignalLength = 4 ); - + static const Uint32 EndOfData = (1 << 31); + private: // Type definitions @@ -225,29 +243,15 @@ private: UintR requestInfo; // DATA 1 UintR transId1; // DATA 2 UintR transId2; // DATA 3 -#if 0 - UintR operLenAndIdx[16]; // DATA 4-19 - - /** - * Get:ers for operLenAndIdx - */ - static Uint32 getLen(const UintR & operLenAndIdx); - static Uint8 getIdx(const UintR & operLenAndIdx); -#endif - - /** - * Get:ers for requestInfo - */ - static Uint8 getOperations(const UintR & reqInfo); - static Uint8 getScanStatus(const UintR & reqInfo); - - /** - * Set:ers for requestInfo - */ - static void setOperations(UintR & reqInfo, Uint32 ops); - static void setScanStatus(UintR & reqInfo, Uint32 stat); + struct OpData { + Uint32 apiPtrI; + Uint32 tcPtrI; + Uint32 info; + }; + static Uint32 getLength(Uint32 opDataInfo) { return opDataInfo >> 5; }; + static Uint32 getRows(Uint32 opDataInfo) { return opDataInfo & 31;} }; /** @@ -267,33 +271,6 @@ private: #define STATUS_SHIFT (8) #define STATUS_MASK (0xFF) -inline -Uint8 -ScanTabConf::getOperations(const UintR & reqInfo){ - return (Uint8)((reqInfo >> OPERATIONS_SHIFT) & OPERATIONS_MASK); -} - -inline -void -ScanTabConf::setOperations(UintR & requestInfo, Uint32 ops){ - ASSERT_MAX(ops, OPERATIONS_MASK, "ScanTabConf::setOperations"); - requestInfo |= (ops << OPERATIONS_SHIFT); -} - -inline -Uint8 -ScanTabConf::getScanStatus(const UintR & reqInfo){ - return (Uint8)((reqInfo >> STATUS_SHIFT) & STATUS_MASK); -} - -inline -void -ScanTabConf::setScanStatus(UintR & requestInfo, Uint32 stat){ - ASSERT_MAX(stat, STATUS_MASK, "ScanTabConf::setScanStatus"); - requestInfo |= (stat << STATUS_SHIFT); -} - - /** * * SENDER: Dbtc, API diff --git a/ndb/include/kernel/signaldata/TcCommit.hpp b/ndb/include/kernel/signaldata/TcCommit.hpp index 43eb7be1c39..b7f3fbbb361 100644 --- a/ndb/include/kernel/signaldata/TcCommit.hpp +++ b/ndb/include/kernel/signaldata/TcCommit.hpp @@ -33,6 +33,7 @@ class TcCommitConf { * Reciver(s) */ friend class Ndb; + friend class NdbConnection; public: STATIC_CONST( SignalLength = 3 ); diff --git a/ndb/include/kernel/signaldata/TcKeyReq.hpp b/ndb/include/kernel/signaldata/TcKeyReq.hpp index df0a00da3e0..f7d3c2e3282 100644 --- a/ndb/include/kernel/signaldata/TcKeyReq.hpp +++ b/ndb/include/kernel/signaldata/TcKeyReq.hpp @@ -38,6 +38,7 @@ class TcKeyReq { friend class Ndbcntr; friend class NdbOperation; friend class NdbIndexOperation; + friend class NdbScanOperation; friend class DbUtil; /** diff --git a/ndb/include/ndbapi/Ndb.hpp b/ndb/include/ndbapi/Ndb.hpp index fd6e827ceb4..b02675da4e1 100644 --- a/ndb/include/ndbapi/Ndb.hpp +++ b/ndb/include/ndbapi/Ndb.hpp @@ -868,6 +868,7 @@ class NdbObjectIdMap; class NdbOperation; class NdbEventOperationImpl; class NdbScanOperation; +class NdbIndexScanOperation; class NdbIndexOperation; class NdbConnection; class NdbSchemaOp; @@ -878,7 +879,6 @@ class NdbLabel; class NdbBranch; class NdbSubroutine; class NdbCall; -class NdbScanReceiver; class Table; class BaseString; class NdbEventOperation; @@ -965,8 +965,9 @@ class Ndb friend class NdbSchemaCon; friend class Table; friend class NdbApiSignal; - friend class NdbScanReceiver; friend class NdbIndexOperation; + friend class NdbScanOperation; + friend class NdbIndexScanOperation; friend class NdbDictionaryImpl; friend class NdbDictInterface; @@ -1455,7 +1456,7 @@ private: NdbConnection* doConnect(Uint32 nodeId); void doDisconnect(); - NdbScanReceiver* getNdbScanRec();// Get a NdbScanReceiver from idle list + NdbReceiver* getNdbScanRec();// Get a NdbScanReceiver from idle list NdbLabel* getNdbLabel(); // Get a NdbLabel from idle list NdbBranch* getNdbBranch(); // Get a NdbBranch from idle list NdbSubroutine* getNdbSubroutine();// Get a NdbSubroutine from idle @@ -1464,21 +1465,21 @@ private: NdbRecAttr* getRecAttr(); // Get a receeive attribute object from // idle list of the Ndb object. NdbOperation* getOperation(); // Get an operation from idle list - NdbScanOperation* getScanOperation(); // Get a scan operation from idle + NdbIndexScanOperation* getScanOperation(); // Get a scan operation from idle NdbIndexOperation* getIndexOperation();// Get an index operation from idle class NdbGlobalEventBufferHandle* getGlobalEventBufferHandle(); void releaseSignal(NdbApiSignal* anApiSignal); void releaseSignalsInList(NdbApiSignal** pList); - void releaseNdbScanRec(NdbScanReceiver* aNdbScanRec); + void releaseNdbScanRec(NdbReceiver* aNdbScanRec); void releaseNdbLabel(NdbLabel* anNdbLabel); void releaseNdbBranch(NdbBranch* anNdbBranch); void releaseNdbSubroutine(NdbSubroutine* anNdbSubroutine); void releaseNdbCall(NdbCall* anNdbCall); void releaseRecAttr (NdbRecAttr* aRecAttr); void releaseOperation(NdbOperation* anOperation); - void releaseScanOperation(NdbScanOperation* aScanOperation); + void releaseScanOperation(NdbIndexScanOperation*); void check_send_timeout(); void remove_sent_list(Uint32); @@ -1574,7 +1575,6 @@ private: void* int2void (Uint32 val); NdbReceiver* void2rec (void* val); NdbConnection* void2con (void* val); - NdbScanReceiver* void2rec_srec(void* val); NdbOperation* void2rec_op (void* val); NdbIndexOperation* void2rec_iop (void* val); @@ -1614,7 +1614,7 @@ private: NdbOperation* theOpIdleList; // First operation in the idle list. - NdbScanOperation* theScanOpIdleList; // First scan operation in the idle list. + NdbIndexScanOperation* theScanOpIdleList; // First scan operation in the idle list. NdbIndexOperation* theIndexOpIdleList; // First index operation in the idle list. NdbSchemaCon* theSchemaConIdleList; // First schemaCon in idle list. @@ -1627,7 +1627,7 @@ private: NdbBranch* theBranchList; // First branch descriptor in list NdbSubroutine* theSubroutineList; // First subroutine descriptor in NdbCall* theCallList; // First call descriptor in list - NdbScanReceiver* theScanList; + NdbReceiver* theScanList; Uint32 theMyRef; // My block reference Uint32 theNode; // The node number of our node diff --git a/ndb/include/ndbapi/NdbApi.hpp b/ndb/include/ndbapi/NdbApi.hpp index e5efc9756ce..cdc48dad039 100644 --- a/ndb/include/ndbapi/NdbApi.hpp +++ b/ndb/include/ndbapi/NdbApi.hpp @@ -23,6 +23,8 @@ #include "NdbOperation.hpp" #include "NdbScanOperation.hpp" #include "NdbIndexOperation.hpp" +#include "NdbIndexScanOperation.hpp" +#include "NdbScanFilter.hpp" #include "NdbSchemaCon.hpp" #include "NdbSchemaOp.hpp" #include "NdbRecAttr.hpp" diff --git a/ndb/include/ndbapi/NdbConnection.hpp b/ndb/include/ndbapi/NdbConnection.hpp index 0245859a632..b6f5aef5947 100644 --- a/ndb/include/ndbapi/NdbConnection.hpp +++ b/ndb/include/ndbapi/NdbConnection.hpp @@ -23,12 +23,11 @@ class NdbConnection; class NdbOperation; -class NdbCursorOperation; class NdbScanOperation; +class NdbIndexScanOperation; class NdbIndexOperation; class NdbApiSignal; class Ndb; -class NdbScanReceiver; /** @@ -131,7 +130,7 @@ class NdbConnection friend class NdbOperation; friend class NdbScanOperation; friend class NdbIndexOperation; - friend class NdbScanReceiver; + friend class NdbIndexScanOperation; public: @@ -147,57 +146,32 @@ public: */ NdbOperation* getNdbOperation(const char* aTableName); - /** - * Get an NdbOperation for index scan of a table. - * Note that the operation has to be defined before it is executed. - * - * @note All operations within the same transaction need to - * be initialized with this method. - * - * @param anIndexName The index name. - * @param aTableName The table name. - * @return Pointer to an NdbOperation object if successful, otherwise NULL. - */ - NdbOperation* getNdbOperation(const char* anIndexName, - const char* aTableName); - -#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL /** * Get an operation from NdbScanOperation idlelist and * get the NdbConnection object which * was fetched by startTransaction pointing to this operation. - * This operation will set the theTableId - * in the NdbOperation object.synchronous. * * @param aTableName a table name. * @return pointer to an NdbOperation object if successful, otherwise NULL */ NdbScanOperation* getNdbScanOperation(const char* aTableName); -#endif -#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL /** * Get an operation from NdbScanOperation idlelist and * get the NdbConnection object which * was fetched by startTransaction pointing to this operation. - * This operation will set the theTableId - * in the NdbOperation object.synchronous. * * @param anIndexName The index name. * @param aTableName a table name. * @return pointer to an NdbOperation object if successful, otherwise NULL */ - NdbScanOperation* getNdbScanOperation(const char* anIndexName, - const char* aTableName); -#endif - - + NdbIndexScanOperation* getNdbIndexScanOperation(const char* anIndexName, + const char* aTableName); + /** * Get an operation from NdbIndexOperation idlelist and * get the NdbConnection object that * was fetched by startTransaction pointing to this operation. - * This operation will set the theTableId - * in the NdbOperation object. Synchronous. * * @param indexName An index name (as created by createIndex). * @param tableName A table name. @@ -309,75 +283,6 @@ public: /** @} *********************************************************************/ - /** - * @name Scan Transactions - * @{ - */ - - /** - * Execute a scan transaction. This will define - * and start the scan transaction in the NDB kernel. - * - * @return 0 if successful otherwise -1. - */ - int executeScan(); - - /** - * Get the next tuple in a scan transaction. - * - * After each call to NdbConnection::nextScanResult - * the buffers and NdbRecAttr objects defined in - * NdbOperation::getValue are updated with values - * from the scanned tuple. - * - * @param fetchAllowed If set to false, then fetching is disabled - * - * The NDB API will contact the NDB Kernel for more tuples - * when necessary to do so unless you set the fetchAllowed - * to false. - * This will force NDB to process any records it - * already has in it's caches. When there are no more cached - * records it will return 2. You must then call nextScanResult - * with fetchAllowed = true in order to contact NDB for more - * records. - * - * fetchAllowed = false is useful when you want to update or - * delete all the records fetched in one transaction(This will save a - * lot of round trip time and make updates or deletes of scanned - * records a lot faster). - * While nextScanResult(false) - * returns 0 take over the record to another transaction. When - * nextScanResult(false) returns 2 you must execute and commit the other - * transaction. This will cause the locks to be transferred to the - * other transaction, updates or deletes will be made and then the - * locks will be released. - * After that, call nextScanResult(true) which will fetch new records and - * cache them in the NdbApi. - * - * @note If you don't take over the records to another transaction the - * locks on those records will be released the next time NDB Kernel - * is contacted for more records. - * - * @note Please contact for examples of efficient scan - * updates and deletes. - * - * @return - * - -1: if unsuccessful,
- * - 0: if another tuple was received, and
- * - 1: if there are no more tuples to scan. - * - 2: if there are no more cached records in NdbApi - */ - int nextScanResult(bool fetchAllowed = true); - - /** - * Stops the scan. Used if no more tuples are wanted. - * The transaction should still be closed with - * Ndb::closeTransaction. - * - * @return 0 if successful otherwise -1. - */ - int stopScan(); - /** * @name Meta Information * @{ @@ -536,13 +441,7 @@ private: int receiveTCINDXCONF(const class TcIndxConf *, Uint32 aDataLength); int receiveTCINDXREF(NdbApiSignal*); int receiveSCAN_TABREF(NdbApiSignal*); - int receiveSCAN_TABCONF(NdbApiSignal*); - int receiveSCAN_TABINFO(NdbApiSignal*); - - int checkNextScanResultComplete(); - int sendScanStart(); - int sendScanNext(bool stopScanFlag); - int fetchNextScanResult(); + int receiveSCAN_TABCONF(NdbApiSignal*, const Uint32*, Uint32 len); int doSend(); // Send all operations int sendROLLBACK(); // Send of an ROLLBACK @@ -565,7 +464,7 @@ private: // Release all cursor operations in connection void releaseOps(NdbOperation*); - void releaseCursorOperations(NdbCursorOperation*); + void releaseScanOperations(NdbIndexScanOperation*); // Set the transaction identity of the transaction void setTransactionId(Uint64 aTransactionId); @@ -581,7 +480,7 @@ private: int checkMagicNumber(); // Verify correct object NdbOperation* getNdbOperation(class NdbTableImpl* aTable); - NdbScanOperation* getNdbScanOperation(class NdbTableImpl* aTable); + NdbIndexScanOperation* getNdbScanOperation(class NdbTableImpl* aTable); NdbIndexOperation* getNdbIndexOperation(class NdbIndexImpl* anIndex, class NdbTableImpl* aTable); @@ -622,7 +521,6 @@ private: Uint32 theNoOfOpSent; // How many operations have been sent Uint32 theNoOfOpCompleted; // How many operations have completed Uint32 theNoOfOpFetched; // How many operations was actually fetched - Uint32 theNoOfSCANTABCONFRecv; // How many SCAN_TABCONF have been received Uint32 theMyRef; // Our block reference Uint32 theTCConPtr; // Transaction Co-ordinator connection pointer. Uint64 theTransactionId; // theTransactionId of the transaction @@ -647,20 +545,16 @@ private: Uint32 theNodeSequence; // The sequence no of the db node bool theReleaseOnClose; - // Cursor operations - bool m_waitForReply; - NdbCursorOperation* m_theFirstCursorOperation; - NdbCursorOperation* m_theLastCursorOperation; - - NdbCursorOperation* m_firstExecutedCursorOp; // Scan operations - bool theScanFinished; + bool m_waitForReply; + NdbIndexScanOperation* m_theFirstScanOperation; + NdbIndexScanOperation* m_theLastScanOperation; + + NdbIndexScanOperation* m_firstExecutedScanOp; - NdbScanReceiver* theCurrentScanRec; // The current operation to - // distribute to the app. - NdbScanReceiver* thePreviousScanRec; // The previous operation read by - // nextScanResult. - NdbOperation* theScanningOp; // The operation actually performing the scan + // Scan operations + // The operation actually performing the scan + NdbScanOperation* theScanningOp; Uint32 theBuddyConPtr; static void sendTC_COMMIT_ACK(NdbApiSignal *, @@ -671,6 +565,17 @@ private: #ifdef VM_TRACE void printState(); #endif + + bool checkState_TransId(const Uint32 * transId) const { + const Uint32 tTmp1 = transId[0]; + const Uint32 tTmp2 = transId[1]; + Uint64 tRecTransId = (Uint64)tTmp1 + ((Uint64)tTmp2 << 32); + bool b = theStatus == Connected && theTransactionId == tRecTransId; +#ifdef NDB_NO_DROPPED_SIGNAL + if(!b) abort(); +#endif + return b; + } }; inline diff --git a/ndb/include/ndbapi/NdbCursorOperation.hpp b/ndb/include/ndbapi/NdbCursorOperation.hpp index cd76b045ea2..e7eeb54ba2d 100644 --- a/ndb/include/ndbapi/NdbCursorOperation.hpp +++ b/ndb/include/ndbapi/NdbCursorOperation.hpp @@ -17,77 +17,4 @@ #ifndef NdbCursorOperation_H #define NdbCursorOperation_H -#include - -class NdbResultSet; - -/** - * @class NdbCursorOperation - * @brief Operation using cursors - */ -class NdbCursorOperation : public NdbOperation -{ - friend class NdbResultSet; - friend class NdbConnection; - -public: - /** - * Type of cursor - */ - enum CursorType { - NoCursor = 0, - ScanCursor = 1, - IndexCursor = 2 - }; - - /** - * Lock when performing scan - */ - enum LockMode { - LM_Read = 0, - LM_Exclusive = 1, - LM_CommittedRead = 2, -#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL - LM_Dirty = 2 -#endif - }; - - virtual CursorType cursorType() = 0; - - /** - * readTuples returns a NdbResultSet where tuples are stored. - * Tuples are not stored in NdbResultSet until execute(NoCommit) - * has been executed and nextResult has been called. - * - * @param parallel Scan parallelism - * @param LockMode Scan lock handling - * @returns NdbResultSet. - */ - virtual NdbResultSet* readTuples(unsigned parallel = 0, - LockMode = LM_Read ) = 0; - - inline NdbResultSet* readTuplesExclusive(int parallell = 0){ - return readTuples(parallell, LM_Exclusive); - } - -protected: - NdbCursorOperation(Ndb* aNdb); - - ~NdbCursorOperation(); - - void cursInit(); - - virtual int executeCursor(int ProcessorId) = 0; - - NdbResultSet* getResultSet(); - NdbResultSet* m_resultSet; - -private: - - virtual int nextResult(bool fetchAllowed) = 0; - - virtual void closeScan() = 0; -}; - - #endif diff --git a/ndb/include/ndbapi/NdbIndexOperation.hpp b/ndb/include/ndbapi/NdbIndexOperation.hpp index 3b8e5f7a888..934dbbe6dee 100644 --- a/ndb/include/ndbapi/NdbIndexOperation.hpp +++ b/ndb/include/ndbapi/NdbIndexOperation.hpp @@ -29,7 +29,7 @@ #ifndef NdbIndexOperation_H #define NdbIndexOperation_H -#include +#include "NdbOperation.hpp" class Index; class NdbResultSet; diff --git a/ndb/include/ndbapi/NdbIndexScanOperation.hpp b/ndb/include/ndbapi/NdbIndexScanOperation.hpp new file mode 100644 index 00000000000..3f64880bbc0 --- /dev/null +++ b/ndb/include/ndbapi/NdbIndexScanOperation.hpp @@ -0,0 +1,140 @@ +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#ifndef NdbIndexScanOperation_H +#define NdbIndexScanOperation_H + +#include + +/** + * @class NdbIndexScanOperation + * @brief Class of scan operations for use to scan ordered index + */ +class NdbIndexScanOperation : public NdbScanOperation { + friend class Ndb; + friend class NdbConnection; + friend class NdbResultSet; + friend class NdbOperation; + friend class NdbScanOperation; +public: + /** + * readTuples returns a NdbResultSet where tuples are stored. + * Tuples are not stored in NdbResultSet until execute(NoCommit) + * has been executed and nextResult has been called. + * + * @param parallel Scan parallelism + * @param batch No of rows to fetch from each fragment at a time + * @param LockMode Scan lock handling + * @param order_by Order result set in index order + * @returns NdbResultSet. + * @see NdbScanOperation::readTuples + */ + NdbResultSet* readTuples(LockMode = LM_Read, + Uint32 batch = 0, + Uint32 parallel = 0, + bool order_by = false); + + inline NdbResultSet* readTuples(int parallell){ + return readTuples(LM_Read, 0, parallell, false); + } + + inline NdbResultSet* readTuplesExclusive(int parallell = 0){ + return readTuples(LM_Exclusive, 0, parallell, false); + } + + /** + * @name Define Range Scan + * + * A range scan is a scan on an ordered index. The operation is on + * the index table but tuples are returned from the primary table. + * The index contains all tuples where at least one index key has not + * null value. + * + * A range scan is currently opened via a normal open scan method. + * Bounds can be defined for each index key. After setting bounds, + * usual scan methods can be used (get value, interpreter, take over). + * These operate on the primary table. + * + * @{ + */ + + /** + * Type of ordered index key bound. The values (0-4) will not change + * and can be used explicitly (e.g. they could be computed). + */ + enum BoundType { + BoundLE = 0, ///< lower bound, + BoundLT = 1, ///< lower bound, strict + BoundGE = 2, ///< upper bound + BoundGT = 3, ///< upper bound, strict + BoundEQ = 4 ///< equality + }; + + /** + * Define bound on index key in range scan. + * + * Each index key can have not null lower and/or upper bound, or can + * be set equal to not null value. The bounds can be defined in any + * order but a duplicate definition is an error. + * + * The scan is most effective when bounds are given for an initial + * sequence of non-nullable index keys, and all but the last one is an + * equality. In this case the scan returns a contiguous range from + * each ordered index fragment. + * + * @note This release implements only the case described above, + * except for the non-nullable limitation. Other sets of + * bounds return error or empty result set. + * + * @note In this release a null key value satisfies any lower + * bound and no upper bound. This may change. + * + * @param attrName Attribute name, alternatively: + * @param anAttrId Index column id (starting from 0). + * @param type Type of bound + * @param value Pointer to bound value + * @param len Value length in bytes. + * Fixed per datatype and can be omitted + * @return 0 if successful otherwise -1 + */ + int setBound(const char* attr, int type, const void* aValue, Uint32 len = 0); + + /** + * Define bound on index key in range scan using index column id. + * See the other setBound() method for details. + */ + int setBound(Uint32 anAttrId, int type, const void* aValue, Uint32 len = 0); + + /** @} *********************************************************************/ + +private: + NdbIndexScanOperation(Ndb* aNdb); + virtual ~NdbIndexScanOperation(); + + int setBound(const NdbColumnImpl*, int type, const void* aValue, Uint32 len); + + virtual int equal_impl(const NdbColumnImpl*, const char*, Uint32); + virtual NdbRecAttr* getValue_impl(const NdbColumnImpl*, char*); + + void fix_get_values(); + int next_result_ordered(bool fetchAllowed); + int send_next_scan_ordered(Uint32 idx); + int compare(Uint32 key, Uint32 cols, const NdbReceiver*, const NdbReceiver*); + + Uint32 m_sort_columns; +}; + +#endif diff --git a/ndb/include/ndbapi/NdbOperation.hpp b/ndb/include/ndbapi/NdbOperation.hpp index 0706afa5cb3..c8e4ac3b6a5 100644 --- a/ndb/include/ndbapi/NdbOperation.hpp +++ b/ndb/include/ndbapi/NdbOperation.hpp @@ -42,7 +42,8 @@ class NdbOperation friend class NdbScanReceiver; friend class NdbScanFilter; friend class NdbScanFilterImpl; - + friend class NdbReceiver; + public: /** * @name Define Standard Operation Type @@ -195,197 +196,8 @@ public: */ virtual int interpretedDeleteTuple(); - /** - * Scan a table to read tuples. - * - * The operation only sets a temporary read lock while - * reading the tuple. - * The tuple lock is released when the result of the read reaches the - * application. - * - * @param Parallelism Number of parallel tuple reads are performed - * in the scan. - * Currently a maximum of 256 parallel tuple - * reads are allowed. - * The parallelism can in reality be lower - * than specified - * depending on the number of nodes - * in the cluster - * @return 0 if successful otherwise -1. - */ - int openScanRead(Uint32 Parallelism = 16 ); - - /** - * Scan a table to write or update tuples. - * - * The operation sets an exclusive lock on the tuple and sends the result - * to the application. - * Thus when the application reads the data, the tuple is - * still locked with an exclusive lock. - * - * @param parallelism Number of parallel tuple reads are performed - * in the scan. - * Currently a maximum of 256 parallel tuple - * reads are allowed. - * The parallelism can in reality be lower - * than specified depending on the number - * of nodes in the cluster - * @return 0 if successful otherwise -1. - * - */ - int openScanExclusive(Uint32 parallelism = 16); - - /** - * Scan a table to read tuples. - * - * The operation only sets a read lock while - * reading the tuple. - * Thus when the application reads the data, the tuple is - * still locked with a read lock. - * - * @param parallelism Number of parallel tuple reads are performed - * in the scan. - * Currently a maximum of 256 parallel tuple - * reads are allowed. - * The parallelism can in reality be lower - * than specified - * depending on the number of nodes - * in the cluster - * @return 0 if successful otherwise -1. - */ - int openScanReadHoldLock(Uint32 parallelism = 16); - - /** - * Scan a table to read tuples. - * - * The operation does not wait for locks held by other transactions - * but returns the latest committed tuple instead. - * - * @param parallelism Number of parallel tuple reads are performed - * in the scan. - * Currently a maximum of 256 parallel tuple - * reads are allowed. - * The parallelism can in reality be lower - * than specified - * depending on the number of nodes - * in the cluster - * @return 0 if successful otherwise -1. - */ - int openScanReadCommitted(Uint32 parallelism = 16); - /** @} *********************************************************************/ - /** - * @name Define Range Scan - * - * A range scan is a scan on an ordered index. The operation is on - * the index table but tuples are returned from the primary table. - * The index contains all tuples where at least one index key has not - * null value. - * - * A range scan is currently opened via a normal open scan method. - * Bounds can be defined for each index key. After setting bounds, - * usual scan methods can be used (get value, interpreter, take over). - * These operate on the primary table. - * - * @{ - */ - - /** - * Type of ordered index key bound. The values (0-4) will not change - * and can be used explicitly (e.g. they could be computed). - */ - enum BoundType { - BoundLE = 0, ///< lower bound, - BoundLT = 1, ///< lower bound, strict - BoundGE = 2, ///< upper bound - BoundGT = 3, ///< upper bound, strict - BoundEQ = 4 ///< equality - }; - - /** - * Define bound on index key in range scan. - * - * Each index key can have not null lower and/or upper bound, or can - * be set equal to not null value. The bounds can be defined in any - * order but a duplicate definition is an error. - * - * The scan is most effective when bounds are given for an initial - * sequence of non-nullable index keys, and all but the last one is an - * equality. In this case the scan returns a contiguous range from - * each ordered index fragment. - * - * @note This release implements only the case described above, - * except for the non-nullable limitation. Other sets of - * bounds return error or empty result set. - * - * @note In this release a null key value satisfies any lower - * bound and no upper bound. This may change. - * - * @param attrName Attribute name, alternatively: - * @param anAttrId Index column id (starting from 0). - * @param type Type of bound - * @param value Pointer to bound value - * @param len Value length in bytes. - * Fixed per datatype and can be omitted - * @return 0 if successful otherwise -1 - */ - int setBound(const char* anAttrName, int type, const void* aValue, Uint32 len = 0); - - /** - * Define bound on index key in range scan using index column id. - * See the other setBound() method for details. - */ - int setBound(Uint32 anAttrId, int type, const void* aValue, Uint32 len = 0); - - /** @} *********************************************************************/ - - /** - * Validate parallelism parameter by checking the number - * against number of executing Ndb nodes. - * - * @param Parallelism - * @return 0 if correct parallelism value, otherwise -1. - * - */ - int checkParallelism(Uint32 Parallelism); - - /** - * Transfer scan operation to an updating transaction. Use this function - * when a scan has found a record that you want to update. - * 1. Start a new transaction. - * 2. Call the function takeOverForUpdate using your new transaction - * as parameter, all the properties of the found record will be copied - * to the new transaction. - * 3. When you execute the new transaction, the lock held by the scan will - * be transferred to the new transaction(it's taken over). - * - * @note You must have started the scan with openScanExclusive - * to be able to update the found tuple. - * - * @param updateTrans the update transaction connection. - * @return an NdbOperation or NULL. - */ - NdbOperation* takeOverForUpdate(NdbConnection* updateTrans); - - /** - * Transfer scan operation to a deleting transaction. Use this function - * when a scan has found a record that you want to delete. - * 1. Start a new transaction. - * 2. Call the function takeOverForDelete using your new transaction - * as parameter, all the properties of the found record will be copied - * to the new transaction. - * 3. When you execute the new transaction, the lock held by the scan will - * be transferred to the new transaction(its taken over). - * - * @note You must have started the scan with openScanExclusive - * to be able to delete the found tuple. - * - * @param deleteTrans the delete transaction connection. - * @return an NdbOperation or NULL. - */ - NdbOperation* takeOverForDelete(NdbConnection* deleteTrans); - /** * @name Specify Search Conditions * @{ @@ -850,16 +662,7 @@ protected: // Initialise after allocating operation to a transaction //-------------------------------------------------------------- int init(class NdbTableImpl*, NdbConnection* aCon); - - void initScan(); // Initialise after allocating operation - // to a scan transaction - virtual void releaseScan(); // Release scan parts of transaction - void releaseSignals(); - void releaseScanSignals(); - void prepareNextScanResult(); - - // Common part for Read and Exclusive - int openScan(Uint32 aParallelism, bool, bool, bool); + void initInterpreter(); void next(NdbOperation*); // Set next pointer @@ -891,11 +694,6 @@ protected: *****************************************************************************/ int doSend(int ProcessorId, Uint32 lastFlag); - int doSendScan(int ProcessorId); - - int prepareSendScan(Uint32 TC_ConnectPtr, - Uint64 TransactionId); - virtual int prepareSend(Uint32 TC_ConnectPtr, Uint64 TransactionId); virtual void setLastFlag(NdbApiSignal* signal, Uint32 lastFlag); @@ -922,7 +720,7 @@ protected: virtual int equal_impl(const NdbColumnImpl* anAttrObject, const char* aValue, Uint32 len); - NdbRecAttr* getValue(const NdbColumnImpl* anAttrObject, char* aValue = 0); + NdbRecAttr* getValue_impl(const NdbColumnImpl* anAttrObject, char* aValue = 0); int setValue(const NdbColumnImpl* anAttrObject, const char* aValue, Uint32 len); int incValue(const NdbColumnImpl* anAttrObject, Uint32 aValue); int incValue(const NdbColumnImpl* anAttrObject, Uint64 aValue); @@ -933,15 +731,12 @@ protected: int branch_reg_reg(Uint32 type, Uint32, Uint32, Uint32); int branch_col(Uint32 type, Uint32, const char *, Uint32, bool, Uint32 Label); int branch_col_null(Uint32 type, Uint32 col, Uint32 Label); - int setBound(const NdbColumnImpl* anAttrObject, int type, const void* aValue, Uint32 len); // Handle ATTRINFO signals int receiveREAD_AI(Uint32* aDataPtr, Uint32 aLength); int insertATTRINFO(Uint32 aData); int insertATTRINFOloop(const Uint32* aDataPtr, Uint32 aLength); - int getFirstATTRINFOScan(); - int saveBoundATTRINFO(); int insertKEYINFO(const char* aValue, Uint32 aStartPosition, @@ -965,9 +760,6 @@ protected: Uint32 ptr2int() { return theReceiver.getId(); }; - NdbOperation* - takeOverScanOp(OperationType opType, NdbConnection* updateTrans); - /****************************************************************************** * These are the private variables that are defined in the operation objects. *****************************************************************************/ @@ -980,7 +772,6 @@ protected: Ndb* theNdb; // Point back to the Ndb object. NdbConnection* theNdbCon; // Point back to the connection object. NdbOperation* theNext; // Next pointer to operation. - NdbOperation* theNextScanOp; NdbApiSignal* theTCREQ; // The TC[KEY/INDX]REQ signal object NdbApiSignal* theFirstATTRINFO; // The first ATTRINFO signal object NdbApiSignal* theCurrentATTRINFO; // The current ATTRINFO signal object @@ -991,9 +782,6 @@ protected: NdbApiSignal* theFirstKEYINFO; // The first KEYINFO signal object NdbApiSignal* theLastKEYINFO; // The first KEYINFO signal object - NdbRecAttr* theFirstRecAttr; // The first receive attribute object - NdbRecAttr* theCurrentRecAttr; // The current receive attribute object - class NdbLabel* theFirstLabel; class NdbLabel* theLastLabel; class NdbBranch* theFirstBranch; @@ -1008,15 +796,6 @@ protected: Uint32* theKEYINFOptr; // Pointer to where to write KEYINFO Uint32* theATTRINFOptr; // Pointer to where to write ATTRINFO - Uint32 theTotalRecAI_Len; // The total length received according - // to the TCKEYCONF signal - Uint32 theCurrRecAI_Len; // The currently received length - Uint32 theAI_ElementLen; // How many words long is this element - Uint32* theCurrElemPtr; // The current pointer to the element - //Uint32 theTableId; // Table id. - //Uint32 theAccessTableId; // The id of table for initial access, - // changed by NdbIndexOperation - //Uint32 theSchemaVersion; // The schema version on the table. class NdbTableImpl* m_currentTable; // The current table class NdbTableImpl* m_accessTable; @@ -1059,15 +838,6 @@ protected: Uint16 m_keyInfoGSN; Uint16 m_attrInfoGSN; - // Scan related variables - Uint32 theParallelism; - NdbScanReceiver** theScanReceiversArray; - NdbApiSignal* theSCAN_TABREQ; - NdbApiSignal* theFirstSCAN_TABINFO_Send; - NdbApiSignal* theLastSCAN_TABINFO_Send; - NdbApiSignal* theFirstSCAN_TABINFO_Recv; - NdbApiSignal* theLastSCAN_TABINFO_Recv; - NdbApiSignal* theSCAN_TABCONF_Recv; // saveBoundATTRINFO() moves ATTRINFO here when setBound() is ready NdbApiSignal* theBoundATTRINFO; Uint32 theTotalBoundAI_Len; diff --git a/ndb/include/ndbapi/NdbRecAttr.hpp b/ndb/include/ndbapi/NdbRecAttr.hpp index 7eeff88671d..ece288ba1c4 100644 --- a/ndb/include/ndbapi/NdbRecAttr.hpp +++ b/ndb/include/ndbapi/NdbRecAttr.hpp @@ -75,8 +75,9 @@ class AttrInfo; class NdbRecAttr { friend class NdbOperation; + friend class NdbIndexScanOperation; friend class NdbEventOperationImpl; - friend class NdbScanReceiver; + friend class NdbReceiver; friend class Ndb; public: @@ -247,9 +248,8 @@ private: NdbRecAttr(); Uint32 attrId() const; /* Get attribute id */ - void setNULL(); /* Set NULL indicator */ - void setNotNULL(); /* Set Not NULL indicator */ - void setUNDEFINED(); /* Set UNDEFINED indicator */ + bool setNULL(); /* Set NULL indicator */ + bool receive_data(const Uint32*, Uint32); void release(); /* Release memory if allocated */ void init(); /* Initialise object when allocated */ @@ -257,6 +257,7 @@ private: void next(NdbRecAttr* aRecAttr); NdbRecAttr* next() const; + int setup(const class NdbColumnImpl* anAttrInfo, char* aValue); /* Set up attributes and buffers */ bool copyoutRequired() const; /* Need to copy data to application */ @@ -271,6 +272,7 @@ private: Uint32 theAttrId; /* The attribute id */ int theNULLind; + bool m_nullable; Uint32 theAttrSize; Uint32 theArraySize; const NdbDictionary::Column* m_column; @@ -291,29 +293,7 @@ NdbRecAttr::getColumn() const { inline Uint32 NdbRecAttr::attrSize() const { - - switch(getType()){ - case NdbDictionary::Column::Int: - case NdbDictionary::Column::Unsigned: - case NdbDictionary::Column::Float: - return 4; - case NdbDictionary::Column::Decimal: - case NdbDictionary::Column::Char: - case NdbDictionary::Column::Varchar: - case NdbDictionary::Column::Binary: - case NdbDictionary::Column::Varbinary: - return 1; - case NdbDictionary::Column::Bigint: - case NdbDictionary::Column::Bigunsigned: - case NdbDictionary::Column::Double: - case NdbDictionary::Column::Datetime: - return 8; - case NdbDictionary::Column::Timespec: - return 12; - case NdbDictionary::Column::Undefined: - default: - return 0; - } + return theAttrSize; } inline @@ -478,24 +458,11 @@ NdbRecAttr::attrId() const } inline -void +bool NdbRecAttr::setNULL() { theNULLind = 1; -} - -inline -void -NdbRecAttr::setNotNULL() -{ - theNULLind = 0; -} - -inline -void -NdbRecAttr::setUNDEFINED() -{ - theNULLind = -1; + return m_nullable; } inline diff --git a/ndb/include/ndbapi/NdbReceiver.hpp b/ndb/include/ndbapi/NdbReceiver.hpp index a1a08a9735a..5f69887f402 100644 --- a/ndb/include/ndbapi/NdbReceiver.hpp +++ b/ndb/include/ndbapi/NdbReceiver.hpp @@ -23,6 +23,12 @@ class Ndb; class NdbReceiver { + friend class Ndb; + friend class NdbOperation; + friend class NdbScanOperation; + friend class NdbIndexOperation; + friend class NdbIndexScanOperation; + friend class NdbConnection; public: enum ReceiverType { NDB_UNINITIALIZED, NDB_OPERATION = 1, @@ -31,7 +37,8 @@ public: }; NdbReceiver(Ndb *aNdb); - void init(ReceiverType type, void* owner); + void init(ReceiverType type, void* owner, bool keyInfo); + void release(); ~NdbReceiver(); Uint32 getId(){ @@ -42,18 +49,51 @@ public: return m_type; } + inline NdbConnection * getTransaction(); void* getOwner(){ return m_owner; } bool checkMagicNumber() const; + inline void next(NdbReceiver* next) { m_next = next;} + inline NdbReceiver* next() { return m_next; } + private: Uint32 theMagicNumber; Ndb* m_ndb; Uint32 m_id; + Uint32 m_tcPtrI; + Uint32 m_key_info; ReceiverType m_type; void* m_owner; + NdbReceiver* m_next; + + /** + * At setup + */ + class NdbRecAttr * getValue(const class NdbColumnImpl*, char * user_dst_ptr); + void do_get_value(NdbReceiver*, Uint32 rows, Uint32 key_size); + void prepareSend(); + + int execKEYINFO20(Uint32 info, const Uint32* ptr, Uint32 len); + int execTRANSID_AI(const Uint32* ptr, Uint32 len); + int execTCOPCONF(Uint32 len); + int execSCANOPCONF(Uint32 tcPtrI, Uint32 len, Uint32 rows); + class NdbRecAttr* theFirstRecAttr; + class NdbRecAttr* theCurrentRecAttr; + class NdbRecAttr** m_rows; + + Uint32 m_list_index; // When using multiple + Uint32 m_current_row; + Uint32 m_result_rows; + Uint32 m_defined_rows; + + Uint32 m_expected_result_length; + Uint32 m_received_result_length; + + bool nextResult() const { return m_current_row < m_result_rows; } + void copyout(NdbReceiver&); }; #ifdef NDB_NO_DROPPED_SIGNAL @@ -72,5 +112,32 @@ NdbReceiver::checkMagicNumber() const { return retVal; } +inline +void +NdbReceiver::prepareSend(){ + m_current_row = 0; + m_received_result_length = 0; + m_expected_result_length = 0; + theCurrentRecAttr = theFirstRecAttr; +} + +inline +int +NdbReceiver::execTCOPCONF(Uint32 len){ + Uint32 tmp = m_received_result_length; + m_expected_result_length = len; + return (tmp == len ? 1 : 0); +} + +inline +int +NdbReceiver::execSCANOPCONF(Uint32 tcPtrI, Uint32 len, Uint32 rows){ + m_tcPtrI = tcPtrI; + m_result_rows = rows; + Uint32 tmp = m_received_result_length; + m_expected_result_length = len; + return (tmp == len ? 1 : 0); +} + #endif #endif diff --git a/ndb/include/ndbapi/NdbResultSet.hpp b/ndb/include/ndbapi/NdbResultSet.hpp index d48df01214e..7cf18a6685d 100644 --- a/ndb/include/ndbapi/NdbResultSet.hpp +++ b/ndb/include/ndbapi/NdbResultSet.hpp @@ -30,17 +30,15 @@ #define NdbResultSet_H -#include -#include #include /** * @class NdbResultSet - * @brief NdbResultSet contains a NdbCursorOperation. + * @brief NdbResultSet contains a NdbScanOperation. */ class NdbResultSet { - friend class NdbCursorOperation; + friend class NdbScanOperation; public: @@ -93,22 +91,57 @@ public: */ int nextResult(bool fetchAllowed = true); + /** + * Close result set (scan) + */ void close(); + /** + * Transfer scan operation to an updating transaction. Use this function + * when a scan has found a record that you want to update. + * 1. Start a new transaction. + * 2. Call the function takeOverForUpdate using your new transaction + * as parameter, all the properties of the found record will be copied + * to the new transaction. + * 3. When you execute the new transaction, the lock held by the scan will + * be transferred to the new transaction(it's taken over). + * + * @note You must have started the scan with openScanExclusive + * to be able to update the found tuple. + * + * @param updateTrans the update transaction connection. + * @return an NdbOperation or NULL. + */ NdbOperation* updateTuple(); - NdbOperation* updateTuple(NdbConnection* takeOverTransaction); - + NdbOperation* updateTuple(NdbConnection* updateTrans); + + /** + * Transfer scan operation to a deleting transaction. Use this function + * when a scan has found a record that you want to delete. + * 1. Start a new transaction. + * 2. Call the function takeOverForDelete using your new transaction + * as parameter, all the properties of the found record will be copied + * to the new transaction. + * 3. When you execute the new transaction, the lock held by the scan will + * be transferred to the new transaction(its taken over). + * + * @note You must have started the scan with openScanExclusive + * to be able to delete the found tuple. + * + * @param deleteTrans the delete transaction connection. + * @return an NdbOperation or NULL. + */ int deleteTuple(); int deleteTuple(NdbConnection* takeOverTransaction); private: - NdbResultSet(NdbCursorOperation*); + NdbResultSet(NdbScanOperation*); ~NdbResultSet(); void init(); - NdbCursorOperation* m_operation; + NdbScanOperation* m_operation; }; #endif diff --git a/ndb/include/ndbapi/NdbScanOperation.hpp b/ndb/include/ndbapi/NdbScanOperation.hpp index f83669fb616..8ff640dc6ec 100644 --- a/ndb/include/ndbapi/NdbScanOperation.hpp +++ b/ndb/include/ndbapi/NdbScanOperation.hpp @@ -29,67 +29,74 @@ #ifndef NdbScanOperation_H #define NdbScanOperation_H - #include -#include /** * @class NdbScanOperation * @brief Class of scan operations for use in transactions. */ -class NdbScanOperation : public NdbCursorOperation -{ +class NdbScanOperation : public NdbOperation { friend class Ndb; friend class NdbConnection; friend class NdbResultSet; friend class NdbOperation; public: + /** + * Type of cursor + */ + enum CursorType { + NoCursor = 0, + ScanCursor = 1, + IndexCursor = 2 + }; + + /** + * Lock when performing scan + */ + enum LockMode { + LM_Read = 0, + LM_Exclusive = 1, + LM_CommittedRead = 2, +#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL + LM_Dirty = 2 +#endif + }; + + /** + * Type of cursor + */ + CursorType get_cursor_type() const; + /** * readTuples returns a NdbResultSet where tuples are stored. * Tuples are not stored in NdbResultSet until execute(NoCommit) * has been executed and nextResult has been called. * * @param parallel Scan parallelism + * @param batch No of rows to fetch from each fragment at a time * @param LockMode Scan lock handling * @returns NdbResultSet. + * @note specifying 0 for batch and parallall means max performance */ - virtual NdbResultSet* readTuples(unsigned parallel = 0, - LockMode = LM_Read ); + NdbResultSet* readTuples(LockMode = LM_Read, + Uint32 batch = 0, Uint32 parallel = 0); -#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL + inline NdbResultSet* readTuples(int parallell){ + return readTuples(LM_Read, 0, parallell); + } + + inline NdbResultSet* readTuplesExclusive(int parallell = 0){ + return readTuples(LM_Exclusive, 0, parallell); + } + +protected: + CursorType m_cursor_type; - int updateTuples(); - int updateTuples(Uint32 parallelism); - - int deleteTuples(); - int deleteTuples(Uint32 parallelism); - - // Overload setValue for updateTuples - int setValue(const char* anAttrName, const char* aValue, Uint32 len = 0); - int setValue(const char* anAttrName, Int32 aValue); - int setValue(const char* anAttrName, Uint32 aValue); - int setValue(const char* anAttrName, Int64 aValue); - int setValue(const char* anAttrName, Uint64 aValue); - int setValue(const char* anAttrName, float aValue); - int setValue(const char* anAttrName, double aValue); - - int setValue(Uint32 anAttrId, const char* aValue, Uint32 len = 0); - int setValue(Uint32 anAttrId, Int32 aValue); - int setValue(Uint32 anAttrId, Uint32 aValue); - int setValue(Uint32 anAttrId, Int64 aValue); - int setValue(Uint32 anAttrId, Uint64 aValue); - int setValue(Uint32 anAttrId, float aValue); - int setValue(Uint32 anAttrId, double aValue); -#endif -private: NdbScanOperation(Ndb* aNdb); - ~NdbScanOperation(); - NdbCursorOperation::CursorType cursorType(); - - virtual int nextResult(bool fetchAllowed = true); + int nextResult(bool fetchAllowed = true); virtual void release(); void closeScan(); @@ -105,125 +112,51 @@ private: virtual void setErrorCode(int aErrorCode); virtual void setErrorCodeAbort(int aErrorCode); - virtual int equal_impl(const NdbColumnImpl* anAttrObject, - const char* aValue, - Uint32 len); -private: + NdbResultSet * m_resultSet; + NdbResultSet* getResultSet(); NdbConnection *m_transConnection; - bool m_autoExecute; - bool m_updateOp; - bool m_writeOp; - bool m_deleteOp; - class SetValueRecList* m_setValueList; -}; -#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL -class AttrInfo; -class SetValueRecList; + // Scan related variables + Uint32 theBatchSize; + Uint32 theParallelism; + Uint32 m_keyInfo; + NdbApiSignal* theSCAN_TABREQ; -class SetValueRec { - friend class SetValueRecList; -public: - SetValueRec(); - ~SetValueRec(); - - enum SetValueType { - SET_STRING_ATTR1 = 0, - SET_INT32_ATTR1 = 1, - SET_UINT32_ATTR1 = 2, - SET_INT64_ATTR1 = 3, - SET_UINT64_ATTR1 = 4, - SET_FLOAT_ATTR1 = 5, - SET_DOUBLE_ATTR1 = 6, - SET_STRING_ATTR2 = 7, - SET_INT32_ATTR2 = 8, - SET_UINT32_ATTR2 = 9, - SET_INT64_ATTR2 = 10, - SET_UINT64_ATTR2 = 11, - SET_FLOAT_ATTR2 = 12, - SET_DOUBLE_ATTR2 = 13 - }; - - SetValueType stype; - union { - char* anAttrName; - Uint32 anAttrId; - }; - struct String { - char* aStringValue; - Uint32 len; - }; - union { - String stringStruct; - Int32 anInt32Value; - Uint32 anUint32Value; - Int64 anInt64Value; - Uint64 anUint64Value; - float aFloatValue; - double aDoubleValue; - }; -private: - SetValueRec* next; -}; - -inline -SetValueRec::SetValueRec() : - next(0) -{ -} - -class SetValueRecList { -public: - SetValueRecList(); - ~SetValueRecList(); - - void add(const char* anAttrName, const char* aValue, Uint32 len = 0); - void add(const char* anAttrName, Int32 aValue); - void add(const char* anAttrName, Uint32 aValue); - void add(const char* anAttrName, Int64 aValue); - void add(const char* anAttrName, Uint64 aValue); - void add(const char* anAttrName, float aValue); - void add(const char* anAttrName, double aValue); - void add(Uint32 anAttrId, const char* aValue, Uint32 len = 0); - void add(Uint32 anAttrId, Int32 aValue); - void add(Uint32 anAttrId, Uint32 aValue); - void add(Uint32 anAttrId, Int64 aValue); - void add(Uint32 anAttrId, Uint64 aValue); - void add(Uint32 anAttrId, float aValue); - void add(Uint32 anAttrId, double aValue); - - typedef void(* IterateFn)(SetValueRec&, NdbOperation&); - static void callSetValueFn(SetValueRec&, NdbOperation&); - void iterate(IterateFn nextfn, NdbOperation&); -private: - SetValueRec* first; - SetValueRec* last; -}; - -inline -SetValueRecList::SetValueRecList() : - first(0), - last(0) -{ -} + int getFirstATTRINFOScan(); + int saveBoundATTRINFO(); + int doSendScan(int ProcessorId); + int prepareSendScan(Uint32 TC_ConnectPtr, Uint64 TransactionId); -inline -SetValueRecList::~SetValueRecList() { - if (first) delete first; - first = last = 0; -} + int fix_receivers(Uint32 parallel, bool keyInfo); + Uint32 m_allocated_receivers; + NdbReceiver** m_receivers; // All receivers + Uint32* m_prepared_receivers; // These are to be sent + + Uint32 m_current_api_receiver; + Uint32 m_api_receivers_count; + NdbReceiver** m_api_receivers; // These are currently used by api + + Uint32 m_conf_receivers_count; // NOTE needs mutex to access + NdbReceiver** m_conf_receivers; // receive thread puts them here + + Uint32 m_sent_receivers_count; // NOTE needs mutex to access + NdbReceiver** m_sent_receivers; // receive thread puts them here + + int send_next_scan(Uint32 cnt, bool close); + void receiver_delivered(NdbReceiver*); + void receiver_completed(NdbReceiver*); + void execCLOSE_SCAN_REP(Uint32 errCode); + + NdbOperation* takeOverScanOp(OperationType opType, NdbConnection*); + + Uint32 m_ordered; +}; inline -void SetValueRecList::iterate(SetValueRecList::IterateFn nextfn, NdbOperation& oper) -{ - SetValueRec* recPtr = first; - while(recPtr) { - (*nextfn)(*recPtr, oper); - recPtr = recPtr->next; // Move to next in list - MASV - } +NdbScanOperation::CursorType +NdbScanOperation::get_cursor_type() const { + return m_cursor_type; } #endif - -#endif diff --git a/ndb/src/common/debugger/signaldata/DictTabInfo.cpp b/ndb/src/common/debugger/signaldata/DictTabInfo.cpp index a0e0195adad..7e7bf87e2db 100644 --- a/ndb/src/common/debugger/signaldata/DictTabInfo.cpp +++ b/ndb/src/common/debugger/signaldata/DictTabInfo.cpp @@ -48,6 +48,7 @@ DictTabInfo::TableMapping[] = { DTIMAP(Table, CustomTriggerId, CustomTriggerId), DTIMAP2(Table, FrmLen, FrmLen, 0, MAX_FRM_DATA_SIZE), DTIMAPB(Table, FrmData, FrmData, 0, MAX_FRM_DATA_SIZE, FrmLen), + DTIMAP(Table, FragmentCount, FragmentCount), DTIBREAK(AttributeName) }; @@ -128,6 +129,7 @@ DictTabInfo::Table::init(){ CustomTriggerId = RNIL; FrmLen = 0; memset(FrmData, 0, sizeof(FrmData)); + FragmentCount = 0; } void diff --git a/ndb/src/common/debugger/signaldata/ScanTab.cpp b/ndb/src/common/debugger/signaldata/ScanTab.cpp index b4246059f6a..776e9cf3bfc 100644 --- a/ndb/src/common/debugger/signaldata/ScanTab.cpp +++ b/ndb/src/common/debugger/signaldata/ScanTab.cpp @@ -30,20 +30,34 @@ printSCANTABREQ(FILE * output, const Uint32 * theData, Uint32 len, Uint16 receiv fprintf(output, " apiConnectPtr: H\'%.8x\n", sig->apiConnectPtr); fprintf(output, " requestInfo: H\'%.8x:\n", requestInfo); - fprintf(output, " Parallellism: %u, LockMode: %u, Holdlock: %u, RangeScan: %u\n", - sig->getParallelism(requestInfo), sig->getLockMode(requestInfo), sig->getHoldLockFlag(requestInfo), sig->getRangeScanFlag(requestInfo)); - + fprintf(output, " Parallellism: %u, Batch: %u LockMode: %u, Holdlock: %u, RangeScan: %u\n", + sig->getParallelism(requestInfo), + sig->getScanBatch(requestInfo), + sig->getLockMode(requestInfo), + sig->getHoldLockFlag(requestInfo), + sig->getRangeScanFlag(requestInfo)); + fprintf(output, " attrLen: %d, tableId: %d, tableSchemaVer: %d\n", sig->attrLen, sig->tableId, sig->tableSchemaVersion); fprintf(output, " transId(1, 2): (H\'%.8x, H\'%.8x) storedProcId: H\'%.8x\n", sig->transId1, sig->transId2, sig->storedProcId); - fprintf(output, " OperationPtr(s):\n"); - for(int i = 0; i<16; i=i+4){ - fprintf(output, " H\'%.8x, H\'%.8x, H\'%.8x, H\'%.8x\n", - sig->apiOperationPtr[i], sig->apiOperationPtr[i+1], - sig->apiOperationPtr[i+2], sig->apiOperationPtr[i+3]); + fprintf(output, " OperationPtr(s):\n "); + Uint32 restLen = (len - 9); + const Uint32 * rest = &sig->apiOperationPtr[0]; + while(restLen >= 7){ + fprintf(output, + " H\'%.8x H\'%.8x H\'%.8x H\'%.8x H\'%.8x H\'%.8x H\'%.8x\n", + rest[0], rest[1], rest[2], rest[3], + rest[4], rest[5], rest[6]); + restLen -= 7; + rest += 7; + } + if(restLen > 0){ + for(Uint32 i = 0; itransId1, sig->transId2); - fprintf(output, " requestInfo: H\'%.8x(Operations: %u, ScanStatus: %u(\"", - requestInfo, sig->getOperations(requestInfo), sig->getScanStatus(requestInfo)); - switch(sig->getScanStatus(requestInfo)){ - case 0: - fprintf(output, "ZFALSE"); - break; - case 1: - fprintf(output, "ZTRUE"); - break; - case 2: - fprintf(output, "ZCLOSED"); - break; - default: - fprintf(output, "UNKNOWN"); - break; - } - fprintf(output, "\"))\n"); + fprintf(output, " requestInfo: H\'%.8x(EndOfData: %d)\n", + requestInfo, (requestInfo & ScanTabConf::EndOfData != 0)); #if 0 fprintf(output, " Operation(s):\n"); for(int i = 0; i<16; i++){ diff --git a/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp b/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp index 7eb7f995eb7..6cac2f00542 100644 --- a/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp +++ b/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp @@ -114,6 +114,8 @@ Cmvmi::Cmvmi(const Configuration & conf) : } setNodeInfo(nodeId).m_type = nodeType; } + + setNodeInfo(getOwnNodeId()).m_connected = true; } Cmvmi::~Cmvmi() diff --git a/ndb/src/kernel/blocks/dbdict/Dbdict.cpp b/ndb/src/kernel/blocks/dbdict/Dbdict.cpp index 084f41e4166..a11205047e5 100644 --- a/ndb/src/kernel/blocks/dbdict/Dbdict.cpp +++ b/ndb/src/kernel/blocks/dbdict/Dbdict.cpp @@ -75,7 +75,6 @@ #include #include #include -#include "../dbtc/Dbtc.hpp" #include #define ZNOT_FOUND 626 @@ -254,6 +253,7 @@ Dbdict::packTableIntoPagesImpl(SimpleProperties::Writer & w, w.add(DictTabInfo::FragmentTypeVal, tablePtr.p->fragmentType); w.add(DictTabInfo::FragmentKeyTypeVal, tablePtr.p->fragmentKeyType); w.add(DictTabInfo::TableTypeVal, tablePtr.p->tableType); + w.add(DictTabInfo::FragmentCount, tablePtr.p->fragmentCount); if (tablePtr.p->primaryTableId != RNIL){ TableRecordPtr primTab; @@ -3599,30 +3599,37 @@ Dbdict::execCREATE_FRAGMENTATION_CONF(Signal* signal){ SegmentedSectionPtr fragDataPtr; signal->getSection(fragDataPtr, CreateFragmentationConf::FRAGMENTS); - signal->header.m_noOfSections = 0; /** - * Correct table + * Get table */ TableRecordPtr tabPtr; c_tableRecordPool.getPtr(tabPtr, createTabPtr.p->m_tablePtrI); - PageRecordPtr pagePtr; - c_pageRecordArray.getPtr(pagePtr, c_schemaRecord.schemaPage); - SchemaFile::TableEntry * tabEntry = getTableEntry(pagePtr.p, tabPtr.i); + /** + * Save fragment count + */ + tabPtr.p->fragmentCount = conf->noOfFragments; /** * Update table version */ + PageRecordPtr pagePtr; + c_pageRecordArray.getPtr(pagePtr, c_schemaRecord.schemaPage); + SchemaFile::TableEntry * tabEntry = getTableEntry(pagePtr.p, tabPtr.i); + tabPtr.p->tableVersion = tabEntry->m_tableVersion + 1; - + + /** + * Pack + */ SimplePropertiesSectionWriter w(getSectionSegmentPool()); packTableIntoPagesImpl(w, tabPtr); SegmentedSectionPtr spDataPtr; w.getPtr(spDataPtr); - + signal->setSection(spDataPtr, CreateTabReq::DICT_TAB_INFO); signal->setSection(fragDataPtr, CreateTabReq::FRAGMENTATION); @@ -4252,7 +4259,9 @@ Dbdict::execDIADDTABCONF(Signal* signal){ /** * No local fragment (i.e. no LQHFRAGREQ) */ - sendSignal(DBDIH_REF, GSN_TAB_COMMITREQ, signal, 3, JBB); + execute(signal, createTabPtr.p->m_callback, 0); + return; + //sendSignal(DBDIH_REF, GSN_TAB_COMMITREQ, signal, 3, JBB); } } @@ -4637,6 +4646,7 @@ void Dbdict::handleTabInfoInit(SimpleProperties::Reader & it, tablePtr.p->fragmentKeyType = (DictTabInfo::FragmentKeyType)tableDesc.FragmentKeyType; tablePtr.p->tableType = (DictTabInfo::TableType)tableDesc.TableType; tablePtr.p->kValue = tableDesc.TableKValue; + tablePtr.p->fragmentCount = tableDesc.FragmentCount; tablePtr.p->frmLen = tableDesc.FrmLen; memcpy(tablePtr.p->frmData, tableDesc.FrmData, tableDesc.FrmLen); @@ -5080,8 +5090,20 @@ Dbdict::execPREP_DROP_TAB_REF(Signal* signal){ Uint32 nodeId = refToNode(prep->senderRef); dropTabPtr.p->m_coordinatorData.m_signalCounter.clearWaitingFor(nodeId); - - dropTabPtr.p->setErrorCode((Uint32)prep->errorCode); + + Uint32 block = refToBlock(prep->senderRef); + if((prep->errorCode == PrepDropTabRef::NoSuchTable && block == DBLQH) || + (prep->errorCode == PrepDropTabRef::NF_FakeErrorREF)){ + jam(); + /** + * Ignore errors: + * 1) no such table and LQH, it might not exists in different LQH's + * 2) node failure... + */ + } else { + dropTabPtr.p->setErrorCode((Uint32)prep->errorCode); + } + if(!dropTabPtr.p->m_coordinatorData.m_signalCounter.done()){ jam(); return; @@ -5112,6 +5134,19 @@ void Dbdict::execDROP_TAB_REF(Signal* signal){ jamEntry(); + DropTabRef * const req = (DropTabRef*)signal->getDataPtr(); + + Uint32 block = refToBlock(req->senderRef); + ndbrequire(req->errorCode == DropTabRef::NF_FakeErrorREF || + (req->errorCode == DropTabRef::NoSuchTable && + (block == DBTUP || block == DBACC || block == DBLQH))); + + if(block != DBDICT){ + jam(); + ndbrequire(refToNode(req->senderRef) == getOwnNodeId()); + dropTab_localDROP_TAB_CONF(signal); + return; + } ndbrequire(false); } diff --git a/ndb/src/kernel/blocks/dbdict/Dbdict.hpp b/ndb/src/kernel/blocks/dbdict/Dbdict.hpp index 68214785234..de1d9757b2a 100644 --- a/ndb/src/kernel/blocks/dbdict/Dbdict.hpp +++ b/ndb/src/kernel/blocks/dbdict/Dbdict.hpp @@ -230,7 +230,7 @@ public: Uint32 frmLen; char frmData[MAX_FRM_DATA_SIZE]; - + Uint32 fragmentCount; }; typedef Ptr TableRecordPtr; diff --git a/ndb/src/kernel/blocks/dbdih/DbdihInit.cpp b/ndb/src/kernel/blocks/dbdih/DbdihInit.cpp index df47237ae59..f996a1fe689 100644 --- a/ndb/src/kernel/blocks/dbdih/DbdihInit.cpp +++ b/ndb/src/kernel/blocks/dbdih/DbdihInit.cpp @@ -254,6 +254,7 @@ Dbdih::Dbdih(const class Configuration & config): addRecSignal(GSN_UPDATE_TOCONF, &Dbdih::execUPDATE_TOCONF); addRecSignal(GSN_PREP_DROP_TAB_REQ, &Dbdih::execPREP_DROP_TAB_REQ); + addRecSignal(GSN_WAIT_DROP_TAB_REF, &Dbdih::execWAIT_DROP_TAB_REF); addRecSignal(GSN_WAIT_DROP_TAB_CONF, &Dbdih::execWAIT_DROP_TAB_CONF); addRecSignal(GSN_DROP_TAB_REQ, &Dbdih::execDROP_TAB_REQ); diff --git a/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp b/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp index 0ce1f1e4bbe..059f1301ba2 100644 --- a/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp +++ b/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp @@ -13359,6 +13359,25 @@ Dbdih::checkPrepDropTabComplete(Signal* signal, TabRecordPtr tabPtr){ } } +void +Dbdih::execWAIT_DROP_TAB_REF(Signal* signal){ + jamEntry(); + WaitDropTabRef * ref = (WaitDropTabRef*)signal->getDataPtr(); + + TabRecordPtr tabPtr; + tabPtr.i = ref->tableId; + ptrCheckGuard(tabPtr, ctabFileSize, tabRecord); + + ndbrequire(tabPtr.p->tabStatus == TabRecord::TS_DROPPING); + Uint32 nodeId = refToNode(ref->senderRef); + + ndbrequire(ref->errorCode == WaitDropTabRef::NoSuchTable || + ref->errorCode == WaitDropTabRef::NF_FakeErrorREF); + + tabPtr.p->m_prepDropTab.waitDropTabCount.clearWaitingFor(nodeId); + checkPrepDropTabComplete(signal, tabPtr); +} + void Dbdih::execWAIT_DROP_TAB_CONF(Signal* signal){ jamEntry(); diff --git a/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp b/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp index c342f60e13f..0f47ee4f38e 100644 --- a/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp +++ b/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp @@ -3198,10 +3198,14 @@ void Dblqh::execLQHKEYREQ(Signal* signal) const NodeId tcNodeId = refToNode(sig5); markerPtr.p->tcNodeId = tcNodeId; + CommitAckMarkerPtr tmp; +#ifdef VM_TRACE + ndbrequire(!m_commitAckMarkerHash.find(tmp, * markerPtr.p)); +#endif m_commitAckMarkerHash.add(markerPtr); regTcPtr->commitAckMarker = markerPtr.i; - } - + } + regTcPtr->reqinfo = Treqinfo; regTcPtr->lastReplicaNo = LqhKeyReq::getLastReplicaNo(Treqinfo); regTcPtr->lockType = LqhKeyReq::getLockType(Treqinfo); @@ -7840,27 +7844,10 @@ void Dblqh::scanTupkeyConfLab(Signal* signal) }//if if (scanptr.p->scanKeyinfoFlag) { jam(); - DatabufPtr TdataBuf; - TdataBuf.i = tcConnectptr.p->firstTupkeybuf; - const Uint32 keyLen = tcConnectptr.p->primKeyLen; - const Uint32 dataBufSz = cdatabufFileSize; - - /** - * Note that this code requires signal->theData to be big enough for - * a entire key - */ - ndbrequire(keyLen * 4 <= sizeof(signal->theData)); - KeyInfo20 * keyInfo = (KeyInfo20*)&signal->theData[0]; - for(Uint32 i = 0; i < keyLen; i += 4){ - ptrCheckGuard(TdataBuf, dataBufSz, databuf); - keyInfo->keyData[i + 0] = TdataBuf.p->data[0]; - keyInfo->keyData[i + 1] = TdataBuf.p->data[1]; - keyInfo->keyData[i + 2] = TdataBuf.p->data[2]; - keyInfo->keyData[i + 3] = TdataBuf.p->data[3]; - TdataBuf.i = TdataBuf.p->nextDatabuf; - } sendKeyinfo20(signal, scanptr.p, tcConnectptr.p); releaseOprec(signal); + + tdata4 += tcConnectptr.p->primKeyLen;// Inform API about keyinfo len aswell }//if ndbrequire(scanptr.p->scanCompletedOperations < MAX_PARALLEL_OP_PER_SCAN); scanptr.p->scanOpLength[scanptr.p->scanCompletedOperations] = tdata4; @@ -8297,7 +8284,8 @@ void Dblqh::initScanTc(Signal* signal, tcConnectptr.p->opExec = 1; tcConnectptr.p->operation = ZREAD; tcConnectptr.p->listState = TcConnectionrec::NOT_IN_LIST; - + tcConnectptr.p->commitAckMarker = RNIL; + tabptr.p->usageCount++; }//Dblqh::initScanTc() @@ -8401,72 +8389,119 @@ void Dblqh::sendKeyinfo20(Signal* signal, ndbrequire(scanP->scanCompletedOperations < MAX_PARALLEL_OP_PER_SCAN); KeyInfo20 * keyInfo = (KeyInfo20 *)&signal->theData[0]; + DatabufPtr TdataBuf; + TdataBuf.i = tcConP->firstTupkeybuf; + Uint32 keyLen = tcConP->primKeyLen; + const Uint32 dataBufSz = cdatabufFileSize; + + /** + * Note that this code requires signal->theData to be big enough for + * a entire key + */ + ndbrequire(keyLen * 4 <= sizeof(signal->theData)); + const BlockReference ref = scanP->scanApiBlockref; const Uint32 scanOp = scanP->scanCompletedOperations; + const Uint32 nodeId = refToNode(ref); + const bool connectedToNode = getNodeInfo(nodeId).m_connected; + const Uint32 type = getNodeInfo(nodeId).m_type; + const bool is_api = (type >= NodeInfo::API && type <= NodeInfo::REP); + const bool old_dest = (getNodeInfo(nodeId).m_version < MAKE_VERSION(3,5,0)); + const bool longable = is_api && !old_dest; + + Uint32 * dst = keyInfo->keyData; + dst += nodeId == getOwnNodeId() ? 0 : KeyInfo20::DataLength; + + /** + * Copy keydata from data buffer into signal + * + */ + for(Uint32 i = 0; i < keyLen; i += 4){ + ptrCheckGuard(TdataBuf, dataBufSz, databuf); + * dst++ = TdataBuf.p->data[0]; + * dst++ = TdataBuf.p->data[1]; + * dst++ = TdataBuf.p->data[2]; + * dst++ = TdataBuf.p->data[3]; + TdataBuf.i = TdataBuf.p->nextDatabuf; + } + keyInfo->clientOpPtr = scanP->scanApiOpPtr[scanOp]; - keyInfo->keyLen = tcConP->primKeyLen; + keyInfo->keyLen = keyLen; keyInfo->scanInfo_Node = KeyInfo20::setScanInfo(scanOp, scanP->scanNumber)+ (getOwnNodeId() << 16); - keyInfo->transId1 = tcConP->transid[0]; keyInfo->transId2 = tcConP->transid[1]; - - const BlockReference ref = scanP->scanApiBlockref; - const Uint32 keyLen = tcConP->primKeyLen; - if(refToNode(ref) == getOwnNodeId()){ + + Uint32 * src = signal->theData+25; + if(connectedToNode){ jam(); - EXECUTE_DIRECT(refToBlock(ref), GSN_KEYINFO20, signal, 5 + keyLen); + + if(nodeId != getOwnNodeId()){ + jam(); + + if(keyLen <= KeyInfo20::DataLength || !longable) { + while(keyLen > KeyInfo20::DataLength){ + jam(); + MEMCOPY_NO_WORDS(keyInfo->keyData, src, KeyInfo20::DataLength); + sendSignal(ref, GSN_KEYINFO20, signal, 25, JBB); + src += KeyInfo20::DataLength;; + keyLen -= KeyInfo20::DataLength; + } while(keyLen >= KeyInfo20::DataLength); + + MEMCOPY_NO_WORDS(keyInfo->keyData, src, keyLen); + sendSignal(ref, GSN_KEYINFO20, signal, + KeyInfo20::HeaderLength+keyLen, JBB); + return; + } + + LinearSectionPtr ptr[3]; + ptr[0].p = src; + ptr[0].sz = keyLen; + sendSignal(ref, GSN_KEYINFO20, signal, KeyInfo20::HeaderLength, + JBB, ptr, 1); + return; + } + + EXECUTE_DIRECT(refToBlock(ref), GSN_KEYINFO20, signal, 3 + keyLen); jamEntry(); return; - } - - bool connectedToNode = getNodeInfo(refToNode(ref)).m_connected; - - if (ERROR_INSERTED(5029)){ - // Use error insert to turn routing on - jam(); - connectedToNode = false; } - if (connectedToNode){ + /** + * If this node does not have a direct connection + * to the receiving node we want to send the signals + * routed via the node that controls this read + */ + Uint32 routeBlockref = tcConP->clientBlockref; + + if(keyLen < KeyInfo20::DataLength || !longable){ jam(); - Uint32 keyLenLeft = keyLen; - Uint32 keyDataIndex = 20; - for(; keyLenLeft > 20; keyLenLeft -= 20, keyDataIndex += 20){ - jam(); - sendSignal(ref, GSN_KEYINFO20, signal, 25, JBB); - for(Uint32 i = 0; i<20; i++) - keyInfo->keyData[i] = keyInfo->keyData[keyDataIndex + i]; - }//for - sendSignal(ref, GSN_KEYINFO20, signal, 5 + keyLenLeft, JBB); - } else { - /** - * If this node does not have a direct connection - * to the receiving node we want to send the signals - * routed via the control node - */ - jam(); - Uint32 keyLenLeft = keyLen; - Uint32 keyDataIndex = 19; - BlockReference routeBlockref = tcConP->clientBlockref; - for(; keyLenLeft > 19; keyLenLeft -= 19, keyDataIndex += 19){ - jam(); - // store final destination, but save original value - Uint32 saveOne = keyInfo->keyData[19]; - keyInfo->keyData[19] = ref; + while (keyLen > (KeyInfo20::DataLength - 1)) { + jam(); + MEMCOPY_NO_WORDS(keyInfo->keyData, src, KeyInfo20::DataLength - 1); + keyInfo->keyData[KeyInfo20::DataLength-1] = ref; sendSignal(routeBlockref, GSN_KEYINFO20_R, signal, 25, JBB); - keyInfo->keyData[19] = saveOne; - for(Uint32 i = 0; i<19; i++){ - keyInfo->keyData[i] = keyInfo->keyData[keyDataIndex + i]; - } - }//for - keyInfo->keyData[keyLenLeft] = ref; - sendSignal(routeBlockref, GSN_KEYINFO20_R, signal, 5 + keyLenLeft + 1, JBB); + src += KeyInfo20::DataLength - 1; + keyLen -= KeyInfo20::DataLength - 1; + } + + MEMCOPY_NO_WORDS(keyInfo->keyData, src, keyLen); + keyInfo->keyData[keyLen] = ref; + sendSignal(routeBlockref, GSN_KEYINFO20_R, signal, + KeyInfo20::HeaderLength+keyLen+1, JBB); + return; } -}//Dblqh::sendKeyinfo20() - + keyInfo->keyData[0] = ref; + LinearSectionPtr ptr[3]; + ptr[0].p = src; + ptr[0].sz = keyLen; + sendSignal(routeBlockref, GSN_KEYINFO20_R, signal, + KeyInfo20::HeaderLength+1, JBB, ptr, 1); + return; +} + /* ------------------------------------------------------------------------ * ------- SEND SCAN_FRAGCONF TO TC THAT CONTROLS THE SCAN ------- * @@ -8848,7 +8883,7 @@ void Dblqh::execTRANSID_AI(Signal* signal) ndbrequire(tcConnectptr.p->transactionState == TcConnectionrec::COPY_TUPKEY); Uint32 * src = &signal->theData[3]; while(length > 22){ - if (saveTupattrbuf(signal, &signal->theData[3], 22) == ZOK) { + if (saveTupattrbuf(signal, src, 22) == ZOK) { ; } else { jam(); diff --git a/ndb/src/kernel/blocks/dbtc/Dbtc.hpp b/ndb/src/kernel/blocks/dbtc/Dbtc.hpp index c87712e1887..61e7e42621c 100644 --- a/ndb/src/kernel/blocks/dbtc/Dbtc.hpp +++ b/ndb/src/kernel/blocks/dbtc/Dbtc.hpp @@ -992,12 +992,90 @@ public: }; typedef Ptr TableRecordPtr; + /** + * There is max 16 ScanFragRec's for + * each scan started in TC. Each ScanFragRec is used by + * a scan fragment "process" that scans one fragment at a time. + * It will receive max 16 tuples in each request + */ + struct ScanFragRec { + ScanFragRec(){} + /** + * ScanFragState + * WAIT_GET_PRIMCONF : Waiting for DIGETPRIMCONF when starting a new + * fragment scan + * LQH_ACTIVE : The scan process has sent a command to LQH and is + * waiting for the response + * LQH_ACTIVE_CLOSE : The scan process has sent close to LQH and is + * waiting for the response + * DELIVERED : The result have been delivered, this scan frag process + * are waiting for a SCAN_NEXTREQ to tell us to continue scanning + * RETURNING_FROM_DELIVERY : SCAN_NEXTREQ received and continuing scan + * soon + * QUEUED_FOR_DELIVERY : Result queued in TC and waiting for delivery + * to API + * COMPLETED : The fragment scan processes has completed and finally + * sent a SCAN_PROCCONF + */ + enum ScanFragState { + IDLE = 0, + WAIT_GET_PRIMCONF = 1, + LQH_ACTIVE = 2, + DELIVERED = 4, + QUEUED_FOR_DELIVERY = 6, + COMPLETED = 7 + }; + // Timer for checking timeout of this fragment scan + Uint32 scanFragTimer; + + // Id of the current scanned fragment + Uint32 scanFragId; + + // Blockreference of LQH + BlockReference lqhBlockref; + + // getNodeInfo.m_connectCount, set at seize used so that + // I don't accidently kill a starting node + Uint32 m_connectCount; + + // State of this fragment scan + ScanFragState scanFragState; + + // Id of the ScanRecord this fragment scan belongs to + Uint32 scanRec; + + // The maximum number of operations that can be scanned before + // returning to TC + Uint16 scanFragConcurrency; + + inline void startFragTimer(Uint32 timeVal){ + scanFragTimer = timeVal; + } + inline void stopFragTimer(void){ + scanFragTimer = 0; + } + + Uint32 m_ops; + Uint32 m_chksum; + Uint32 m_apiPtr; + Uint32 m_totalLen; + union { + Uint32 nextPool; + Uint32 nextList; + }; + Uint32 prevList; + }; + + typedef Ptr ScanFragRecPtr; + typedef LocalDLList ScanFragList; + /** * Each scan allocates one ScanRecord to store information * about the current scan * */ struct ScanRecord { + ScanRecord() {} /** NOTE! This is the old comment for ScanState. - MASV * STATE TRANSITIONS OF SCAN_STATE. SCAN_STATE IS THE STATE * VARIABLE OF THE RECEIVE AND DELIVERY PROCESS. @@ -1057,161 +1135,68 @@ public: WAIT_SCAN_TAB_INFO = 1, WAIT_AI = 2, WAIT_FRAGMENT_COUNT = 3, - SCAN_NEXT_ORDERED = 4, - QUEUED_DELIVERED = 5, - DELIVERED = 6, - CLOSING_SCAN = 7 + RUNNING = 4, + CLOSING_SCAN = 5 }; + // State of this scan ScanState scanState; - // References to ScanFragRecs - Uint32 scanFragrec[16]; - // Refrences to ScanOperationRecords - Uint32 scanOprec[16]; - // Number of ScanOperationRecords allocated - Uint32 noScanOprec; + + DLList::Head m_running_scan_frags; // Currently in LQH + union { Uint32 m_queued_count; Uint32 scanReceivedOperations; }; + DLList::Head m_queued_scan_frags; // In TC !sent to API + DLList::Head m_delivered_scan_frags;// Delivered to API + DLList::Head m_completed_scan_frags;// Completed + // Id of the next fragment to be scanned. Used by scan fragment // processes when they are ready for the next fragment Uint32 scanNextFragId; + // Total number of fragments in the table we are scanning Uint32 scanNoFrag; + // Index of next ScanRecords when in free list Uint32 nextScan; + // Length of expected attribute information Uint32 scanAiLength; + // Reference to ApiConnectRecord Uint32 scanApiRec; + // Reference to TcConnectRecord Uint32 scanTcrec; + // Number of scan frag processes that belong to this scan Uint32 scanParallel; - // The number of recieved operations so far - Uint32 scanReceivedOperations; + // Schema version used by this scan Uint32 scanSchemaVersion; + // Index of stored procedure belonging to this scan Uint32 scanStoredProcId; + // The index of table that is scanned Uint32 scanTableref; + // Number of operation records per scanned fragment Uint16 noOprecPerFrag; - // The number of SCAN_TABINFO to receive - Uint16 noScanTabInfo; - // The number of SCAN_TABINFO received so far - Uint16 scanTabInfoReceived; - // apiIsClosed indicates if it's ok to release all resources - // and send a response to the API - // If it's false resources should not be released wait for API - // to close the scan - bool apiIsClosed; - // The number of scan frag processes that have completed their task - Uint8 scanProcessesCompleted; - // This variable is ZFALSE as long as any scan process is still alive - // It is ZTRUE as soon as all scan processes have been stopped - Uint8 scanCompletedStatus; + // Shall the locks be held until the application have read the // records Uint8 scanLockHold; + // Shall the locks be read or write locks Uint8 scanLockMode; + // Skip locks by other transactions and read latest committed Uint8 readCommitted; + // Scan is on ordered index Uint8 rangeScan; }; typedef Ptr ScanRecordPtr; - /** - * Each scan has max 16 ScanOperationRecords - * they are used for storing data to be sent to the api - */ - struct ScanOperationRecord { - // Reference to the scan operation in api - Uint32 apiOpptr[16]; - // Index and length of all recieved operations - // They will be cached here until SCAN_TABCONF is sent to api - Uint32 scanOpLength[16]; - // Next ScanOperationRecord when in free list - Uint32 nextScanOp; - }; /* p2c: size = 132 bytes */ - - typedef Ptr ScanOperationRecordPtr; - - /** - * There is max 16 ScanFragRec's for - * each scan started in TC. Each ScanFragRec is used by - * a scan fragment "process" that scans one fragment at a time. - * It will receive max 16 tuples in each request - */ - struct ScanFragRec { - /** - * ScanFragState - * WAIT_GET_PRIMCONF : Waiting for DIGETPRIMCONF when starting a new - * fragment scan - * LQH_ACTIVE : The scan process has sent a command to LQH and is - * waiting for the response - * LQH_ACTIVE_CLOSE : The scan process has sent close to LQH and is - * waiting for the response - * DELIVERED : The result have been delivered, this scan frag process - * are waiting for a SCAN_NEXTREQ to tell us to continue scanning - * RETURNING_FROM_DELIVERY : SCAN_NEXTREQ received and continuing scan - * soon - * QUEUED_FOR_DELIVERY : Result queued in TC and waiting for delivery - * to API - * COMPLETED : The fragment scan processes has completed and finally - * sent a SCAN_PROCCONF - */ - enum ScanFragState { - IDLE = 0, - WAIT_GET_PRIMCONF = 1, - LQH_ACTIVE = 2, - LQH_ACTIVE_CLOSE = 3, - DELIVERED = 4, - RETURNING_FROM_DELIVERY = 5, - QUEUED_FOR_DELIVERY = 6, - COMPLETED = 7 - }; - // Timer for checking timeout of this fragment scan - Uint32 scanFragTimer; - // Id of the current scanned fragment - Uint32 scanFragId; - // Blockreference of LQH - BlockReference lqhBlockref; - // getNodeInfo.m_connectCount, set at seize used so that - // I don't accidently kill a starting node - Uint32 m_connectCount; - // State of this fragment scan - ScanFragState scanFragState; - // Id of the ScanRecord this fragment scan belongs to - Uint32 scanRec; - // Index of next ScanFragRec, when in list of - // free ScanFragRec's - Uint32 nextScanFrag; - // Process id of this scan process within the total scan - Uint32 scanFragProcId; - // Node where current fragment resides - NodeId scanFragNodeId; - // Index of where to store the result in ScanRecord - Uint16 scanIndividual; - // The maximum number of operations that can be scanned before - // returning to TC - Uint16 scanFragConcurrency; - // Current status of the fragment scan - // * 0 = NOT COMPLETED - // * 1 = COMPLETED - // * 2 = CLOSED - Uint8 scanFragCompletedStatus; - - inline void startFragTimer(Uint32 timeVal){ - scanFragTimer = timeVal; - } - inline void stopFragTimer(void){ - scanFragTimer = 0; - } - }; - - typedef Ptr ScanFragRecPtr; - /* **********************************************************************$ */ /* ******$ DATA BUFFER ******$ */ /* */ @@ -1369,6 +1354,7 @@ private: void execCREATE_TAB_REQ(Signal* signal); void execPREP_DROP_TAB_REQ(Signal* signal); void execDROP_TAB_REQ(Signal* signal); + void execWAIT_DROP_TAB_REF(Signal* signal); void execWAIT_DROP_TAB_CONF(Signal* signal); void checkWaitDropTabFailedLqh(Signal*, Uint32 nodeId, Uint32 tableId); void execALTER_TAB_REQ(Signal* signal); @@ -1428,23 +1414,17 @@ private: Uint32 buddyPtr, UintR transid1, UintR transid2); - void initScanOprec(Signal* signal); void initScanrec(Signal* signal, const UintR scanParallel, const UintR noOprecPerFrag); void initScanfragrec(Signal* signal); - void releaseScanrec(Signal* signal); - void releaseScanResources(Signal* signal); - void releaseScanFragrec(Signal* signal); - void releaseScanOprec(Signal* signal); + void releaseScanResources(ScanRecordPtr); void seizeScanrec(Signal* signal); - void seizeScanFragrec(Signal* signal); - void seizeScanOprec(Signal* signal); void sendScanFragReq(Signal* signal); void sendScanTabConf(Signal* signal); - void sendScanProcConf(Signal* signal); - void setScanReceived(Signal* signal, Uint32 noCompletedOps); - + void close_scan_req(Signal*, ScanRecordPtr); + void close_scan_req_send_conf(Signal*, ScanRecordPtr); + void checkGcp(Signal* signal); void commitGciHandling(Signal* signal, UintR Tgci); void copyApi(Signal* signal); @@ -1473,12 +1453,12 @@ private: void releaseApiCon(Signal* signal, UintR aApiConnectPtr); void releaseApiConCopy(Signal* signal); void releaseApiConnectFail(Signal* signal); - void releaseAttrinfo(Signal* signal); + void releaseAttrinfo(); void releaseGcp(Signal* signal); - void releaseKeys(Signal* signal); + void releaseKeys(); void releaseSimpleRead(Signal* signal); void releaseDirtyWrite(Signal* signal); - void releaseTcCon(Signal* signal); + void releaseTcCon(); void releaseTcConnectFail(Signal* signal); void releaseTransResources(Signal* signal); void saveAttrbuf(Signal* signal); @@ -1638,6 +1618,8 @@ private: void checkScanActiveInFailedLqh(Signal* signal, Uint32 scanPtrI, Uint32 failedNodeId); + void checkScanFragList(Signal*, Uint32 failedNodeId, ScanRecord * scanP, + LocalDLList::Head&); // Initialisation void initData(); @@ -1720,17 +1702,10 @@ private: ScanRecordPtr scanptr; UintR cscanrecFileSize; - ScanOperationRecord *scanOperationRecord; - ScanOperationRecordPtr scanOpptr; - UintR cscanOprecFileSize; - - ScanFragRec *scanFragmentRecord; + UnsafeArrayPool c_scan_frag_pool; ScanFragRecPtr scanFragptr; - UintR cscanFragrecFileSize; - UintR cfirstfreeScanOprec; - UintR cnoFreeScanOprec; - UintR cfirstfreeScanFragrec; + UintR cscanFragrecFileSize; UintR cdatabufFilesize; BlockReference cdictblockref; diff --git a/ndb/src/kernel/blocks/dbtc/DbtcInit.cpp b/ndb/src/kernel/blocks/dbtc/DbtcInit.cpp index 61ecca513f0..9ac1812492f 100644 --- a/ndb/src/kernel/blocks/dbtc/DbtcInit.cpp +++ b/ndb/src/kernel/blocks/dbtc/DbtcInit.cpp @@ -35,7 +35,6 @@ void Dbtc::initData() cgcpFilesize = ZGCP_FILESIZE; cscanrecFileSize = ZSCANREC_FILE_SIZE; cscanFragrecFileSize = ZSCAN_FRAGREC_FILE_SIZE; - cscanOprecFileSize = ZSCAN_OPREC_FILE_SIZE; ctabrecFilesize = ZTABREC_FILESIZE; ctcConnectFilesize = ZTC_CONNECT_FILESIZE; cdihblockref = DBDIH_REF; @@ -49,8 +48,6 @@ void Dbtc::initData() hostRecord = 0; tableRecord = 0; scanRecord = 0; - scanOperationRecord = 0; - scanFragmentRecord = 0; databufRecord = 0; attrbufRecord = 0; gcpRecord = 0; @@ -143,16 +140,19 @@ void Dbtc::initRecords() sizeof(ScanRecord), cscanrecFileSize); - scanOperationRecord = (ScanOperationRecord*) - allocRecord("ScanOperationRecord", - sizeof(ScanOperationRecord), - cscanOprecFileSize); - scanFragmentRecord = (ScanFragRec*) - allocRecord("ScanFragRec", - sizeof(ScanFragRec), - cscanFragrecFileSize); + c_scan_frag_pool.setSize(cscanFragrecFileSize); + { + ScanFragRecPtr ptr; + SLList tmp(c_scan_frag_pool); + while(tmp.seize(ptr)) { + new (ptr.p) ScanFragRec(); + } + tmp.release(); + } + indexOps.release(); + databufRecord = (DatabufRecord*)allocRecord("DatabufRecord", sizeof(DatabufRecord), cdatabufFilesize); @@ -213,10 +213,7 @@ Dbtc::Dbtc(const class Configuration & conf): addRecSignal(GSN_ATTRINFO, &Dbtc::execATTRINFO); addRecSignal(GSN_CONTINUEB, &Dbtc::execCONTINUEB); addRecSignal(GSN_KEYINFO, &Dbtc::execKEYINFO); - addRecSignal(GSN_SCAN_TABINFO, &Dbtc::execSCAN_TABINFO); addRecSignal(GSN_SCAN_NEXTREQ, &Dbtc::execSCAN_NEXTREQ); - addRecSignal(GSN_SCAN_PROCREQ, &Dbtc::execSCAN_PROCREQ); - addRecSignal(GSN_SCAN_PROCCONF, &Dbtc::execSCAN_PROCCONF); addRecSignal(GSN_TAKE_OVERTCREQ, &Dbtc::execTAKE_OVERTCREQ); addRecSignal(GSN_TAKE_OVERTCCONF, &Dbtc::execTAKE_OVERTCCONF); addRecSignal(GSN_LQHKEYREF, &Dbtc::execLQHKEYREF); @@ -290,6 +287,7 @@ Dbtc::Dbtc(const class Configuration & conf): //addRecSignal(GSN_CREATE_TAB_REQ, &Dbtc::execCREATE_TAB_REQ); addRecSignal(GSN_DROP_TAB_REQ, &Dbtc::execDROP_TAB_REQ); addRecSignal(GSN_PREP_DROP_TAB_REQ, &Dbtc::execPREP_DROP_TAB_REQ); + addRecSignal(GSN_WAIT_DROP_TAB_REF, &Dbtc::execWAIT_DROP_TAB_REF); addRecSignal(GSN_WAIT_DROP_TAB_CONF, &Dbtc::execWAIT_DROP_TAB_CONF); addRecSignal(GSN_ALTER_TAB_REQ, &Dbtc::execALTER_TAB_REQ); @@ -323,17 +321,7 @@ Dbtc::~Dbtc() deallocRecord((void **)&scanRecord, "ScanRecord", sizeof(ScanRecord), cscanrecFileSize); - - deallocRecord((void **)&scanOperationRecord, - "ScanOperationRecord", - sizeof(ScanOperationRecord), - cscanOprecFileSize); - - deallocRecord((void **)&scanFragmentRecord, - "ScanFragRec", - sizeof(ScanFragRec), - cscanFragrecFileSize); - + deallocRecord((void **)&databufRecord, "DatabufRecord", sizeof(DatabufRecord), cdatabufFilesize); diff --git a/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp b/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp index 1c916c2754c..edb51ea3c89 100644 --- a/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp +++ b/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp @@ -110,13 +110,7 @@ void Dbtc::execCONTINUEB(Signal* signal) switch (tcase) { case TcContinueB::ZRETURN_FROM_QUEUED_DELIVERY: jam(); - scanptr.i = Tdata0; - ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord); - scanFragptr.i = Tdata1; - ptrCheckGuard(scanFragptr, cscanFragrecFileSize, scanFragmentRecord); - ndbrequire(scanFragptr.p->scanFragState == - ScanFragRec::RETURNING_FROM_DELIVERY); - returnFromQueuedDeliveryLab(signal); + ndbrequire(false); return; case TcContinueB::ZCOMPLETE_TRANS_AT_TAKE_OVER: jam(); @@ -374,6 +368,39 @@ Dbtc::execWAIT_DROP_TAB_CONF(Signal* signal) } } +void +Dbtc::execWAIT_DROP_TAB_REF(Signal* signal) +{ + jamEntry(); + WaitDropTabRef * ref = (WaitDropTabRef*)signal->getDataPtr(); + + TableRecordPtr tabPtr; + tabPtr.i = ref->tableId; + ptrCheckGuard(tabPtr, ctabrecFilesize, tableRecord); + + ndbrequire(tabPtr.p->dropping == true); + Uint32 nodeId = refToNode(ref->senderRef); + tabPtr.p->dropTable.waitDropTabCount.clearWaitingFor(nodeId); + + ndbrequire(ref->errorCode == WaitDropTabRef::NoSuchTable || + ref->errorCode == WaitDropTabRef::NF_FakeErrorREF); + + if(!tabPtr.p->dropTable.waitDropTabCount.done()){ + jam(); + return; + } + + { + PrepDropTabConf* conf = (PrepDropTabConf*)signal->getDataPtrSend(); + conf->tableId = tabPtr.i; + conf->senderRef = reference(); + conf->senderData = tabPtr.p->dropTable.senderData; + sendSignal(tabPtr.p->dropTable.senderRef, GSN_PREP_DROP_TAB_CONF, signal, + PrepDropTabConf::SignalLength, JBB); + tabPtr.p->dropTable.senderRef = 0; + } +} + void Dbtc::checkWaitDropTabFailedLqh(Signal* signal, Uint32 nodeId, Uint32 tableId) { @@ -526,7 +553,6 @@ void Dbtc::execREAD_CONFIG_REQ(Signal* signal) ctcConnectFilesize = tcConnect; ctabrecFilesize = tables; cscanrecFileSize = tcScan; - cscanOprecFileSize = localScan; cscanFragrecFileSize = localScan; initRecords(); @@ -882,7 +908,15 @@ Dbtc::handleFailedApiNode(Signal* signal, // sending several signals we will increase the loop count by 64. /*********************************************************************/ jam(); - handleScanStop(signal, TapiFailedNode); + + apiConnectptr.p->apiFailState = ZTRUE; + capiConnectClosing[TapiFailedNode]++; + + ScanRecordPtr scanPtr; + scanPtr.i = apiConnectptr.p->apiScanRec; + ptrCheckGuard(scanPtr, cscanrecFileSize, scanRecord); + close_scan_req(signal, scanPtr); + TloopCount += 64; break; case CS_CONNECTED: @@ -1072,6 +1106,7 @@ void Dbtc::handleApiFailState(Signal* signal, UintR TapiConnectptr) */ void Dbtc::handleScanStop(Signal* signal, UintR TapiFailedNode) { +#if JONAS_NOT_DONE arrGuard(TapiFailedNode, MAX_NODES); scanptr.i = apiConnectptr.p->apiScanRec; @@ -1091,7 +1126,7 @@ void Dbtc::handleScanStop(Signal* signal, UintR TapiFailedNode) * We will release the resources and then release the connection * to the failed API. */ - releaseScanResources(signal); + releaseScanResources(scanptr); if (apiNodeHasFailed) { jam(); releaseApiCon(signal, apiConnectptr.i); @@ -1189,6 +1224,7 @@ void Dbtc::handleScanStop(Signal* signal, UintR TapiFailedNode) break; }//switch +#endif }//Dbtc::handleScanStop() /**************************************************************************** @@ -1341,6 +1377,7 @@ void Dbtc::sendSignalErrorRefuseLab(Signal* signal) ptrGuard(apiConnectptr); if (apiConnectptr.p->apiConnectstate != CS_DISCONNECTED) { jam(); + ndbrequire(false); signal->theData[0] = apiConnectptr.p->ndbapiConnect; signal->theData[1] = signal->theData[ttransid_ptr]; signal->theData[2] = signal->theData[ttransid_ptr + 1]; @@ -1424,6 +1461,7 @@ Dbtc::TCKEY_abort(Signal* signal, int place) signal->theData[1] = t1; signal->theData[2] = t2; signal->theData[3] = ZABORT_ERROR; + ndbrequire(false); sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_TCROLLBACKREP, signal, 4, JBB); return; @@ -1881,7 +1919,7 @@ void Dbtc::packKeyData000Lab(Signal* signal, /* THERE WERE UNSENT INFORMATION, SEND IT. */ /*---------------------------------------------------------------------*/ sendKeyinfo(signal, TBRef, tdataPos); - releaseKeys(signal); + releaseKeys(); return; }//if databufptr.i = databufptr.p->nextDatabuf; @@ -3238,7 +3276,7 @@ void Dbtc::packLqhkeyreq040Lab(Signal* signal, /*-------------------------------------------------------------------- * WE HAVE SENT ALL THE SIGNALS OF THIS OPERATION. SET STATE AND EXIT. *---------------------------------------------------------------------*/ - releaseAttrinfo(signal); + releaseAttrinfo(); if (Tboth) { jam(); releaseSimpleRead(signal); @@ -3264,7 +3302,7 @@ void Dbtc::packLqhkeyreq040Lab(Signal* signal, /* ========================================================================= */ /* ------- RELEASE ALL ATTRINFO RECORDS IN AN OPERATION RECORD ------- */ /* ========================================================================= */ -void Dbtc::releaseAttrinfo(Signal* signal) +void Dbtc::releaseAttrinfo() { UintR Tmp; AttrbufRecordPtr Tattrbufptr; @@ -3296,7 +3334,7 @@ void Dbtc::releaseAttrinfo(Signal* signal) regApiPtr->cachePtr = RNIL; return; }//if - systemErrorLab(signal); + systemErrorLab(0); return; }//Dbtc::releaseAttrinfo() @@ -3306,7 +3344,7 @@ void Dbtc::releaseAttrinfo(Signal* signal) void Dbtc::releaseSimpleRead(Signal* signal) { unlinkReadyTcCon(signal); - releaseTcCon(signal); + releaseTcCon(); /** * No LQHKEYCONF in Simple/Dirty read @@ -3370,7 +3408,7 @@ void Dbtc::unlinkReadyTcCon(Signal* signal) }//if }//Dbtc::unlinkReadyTcCon() -void Dbtc::releaseTcCon(Signal* signal) +void Dbtc::releaseTcCon() { TcConnectRecord * const regTcPtr = tcConnectptr.p; UintR TfirstfreeTcConnect = cfirstfreeTcConnect; @@ -4787,7 +4825,7 @@ void Dbtc::releaseTransResources(Signal* signal) tcConnectptr.i = localTcConnectptr.i; tcConnectptr.p = localTcConnectptr.p; localTcConnectptr.i = rtrTcConnectptrIndex; - releaseTcCon(signal); + releaseTcCon(); } while (localTcConnectptr.i != RNIL); handleGcp(signal); releaseFiredTriggerData(&apiConnectptr.p->theFiredTriggers); @@ -4841,7 +4879,7 @@ void Dbtc::releaseApiConCopy(Signal* signal) void Dbtc::releaseDirtyWrite(Signal* signal) { unlinkReadyTcCon(signal); - releaseTcCon(signal); + releaseTcCon(); ApiConnectRecord * const regApiPtr = apiConnectptr.p; if (regApiPtr->apiConnectstate == CS_START_COMMITTING) { if (regApiPtr->firstTcConnect == RNIL) { @@ -4942,7 +4980,7 @@ void Dbtc::execLQHKEYREF(Signal* signal) regApiPtr->lqhkeyconfrec++; unlinkReadyTcCon(signal); - releaseTcCon(signal); + releaseTcCon(); opPtr.p->triggerExecutionCount--; if (opPtr.p->triggerExecutionCount == 0) { @@ -4998,7 +5036,7 @@ void Dbtc::execLQHKEYREF(Signal* signal) Uint32 indexOp = tcConnectptr.p->indexOp; Uint32 clientData = regTcPtr->clientData; unlinkReadyTcCon(signal); /* LINK TC CONNECT RECORD OUT OF */ - releaseTcCon(signal); /* RELEASE THE TC CONNECT RECORD */ + releaseTcCon(); /* RELEASE THE TC CONNECT RECORD */ setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__); if (isIndexOp) { jam(); @@ -6388,7 +6426,7 @@ void Dbtc::timeOutLoopStartFragLab(Signal* signal, Uint32 TscanConPtr) UintR texpiredTime[8]; UintR TloopCount = 0; Uint32 TtcTimer = ctcTimer; - + while ((TscanConPtr + 8) < cscanFragrecFileSize) { jam(); timeOutPtr[0].i = TscanConPtr + 0; @@ -6400,14 +6438,14 @@ void Dbtc::timeOutLoopStartFragLab(Signal* signal, Uint32 TscanConPtr) timeOutPtr[6].i = TscanConPtr + 6; timeOutPtr[7].i = TscanConPtr + 7; - ptrAss(timeOutPtr[0], scanFragmentRecord); - ptrAss(timeOutPtr[1], scanFragmentRecord); - ptrAss(timeOutPtr[2], scanFragmentRecord); - ptrAss(timeOutPtr[3], scanFragmentRecord); - ptrAss(timeOutPtr[4], scanFragmentRecord); - ptrAss(timeOutPtr[5], scanFragmentRecord); - ptrAss(timeOutPtr[6], scanFragmentRecord); - ptrAss(timeOutPtr[7], scanFragmentRecord); + c_scan_frag_pool.getPtrForce(timeOutPtr[0]); + c_scan_frag_pool.getPtrForce(timeOutPtr[1]); + c_scan_frag_pool.getPtrForce(timeOutPtr[2]); + c_scan_frag_pool.getPtrForce(timeOutPtr[3]); + c_scan_frag_pool.getPtrForce(timeOutPtr[4]); + c_scan_frag_pool.getPtrForce(timeOutPtr[5]); + c_scan_frag_pool.getPtrForce(timeOutPtr[6]); + c_scan_frag_pool.getPtrForce(timeOutPtr[7]); tfragTimer[0] = timeOutPtr[0].p->scanFragTimer; tfragTimer[1] = timeOutPtr[1].p->scanFragTimer; @@ -6459,7 +6497,7 @@ void Dbtc::timeOutLoopStartFragLab(Signal* signal, Uint32 TscanConPtr) for ( ; TscanConPtr < cscanFragrecFileSize; TscanConPtr++){ jam(); timeOutPtr[0].i = TscanConPtr; - ptrAss(timeOutPtr[0], scanFragmentRecord); + c_scan_frag_pool.getPtrForce(timeOutPtr[0]); if (timeOutPtr[0].p->scanFragTimer != 0) { texpiredTime[0] = ctcTimer - timeOutPtr[0].p->scanFragTimer; if (texpiredTime[0] > ctimeOutValue) { @@ -6475,6 +6513,7 @@ void Dbtc::timeOutLoopStartFragLab(Signal* signal, Uint32 TscanConPtr) }//if }//for ctimeOutCheckFragActive = TOCS_FALSE; + return; }//timeOutLoopStartFragLab() @@ -6487,11 +6526,9 @@ void Dbtc::execSCAN_HBREP(Signal* signal) jamEntry(); scanFragptr.i = signal->theData[0]; - ptrCheckGuard(scanFragptr, cscanFragrecFileSize, scanFragmentRecord); - + c_scan_frag_pool.getPtr(scanFragptr); switch (scanFragptr.p->scanFragState){ case ScanFragRec::LQH_ACTIVE: - case ScanFragRec::LQH_ACTIVE_CLOSE: break; default: @@ -6541,7 +6578,7 @@ void Dbtc::execSCAN_HBREP(Signal* signal) void Dbtc::timeOutFoundFragLab(Signal* signal, UintR TscanConPtr) { scanFragptr.i = TscanConPtr; - ptrAss(scanFragptr, scanFragmentRecord); + c_scan_frag_pool.getPtr(scanFragptr); DEBUG("timeOutFoundFragLab: scanFragState = "<scanFragState); /*-------------------------------------------------------------------------*/ @@ -6563,39 +6600,11 @@ void Dbtc::timeOutFoundFragLab(Signal* signal, UintR TscanConPtr) */ scanFragError(signal, ZSCAN_FRAG_LQH_ERROR); DEBUG(" LQH_ACTIVE - closing the fragment scan in node " - <scanFragNodeId); + << refToNode(scanFragptr.p->lqhBlockref)); break; - case ScanFragRec::LQH_ACTIVE_CLOSE:{ - jam(); - /** - * The close of LQH expired its time-out. This is not - * acceptable behaviour from LQH and thus we will shoot - * it down. - */ - Uint32 nodeId = scanFragptr.p->scanFragNodeId; - Uint32 cc = scanFragptr.p->m_connectCount; - if(getNodeInfo(nodeId).m_connectCount == cc){ - const BlockReference errRef = calcNdbCntrBlockRef(nodeId); - SystemError * const sysErr = (SystemError*)&signal->theData[0]; - sysErr->errorCode = SystemError::ScanfragTimeout; - sysErr->errorRef = reference(); - sysErr->data1 = scanFragptr.i; - sysErr->data2 = scanFragptr.p->scanRec; - sendSignal(errRef, GSN_SYSTEM_ERROR, signal, - SystemError::SignalLength, JBA); - DEBUG(" node " << nodeId << " killed"); - } else { - DEBUG(" node " << nodeId << " not killed as it has restarted"); - } - scanFragptr.p->stopFragTimer(); - break; - } - case ScanFragRec::DELIVERED: jam(); - case ScanFragRec::RETURNING_FROM_DELIVERY: - jam(); case ScanFragRec::IDLE: jam(); case ScanFragRec::QUEUED_FOR_DELIVERY: @@ -6851,47 +6860,17 @@ void Dbtc::execNODE_FAILREP(Signal* signal) }//Dbtc::execNODE_FAILREP() void Dbtc::checkScanActiveInFailedLqh(Signal* signal, - Uint32 scanPtrI, - Uint32 failedNodeId){ + Uint32 scanPtrI, + Uint32 failedNodeId){ for (scanptr.i = scanPtrI; scanptr.i < cscanrecFileSize; scanptr.i++) { jam(); ptrAss(scanptr, scanRecord); if (scanptr.p->scanState != ScanRecord::IDLE){ - for (Uint32 i=0; i<16; i++) { - jam(); - scanFragptr.i = scanptr.p->scanFragrec[i]; - if (scanFragptr.i != RNIL) { - jam(); - ptrCheckGuard(scanFragptr, cscanFragrecFileSize, scanFragmentRecord); - if (scanFragptr.p->scanFragNodeId == failedNodeId){ - switch (scanFragptr.p->scanFragState){ - case ScanFragRec::LQH_ACTIVE: - case ScanFragRec::LQH_ACTIVE_CLOSE: - jam(); - apiConnectptr.i = scanptr.p->scanApiRec; - ptrCheckGuard(apiConnectptr, capiConnectFilesize, - apiConnectRecord); + checkScanFragList(signal, failedNodeId, + scanptr.p, scanptr.p->m_running_scan_frags); + } - // The connection to this LQH is closed - scanFragptr.p->lqhBlockref = RNIL; - - DEBUG("checkScanActiveInFailedLqh: scanFragError"); - scanFragError(signal, ZSCAN_LQH_ERROR); - - break; - - default: - /* empty */ - jam(); - break; - }// switch - - } //if - } //if - } //for - } //if - // Send CONTINUEB to continue later signal->theData[0] = TcContinueB::ZCHECK_SCAN_ACTIVE_FAILED_LQH; signal->theData[1] = scanptr.i + 1; // Check next scanptr @@ -6901,6 +6880,37 @@ void Dbtc::checkScanActiveInFailedLqh(Signal* signal, }//for } +void +Dbtc::checkScanFragList(Signal* signal, + Uint32 failedNodeId, + ScanRecord * scanP, + ScanFragList::Head & head){ + + ScanFragRecPtr ptr; + ScanFragList list(c_scan_frag_pool, head); + + for(list.first(ptr); !ptr.isNull(); list.next(ptr)){ + if (refToNode(ptr.p->lqhBlockref) == failedNodeId){ + switch (ptr.p->scanFragState){ + case ScanFragRec::LQH_ACTIVE: + jam(); + apiConnectptr.i = scanptr.p->scanApiRec; + ptrCheckGuard(apiConnectptr, capiConnectFilesize, + apiConnectRecord); + + DEBUG("checkScanActiveInFailedLqh: scanFragError"); + scanFragError(signal, ZSCAN_LQH_ERROR); + + break; + default: + /* empty */ + jam(); + break; + } + } + } +} + void Dbtc::execTAKE_OVERTCCONF(Signal* signal) { jamEntry(); @@ -8407,11 +8417,21 @@ void Dbtc::execSCAN_TABREQ(Signal* signal) const Uint32 buddyPtr = (tmpXX == 0xFFFFFFFF ? RNIL : tmpXX); Uint32 currSavePointId = 0; - Uint8 scanConcurrency = scanTabReq->getParallelism(reqinfo); - Uint32 scanParallel; - Uint32 noOprecPerFrag; + Uint32 scanConcurrency = scanTabReq->getParallelism(reqinfo); + Uint32 noOprecPerFrag = ScanTabReq::getScanBatch(reqinfo); + Uint32 scanParallel = scanConcurrency; Uint32 errCode; + if(noOprecPerFrag == 0){ + jam(); + scanParallel = (scanConcurrency + 15) / 16; + noOprecPerFrag = (scanConcurrency >= 16 ? 16 : scanConcurrency & 15); + } +#ifdef VM_TRACE + ndbout_c("noOprecPerFrag=%d", noOprecPerFrag); + ndbout_c("scanParallel=%d", scanParallel); +#endif + jamEntry(); apiConnectptr.i = scanTabReq->apiConnectPtr; tabptr.i = scanTabReq->tableId; @@ -8461,43 +8481,19 @@ void Dbtc::execSCAN_TABREQ(Signal* signal) errCode = ZNO_CONCURRENCY_ERROR; goto SCAN_TAB_error; }//if - if (scanConcurrency <= 16) { - jam(); - noOprecPerFrag = scanConcurrency; - } else { - if (scanConcurrency <= 240) { - jam(); - //If scanConcurrency > 16 it must be a multiple of 16 - if (((scanConcurrency >> 4) << 4) < scanConcurrency) { - scanConcurrency = ((scanConcurrency >> 4) << 4) + 16; - }//if - } else { - jam(); - errCode = ZTOO_HIGH_CONCURRENCY_ERROR; - goto SCAN_TAB_error; - }//if - noOprecPerFrag = 16; - }//if - - scanParallel = ((scanConcurrency - 1) >> 4) + 1; + /********************************************************** * CALCULATE THE NUMBER OF SCAN_TABINFO SIGNALS THAT WILL * ARRIVE TO DEFINE THIS SCAN. THIS ALSO DEFINES THE NUMBER * OF PARALLEL SCANS AND IT ALSO DEFINES THE NUMBER OF SCAN * OPERATION POINTER RECORDS TO ALLOCATE. **********************************************************/ - if (cnoFreeScanOprec < scanParallel) { - jam(); - errCode = ZNO_SCANREC_ERROR; - goto SCAN_TAB_error; - // WE DID NOT HAVE ENOUGH OF FREE SCAN OPERATION POINTER RECORDS. - // THUS WE REFUSE THE SCAN OPERATION. - }//if if (cfirstfreeTcConnect == RNIL) { jam(); errCode = ZNO_FREE_TC_CONNECTION; goto SCAN_TAB_error; }//if + if (cfirstfreeScanrec == RNIL) { jam(); errCode = ZNO_SCANREC_ERROR; @@ -8522,9 +8518,8 @@ void Dbtc::execSCAN_TABREQ(Signal* signal) seizeCacheRecord(signal); seizeScanrec(signal); initScanrec(signal, scanParallel, noOprecPerFrag); - initScanTcrec(signal); + tcConnectptr.p->apiConnect = apiConnectptr.i; initScanApirec(signal, buddyPtr, transid1, transid2); - cnoFreeScanOprec = cnoFreeScanOprec - scanParallel; // The scan is started apiConnectptr.p->apiConnectstate = CS_START_SCAN; @@ -8536,11 +8531,7 @@ void Dbtc::execSCAN_TABREQ(Signal* signal) ***********************************************************/ setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__); updateBuddyTimer(apiConnectptr); - if (scanptr.p->noScanTabInfo > 1) { - jam(); - scanptr.p->scanState = ScanRecord::WAIT_SCAN_TAB_INFO; - return; - }//if + /*********************************************************** * WE HAVE NOW RECEIVED ALL REFERENCES TO SCAN OBJECTS IN * THE API. WE ARE NOW READY TO RECEIVE THE ATTRIBUTE INFO @@ -8566,10 +8557,6 @@ void Dbtc::execSCAN_TABREQ(Signal* signal) return; }//Dbtc::execSCAN_TABREQ() -void Dbtc::initScanTcrec(Signal* signal) -{ - tcConnectptr.p->apiConnect = apiConnectptr.i; -}//Dbtc::initScanTcrec() void Dbtc::initScanApirec(Signal* signal, Uint32 buddyPtr, UintR transid1, UintR transid2) @@ -8583,16 +8570,6 @@ void Dbtc::initScanApirec(Signal* signal, }//Dbtc::initScanApirec() -void Dbtc::initScanOprec(Signal* signal) -{ - UintR tisoIndex; - - for (tisoIndex = 0; tisoIndex < 16; tisoIndex++) { - scanOpptr.p->apiOpptr[tisoIndex] = cdata[tisoIndex]; - scanOpptr.p->scanOpLength[tisoIndex] = RNIL; - }//for -}//Dbtc::initScanOprec() - void Dbtc::initScanrec(Signal* signal, UintR scanParallel, UintR noOprecPerFrag) @@ -8607,34 +8584,26 @@ void Dbtc::initScanrec(Signal* signal, scanptr.p->scanTableref = tabptr.i; scanptr.p->scanSchemaVersion = scanTabReq->tableSchemaVersion; scanptr.p->scanParallel = scanParallel; - scanptr.p->noScanOprec = scanParallel; - scanptr.p->noScanTabInfo = scanParallel; - scanptr.p->scanTabInfoReceived = 1; - scanptr.p->scanProcessesCompleted = 0; + scanptr.p->noOprecPerFrag = noOprecPerFrag; scanptr.p->scanLockMode = ScanTabReq::getLockMode(reqinfo); scanptr.p->scanLockHold = ScanTabReq::getHoldLockFlag(reqinfo); scanptr.p->readCommitted = ScanTabReq::getReadCommittedFlag(reqinfo); scanptr.p->rangeScan = ScanTabReq::getRangeScanFlag(reqinfo); scanptr.p->scanStoredProcId = scanTabReq->storedProcId; - scanptr.p->scanReceivedOperations = 0; - scanptr.p->noOprecPerFrag = noOprecPerFrag; - scanptr.p->apiIsClosed = false; - scanptr.p->scanCompletedStatus = ZFALSE; - scanptr.p->scanState = ScanRecord::SCAN_NEXT_ORDERED; - for (Uint32 i = 0; i < 16; i++) { - if (i < scanParallel){ - jam(); - seizeScanOprec(signal); - scanptr.p->scanOprec[i] = scanOpptr.i; - } else { - jam(); - scanptr.p->scanOprec[i] = RNIL; - } - scanptr.p->scanFragrec[i] = RNIL; + scanptr.p->scanState = ScanRecord::RUNNING; + scanptr.p->m_queued_count = 0; + + ScanFragList list(c_scan_frag_pool, + scanptr.p->m_running_scan_frags); + for (Uint32 i = 0; i < scanParallel; i++) { + jam(); + ScanFragRecPtr ptr; + ndbrequire(list.seize(ptr)); + ptr.p->scanRec = scanptr.i; + ptr.p->scanFragId = 0; + ptr.p->scanFragConcurrency = noOprecPerFrag; + ptr.p->m_apiPtr = cdata[i]; }//for - scanOpptr.i = scanptr.p->scanOprec[0]; - ptrCheckGuard(scanOpptr, cscanOprecFileSize, scanOperationRecord); - initScanOprec(signal); }//Dbtc::initScanrec() void Dbtc::scanTabRefLab(Signal* signal, Uint32 errCode) @@ -8648,58 +8617,6 @@ void Dbtc::scanTabRefLab(Signal* signal, Uint32 errCode) signal, ScanTabRef::SignalLength, JBB); }//Dbtc::scanTabRefLab() -/****************************************************** - * execSCAN_TABINFO - ******************************************************/ -void Dbtc::execSCAN_TABINFO(Signal* signal) -{ - jamEntry(); - apiConnectptr.i = signal->theData[0]; - for(int i=0; i<16; i++) - cdata[i] = signal->theData[i+1]; - - if (apiConnectptr.i >= capiConnectFilesize) { - jam(); - warningHandlerLab(signal); - return; - }//if - ptrAss(apiConnectptr, apiConnectRecord); - - if (apiConnectptr.p->apiConnectstate != CS_START_SCAN){ - jam(); - DEBUG("apiPtr(" << apiConnectptr.i << ") Dropping SCAN_TABINFO, wrong state: " << apiConnectptr.p->apiConnectstate); - return; - } - - scanptr.i = apiConnectptr.p->apiScanRec; - ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord); - - const Uint32 tscanOprec = scanptr.p->scanTabInfoReceived; - scanptr.p->scanTabInfoReceived++; - arrGuard(tscanOprec, 16); - scanOpptr.i = scanptr.p->scanOprec[tscanOprec]; - ptrCheckGuard(scanOpptr, cscanOprecFileSize, scanOperationRecord); - // Start timer and wait for response from API node. - setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__); - updateBuddyTimer(apiConnectptr); - - initScanOprec(signal); - // Start timer and wait for response from API node. - setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__); - updateBuddyTimer(apiConnectptr); - - if (scanptr.p->scanTabInfoReceived == scanptr.p->noScanTabInfo) { - jam(); - /****************************************************************** - * WE HAVE NOW RECEIVED ALL REFERENCES TO SCAN OBJECTS IN THE API. - * WE ARE NOW READY TO RECEIVE THE ATTRIBUTE INFO IF ANY TO RECEIVE. - ******************************************************************/ - scanptr.p->scanState = ScanRecord::WAIT_AI; - return; - } - ndbrequire(scanptr.p->scanTabInfoReceived <= scanptr.p->noScanTabInfo); -}//Dbtc::execSCAN_TABINFO() - /*---------------------------------------------------------------------------*/ /* */ /* RECEPTION OF ATTRINFO FOR SCAN TABLE REQUEST. */ @@ -8805,7 +8722,7 @@ void Dbtc::execDI_FCOUNTCONF(Signal* signal) ndbrequire(scanptr.p->scanState == ScanRecord::WAIT_FRAGMENT_COUNT); if (apiConnectptr.p->apiFailState == ZTRUE) { jam(); - releaseScanResources(signal); + releaseScanResources(scanptr); handleApiFailState(signal, apiConnectptr.i); return; }//if @@ -8828,31 +8745,40 @@ void Dbtc::execDI_FCOUNTCONF(Signal* signal) return; } - if (tfragCount < scanptr.p->scanParallel) { + if(scanptr.p->scanParallel > tfragCount){ jam(); - for (Uint32 i = tfragCount; i < scanptr.p->scanParallel; i++) { - jam(); - arrGuard(i, 16); - scanOpptr.i = scanptr.p->scanOprec[i]; - ptrCheckGuard(scanOpptr, cscanOprecFileSize, scanOperationRecord); - releaseScanOprec(signal); - scanptr.p->scanOprec[i] = RNIL; - }//for - scanptr.p->scanParallel = tfragCount; - }//if + abortScanLab(signal, ZTOO_HIGH_CONCURRENCY_ERROR); + return; + } + + scanptr.p->scanParallel = tfragCount; scanptr.p->scanNoFrag = tfragCount; - for (UintR i = 0; i < scanptr.p->scanParallel; i++) { - jam(); - // START EACH OF THE PARALLEL SCAN PROCESSES - signal->theData[0] = scanptr.i; - signal->theData[1] = i; - signal->theData[2] = scanptr.p->noOprecPerFrag; - sendSignal(cownref, GSN_SCAN_PROCREQ, signal, 3, JBB); - }//for - // We don't need the timer for checking API anymore, control goes to LQH. + scanptr.p->scanNextFragId = 0; setApiConTimer(apiConnectptr.i, 0, __LINE__); - scanptr.p->scanNextFragId = scanptr.p->scanParallel; - scanptr.p->scanState = ScanRecord::SCAN_NEXT_ORDERED; + updateBuddyTimer(apiConnectptr); + + ScanFragRecPtr ptr; + ScanFragList list(c_scan_frag_pool, + scanptr.p->m_running_scan_frags); + for (list.first(ptr); !ptr.isNull(); list.next(ptr)){ + jam(); + +#ifdef VM_TRACE + ndbout_c("DIGETPRIMREQ(%d, %d)", + scanptr.p->scanTableref, scanptr.p->scanNextFragId); +#endif + + ptr.p->startFragTimer(ctcTimer); + ptr.p->scanFragId = scanptr.p->scanNextFragId++; + ptr.p->scanFragState = ScanFragRec::WAIT_GET_PRIMCONF; + ptr.p->startFragTimer(ctcTimer); + + signal->theData[0] = tcConnectptr.p->dihConnectptr; + signal->theData[1] = ptr.i; + signal->theData[2] = scanptr.p->scanTableref; + signal->theData[3] = ptr.p->scanFragId; + sendSignal(cdihblockref, GSN_DIGETPRIMREQ, signal, 4, JBB); + }//for }//Dbtc::execDI_FCOUNTCONF() /****************************************************** @@ -8871,7 +8797,7 @@ void Dbtc::execDI_FCOUNTREF(Signal* signal) ndbrequire(scanptr.p->scanState == ScanRecord::WAIT_FRAGMENT_COUNT); if (apiConnectptr.p->apiFailState == ZTRUE) { jam(); - releaseScanResources(signal); + releaseScanResources(scanptr); handleApiFailState(signal, apiConnectptr.i); return; }//if @@ -8880,126 +8806,43 @@ void Dbtc::execDI_FCOUNTREF(Signal* signal) void Dbtc::abortScanLab(Signal* signal, Uint32 errCode) { - releaseScanResources(signal); scanTabRefLab(signal, errCode); + releaseScanResources(scanptr); }//Dbtc::abortScanLab() -void Dbtc::scanReleaseResourcesLab(Signal* signal) -{ - apiConnectptr.i = scanptr.p->scanApiRec; - ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord); - if (apiConnectptr.p->returncode != 0) { - jam(); - ScanTabRef * ref = (ScanTabRef*)&signal->theData[0]; - ref->apiConnectPtr = apiConnectptr.p->ndbapiConnect; - ref->transId1 = apiConnectptr.p->transid[0]; - ref->transId2 = apiConnectptr.p->transid[1]; - ref->errorCode = apiConnectptr.p->returncode; - sendSignal(apiConnectptr.p->ndbapiBlockref, - GSN_SCAN_TABREF, signal, ScanTabRef::SignalLength, JBB); - } else { - jam(); - sendScanTabConf(signal); - }//if - releaseScanResources(signal); - if (apiConnectptr.p->apiFailState == ZTRUE) { - jam(); - handleApiFailState(signal, apiConnectptr.i); - return; - }//if -}//Dbtc::scanReleaseResourcesLab() - -void Dbtc::releaseScanResources(Signal* signal) +void Dbtc::releaseScanResources(ScanRecordPtr scanPtr) { +#ifdef VM_TRACE + ndbout_c("releaseScanResources: %d", scanPtr.i); +#endif if (apiConnectptr.p->cachePtr != RNIL) { cachePtr.i = apiConnectptr.p->cachePtr; ptrCheckGuard(cachePtr, ccacheFilesize, cacheRecord); - releaseAttrinfo(signal); + releaseAttrinfo(); }//if - cnoFreeScanOprec = cnoFreeScanOprec + scanptr.p->noScanOprec; - scanptr.p->scanCompletedStatus = ZCLOSED; - tcConnectptr.i = scanptr.p->scanTcrec; + tcConnectptr.i = scanPtr.p->scanTcrec; ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord); - releaseTcCon(signal); - for (Uint32 i = 0; i < 16; i++) { - jam(); - scanFragptr.i = scanptr.p->scanFragrec[i]; - scanptr.p->scanFragrec[i] = RNIL; - if (scanFragptr.i != RNIL) { - jam(); - ptrCheckGuard(scanFragptr, cscanFragrecFileSize, scanFragmentRecord); - releaseScanFragrec(signal); - }//if - scanOpptr.i = scanptr.p->scanOprec[i]; - scanptr.p->scanOprec[i] = RNIL; - if (scanOpptr.i != RNIL) { - jam(); - ptrCheckGuard(scanOpptr, cscanOprecFileSize, scanOperationRecord); - releaseScanOprec(signal); - }//if - }//for - releaseScanrec(signal); + releaseTcCon(); + + ScanFragList x(c_scan_frag_pool, + scanPtr.p->m_completed_scan_frags); + x.release(); + ndbrequire(scanPtr.p->m_running_scan_frags.isEmpty()); + ndbrequire(scanPtr.p->m_queued_scan_frags.isEmpty()); + ndbrequire(scanPtr.p->m_delivered_scan_frags.isEmpty()); + + // link into free list + scanPtr.p->nextScan = cfirstfreeScanrec; + scanPtr.p->scanState = ScanRecord::IDLE; + scanPtr.p->scanTcrec = RNIL; + cfirstfreeScanrec = scanPtr.i; + apiConnectptr.p->apiScanRec = RNIL; apiConnectptr.p->apiConnectstate = CS_CONNECTED; setApiConTimer(apiConnectptr.i, 0, __LINE__); }//Dbtc::releaseScanResources() -/****************************************************** - * execSCAN_PROCREQ - ******************************************************/ -void Dbtc::execSCAN_PROCREQ(Signal* signal) -{ - jamEntry(); - scanptr.i = signal->theData[0]; - ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord); - - const UintR tscanFragId = signal->theData[1]; - ndbrequire(tscanFragId < 16); - const UintR tscanNoOprec = signal->theData[2]; - - ndbrequire(cfirstfreeScanFragrec != RNIL); - seizeScanFragrec(signal); - - apiConnectptr.i = scanptr.p->scanApiRec; - ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord); - setApiConTimer(apiConnectptr.i, 0, __LINE__); - - scanptr.p->scanFragrec[tscanFragId] = scanFragptr.i; - scanFragptr.p->scanRec = scanptr.i; - scanFragptr.p->scanIndividual = tscanFragId * tscanNoOprec; - scanFragptr.p->scanFragProcId = tscanFragId; - scanFragptr.p->scanFragId = tscanFragId; - scanFragptr.p->scanFragConcurrency = tscanNoOprec; - scanFragptr.p->scanFragCompletedStatus = ZFALSE; - tcConnectptr.i = scanptr.p->scanTcrec; - ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord); - - { - /** - * Check table - */ - TableRecordPtr tabPtr; - tabPtr.i = scanptr.p->scanTableref; - ptrAss(tabPtr, tableRecord); - Uint32 schemaVersion = scanptr.p->scanSchemaVersion; - if(tabPtr.p->checkTable(schemaVersion) == false){ - jam(); - scanFragError(signal, tabPtr.p->getErrorCode(schemaVersion)); - return; - } - } - - signal->theData[0] = tcConnectptr.p->dihConnectptr; - signal->theData[1] = scanFragptr.i; - signal->theData[2] = scanptr.p->scanTableref; - signal->theData[3] = tscanFragId; - sendSignal(cdihblockref, GSN_DIGETPRIMREQ, signal, 4, JBB); - scanFragptr.p->scanFragState = ScanFragRec::WAIT_GET_PRIMCONF; - updateBuddyTimer(apiConnectptr); - scanFragptr.p->startFragTimer(ctcTimer); -}//Dbtc::execSCAN_PROCREQ() - /**************************************************************** * execDIGETPRIMCONF * @@ -9012,14 +8855,13 @@ void Dbtc::execDIGETPRIMCONF(Signal* signal) jamEntry(); // tcConnectptr.i in theData[0] is not used scanFragptr.i = signal->theData[1]; - ptrCheckGuard(scanFragptr, cscanFragrecFileSize, scanFragmentRecord); + c_scan_frag_pool.getPtr(scanFragptr); tnodeid = signal->theData[2]; arrGuard(tnodeid, MAX_NDB_NODES); ndbrequire(scanFragptr.p->scanFragState == ScanFragRec::WAIT_GET_PRIMCONF); scanFragptr.p->stopFragTimer(); - scanFragptr.p->lqhBlockref = RNIL; scanptr.i = scanFragptr.p->scanRec; ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord); @@ -9049,16 +8891,22 @@ void Dbtc::execDIGETPRIMCONF(Signal* signal) case ScanRecord::CLOSING_SCAN: jam(); updateBuddyTimer(apiConnectptr); - scanFragptr.p->startFragTimer(ctcTimer); - sendScanProcConf(signal); + { + ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags); + ScanFragList comp(c_scan_frag_pool, scanptr.p->m_completed_scan_frags); + + run.remove(scanFragptr); + comp.add(scanFragptr); + } + close_scan_req_send_conf(signal, scanptr); return; default: jam(); /*empty*/; break; }//switch - scanFragptr.p->scanFragNodeId = tnodeid; - scanFragptr.p->lqhBlockref = calcLqhBlockRef(tnodeid); + Uint32 ref = calcLqhBlockRef(tnodeid); + scanFragptr.p->lqhBlockref = ref; scanFragptr.p->m_connectCount = getNodeInfo(tnodeid).m_connectCount; sendScanFragReq(signal); attrbufptr.i = cachePtr.p->firstAttrbuf; @@ -9068,12 +8916,12 @@ void Dbtc::execDIGETPRIMCONF(Signal* signal) sendAttrinfo(signal, scanFragptr.i, attrbufptr.p, - scanFragptr.p->lqhBlockref); + ref); attrbufptr.i = attrbufptr.p->attrbuf[ZINBUF_NEXT]; }//while scanFragptr.p->scanFragState = ScanFragRec::LQH_ACTIVE; - updateBuddyTimer(apiConnectptr); scanFragptr.p->startFragTimer(ctcTimer); + updateBuddyTimer(apiConnectptr); /********************************************* * WE HAVE NOW STARTED A FRAGMENT SCAN. NOW * WAIT FOR THE FIRST SCANNED RECORDS @@ -9093,7 +8941,7 @@ void Dbtc::execDIGETPRIMREF(Signal* signal) // tcConnectptr.i in theData[0] is not used. scanFragptr.i = signal->theData[1]; const Uint32 errCode = signal->theData[2]; - ptrCheckGuard(scanFragptr, cscanFragrecFileSize, scanFragmentRecord); + c_scan_frag_pool.getPtr(scanFragptr); ndbrequire(scanFragptr.p->scanFragState == ScanFragRec::WAIT_GET_PRIMCONF); scanFragError(signal, errCode); }//Dbtc::execDIGETPRIMREF() @@ -9112,7 +8960,7 @@ void Dbtc::execSCAN_FRAGREF(Signal* signal) const Uint32 errCode = ref->errorCode; scanFragptr.i = ref->senderData; - ptrCheckGuard(scanFragptr, cscanFragrecFileSize, scanFragmentRecord); + c_scan_frag_pool.getPtr(scanFragptr); scanptr.i = scanFragptr.p->scanRec; ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord); @@ -9133,7 +8981,6 @@ void Dbtc::execSCAN_FRAGREF(Signal* signal) * stop fragment timer and call scanFragError to start * close of the other fragment scans */ - scanFragptr.p->lqhBlockref = RNIL; scanFragError(signal, errCode); }//Dbtc::execSCAN_FRAGREF() @@ -9154,33 +9001,20 @@ void Dbtc::scanFragError(Signal* signal, Uint32 errorCode) << ", scanState = " << scanptr.p->scanState); scanFragptr.p->stopFragTimer(); +#if JONAS_NOT_DONE apiConnectptr.i = scanptr.p->scanApiRec; ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord); - if (scanFragptr.p->lqhBlockref == RNIL){ - // Since the lqh is closed, this scan process should be reported - // as completed immediately - jam(); - updateBuddyTimer(apiConnectptr); - scanFragptr.p->startFragTimer(ctcTimer); - sendScanProcConf(signal); - }//if // If close of the scan is not already started if (scanptr.p->scanState != ScanRecord::CLOSING_SCAN) { jam(); apiConnectptr.p->returncode = errorCode; - /** - * Only set apiIsClosed if API is waiting for an answer - */ - if (scanptr.p->scanState == ScanRecord::SCAN_NEXT_ORDERED){ - jam(); - scanptr.p->apiIsClosed = true; - } scanCompletedLab(signal); return; }//if +#endif }//Dbtc::scanFragError() @@ -9197,14 +9031,12 @@ void Dbtc::execSCAN_FRAGCONF(Signal* signal) const ScanFragConf * const conf = (ScanFragConf*)&signal->theData[0]; const Uint32 noCompletedOps = conf->completedOps; - for(Uint32 i = 0; iopReturnDataLen[i]; scanFragptr.i = conf->senderData; - ptrCheckGuard(scanFragptr, cscanFragrecFileSize, scanFragmentRecord); - + c_scan_frag_pool.getPtr(scanFragptr); + scanptr.i = scanFragptr.p->scanRec; ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord); - + apiConnectptr.i = scanptr.p->scanApiRec; ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord); @@ -9215,143 +9047,21 @@ void Dbtc::execSCAN_FRAGCONF(Signal* signal) jam(); systemErrorLab(signal); }//if - - scanFragptr.p->scanFragCompletedStatus = conf->fragmentCompleted; + + ndbrequire(scanFragptr.p->scanFragState == ScanFragRec::LQH_ACTIVE); + + const Uint32 status = conf->fragmentCompleted; scanFragptr.p->stopFragTimer(); - switch (scanFragptr.p->scanFragCompletedStatus) { - case ZFALSE: - case ZTRUE: - jam(); - /* empty */ - break; + if(scanptr.p->scanState == ScanRecord::CLOSING_SCAN){ + if(status == ZFALSE){ + /** + * Dont deliver to api, but instead close in LQH + * Dont need to mess with queues + */ + ndbout_c("running -> running(close)"); - case ZCLOSED: - /* The scan has finished this fragment. */ - jam(); - returnFromQueuedDeliveryLab(signal); - return; - break; - - default: - jam(); - systemErrorLab(signal); - break; - }//switch - - // CHECK THE STATE OF THE DELIVERY PROCESS TO THE APPLICATION. - switch (scanptr.p->scanState) { - case ScanRecord::SCAN_NEXT_ORDERED: - jam(); - /** - * THE APPLICATION HAVE ISSUED A SCAN_NEXTREQ AND IS WAITING - * FOR MORE OPERATIONS. SEND OPERATIONS DIRECTLY - */ - if (noCompletedOps > 0) { jam(); - setScanReceived(signal, noCompletedOps); - sendScanTabConf(signal); - scanptr.p->scanState = ScanRecord::DELIVERED; - scanFragptr.p->scanFragState = ScanFragRec::DELIVERED; - return; - }//if - break; - - case ScanRecord::DELIVERED: - case ScanRecord::QUEUED_DELIVERED: - jam(); - /** - * THE APPLICATION HAVE ALREADY RECEIVED A DELIVERY. - * QUEUE THE RECEIVED SCAN OPERATIONS AND ISSUE THEM - * WHEN THE APPLICATION ASKS FOR MORE. - */ - if (noCompletedOps > 0) { - jam(); - setScanReceived(signal, noCompletedOps); - scanptr.p->scanState = ScanRecord::QUEUED_DELIVERED; - scanFragptr.p->scanFragState = ScanFragRec::QUEUED_FOR_DELIVERY; - return; - }//if - break; - - case ScanRecord::CLOSING_SCAN: - jam(); - /************************************************* - * WE ARE CURRENTLY CLOSING THE SCAN. - * - * WE HAVE ALREADY ORDERED THE FRAGMENT TO CLOSE ITS - * SCAN. THIS SIGNAL MUST HAVE BEEN SENT BEFORE THIS - * CLOSE SIGNAL ARRIVED. SIMPLY IGNORE THIS SIGNAL. - **************************************************/ - return; - break; - - default: - jam(); - systemErrorLab(signal); - break; - - }//switch - - /** - * THERE WAS NO TUPLES LEFT TO REPORT IN THIS FRAGMENT. CLOSE SCAN - * HAVE NOT BEEN ORDERED. WE CAN CONTINUE THE SCAN PROCESS IMMEDIATELY. - * THE COMPLETED STATUS MUST BE TRUE SINCE IT IS NOT CLOSED. IF IT WAS - * FALSE IT MUST HAVE BEEN MORE TUPLES TO SCAN AND AT LEAST ONE OF - * THOSE SHOULD HAVE BEEN REPORTED. - */ - if (scanFragptr.p->scanFragCompletedStatus == ZFALSE) { - jam(); - /** - * THE SENDING NODE IS OUT OF ORDER WE WILL KILL IT BY SENDING SYSTEM - * ERROR TO IT - */ - const BlockReference errRef = - calcNdbCntrBlockRef(scanFragptr.p->scanFragNodeId); - SystemError * const sysErr = (SystemError*)&signal->theData[0]; - sysErr->errorCode = SystemError::ScanfragStateError; - sysErr->errorRef = reference(); - sendSignal(errRef, GSN_SYSTEM_ERROR, signal, - SystemError::SignalLength, JBA); - return; - }//if - returnFromQueuedDeliveryLab(signal); -}//Dbtc::execSCAN_FRAGCONF() - -void Dbtc::returnFromQueuedDeliveryLab(Signal* signal) -{ - apiConnectptr.i = scanptr.p->scanApiRec; - ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord); - - switch(scanFragptr.p->scanFragCompletedStatus) { - case ZFALSE: - { - /********************************************************************* - * WE HAVE SENT THE SCANNED OPERATION TO THE APPLICATION AND WE HAVE - * RECEIVED THE ORDER TO CONTINUE SCANNING. THE CURRENT FRAGMENT STILL - * CONTAINS MORE TUPLES TO SCAN. - *********************************************************************/ - jam(); - scanFragptr.p->scanFragState = ScanFragRec::LQH_ACTIVE; - ScanFragNextReq * nextReq = (ScanFragNextReq*)&signal->theData[0]; - nextReq->senderData = scanFragptr.i; - nextReq->closeFlag = ZFALSE; - nextReq->transId1 = apiConnectptr.p->transid[0]; - nextReq->transId2 = apiConnectptr.p->transid[1]; - sendSignal(scanFragptr.p->lqhBlockref, GSN_SCAN_NEXTREQ, signal, - ScanFragNextReq::SignalLength, JBB); - } - break; - - case ZTRUE: - { - /********************************************************************* - * WE HAVE SENT THE SCANNED OPERATION TO THE APPLICATION AND WE HAVE - * RECEIVED THE ORDER TO CONTINUE SCANNING. THE CURRENT FRAGMENT HAVE - * BEEN COMPLETELY SCANNED AND WE ARE READY TO CLOSE IT. - *********************************************************************/ - jam(); - scanFragptr.p->scanFragState = ScanFragRec::LQH_ACTIVE_CLOSE; ScanFragNextReq * nextReq = (ScanFragNextReq*)&signal->theData[0]; nextReq->senderData = scanFragptr.i; nextReq->closeFlag = ZTRUE; @@ -9359,126 +9069,66 @@ void Dbtc::returnFromQueuedDeliveryLab(Signal* signal) nextReq->transId2 = apiConnectptr.p->transid[1]; sendSignal(scanFragptr.p->lqhBlockref, GSN_SCAN_NEXTREQ, signal, ScanFragNextReq::SignalLength, JBB); - } - break; - - case ZCLOSED: - { - /******************************************************************** - * THE SCANNED FRAGMENT HAVE BEEN CLOSED. IF CLOSE SCAN HAVE BEEN - * ORDERED THEN WE CAN REPORT THAT THIS SCAN PROCESS IS COMPLETED. - * ALSO IF THERE ARE NO MORE FRAGMENTS TO SCAN WE CAN REPORT THAT - * THE SCAN PROCESS IS COMPLETED. - ********************************************************************/ - jam(); - scanFragptr.p->lqhBlockref = RNIL; - if ((scanptr.p->scanState != ScanRecord::CLOSING_SCAN) && - (scanptr.p->scanNextFragId < scanptr.p->scanNoFrag)){ - jam(); - scanFragptr.p->scanFragState = ScanFragRec::WAIT_GET_PRIMCONF; - tcConnectptr.i = scanptr.p->scanTcrec; - ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord); - scanFragptr.p->scanFragId = scanptr.p->scanNextFragId; - scanptr.p->scanNextFragId++; - signal->theData[0] = tcConnectptr.p->dihConnectptr; - signal->theData[1] = scanFragptr.i; - signal->theData[2] = scanptr.p->scanTableref; - signal->theData[3] = scanFragptr.p->scanFragId; - sendSignal(cdihblockref, GSN_DIGETPRIMREQ, signal, 4, JBB); - } else { - jam(); - sendScanProcConf(signal); - }//if - } - break; - - default: - jam(); - systemErrorLab(signal); - break; - }//switch - - updateBuddyTimer(apiConnectptr); - scanFragptr.p->startFragTimer(ctcTimer); -}//Dbtc::returnFromQueuedDeliveryLab() - -/********************************************************** - * execSCAN_PROCCONF - **********************************************************/ -void Dbtc::execSCAN_PROCCONF(Signal* signal) -{ - jamEntry(); - - scanptr.i = signal->theData[0]; - ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord); - scanptr.p->scanProcessesCompleted++; - ndbassert(scanptr.p->scanProcessesCompleted <= scanptr.p->scanParallel); - - scanFragptr.i = signal->theData[1]; - ptrCheckGuard(scanFragptr, cscanFragrecFileSize, scanFragmentRecord); - scanFragptr.p->stopFragTimer(); - scanFragptr.p->scanFragState = ScanFragRec::COMPLETED; - - if (scanptr.p->scanProcessesCompleted == scanptr.p->scanParallel) { - jam(); - - // Check that all scan processes are in state COMPLETED - for (Uint32 i = 0; i < 16; i++) { - scanFragptr.i = scanptr.p->scanFragrec[i]; - if (scanFragptr.i != RNIL) { - ptrCheckGuard(scanFragptr, cscanFragrecFileSize, scanFragmentRecord); - ndbrequire(scanFragptr.p->scanFragState == ScanFragRec::COMPLETED); - } - } - - // ALL SCAN PROCESSES HAS COMPLETED - scanptr.p->scanCompletedStatus = ZTRUE; - switch (scanptr.p->scanState) { - - case ScanRecord::CLOSING_SCAN: - jam(); - if (scanptr.p->apiIsClosed == true) { - jam(); - /* - * The API has either failed or ordered a close of this scan - * it's resources should be released and a response sent - */ - scanReleaseResourcesLab(signal); - return; - }//if - - /** - * The close have been performed but the API is still alive and not - * expecting a response, keep resources until API fails or it orders - * a close - */ return; - case ScanRecord::SCAN_NEXT_ORDERED: + } else { jam(); - /** - * The scan is completed and api is waiting for a response. - * Reslease resources and send a response. - */ - scanReleaseResourcesLab(signal); - return; - case ScanRecord::DELIVERED: - case ScanRecord::QUEUED_DELIVERED: - jam(); - /** - * All processes have reported completion, wait for a new request from - * API and start close of the scan then. - */ - scanptr.p->scanReceivedOperations = 0; - scanptr.p->scanState = ScanRecord::CLOSING_SCAN; - return; - default: - jam(); - systemErrorLab(signal); - break; - }//switch + ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags); + ScanFragList comp(c_scan_frag_pool, scanptr.p->m_completed_scan_frags); + + run.remove(scanFragptr); + comp.add(scanFragptr); + } + close_scan_req_send_conf(signal, scanptr); + return; } -}//Dbtc::execSCAN_PROCCONF() + + if(status == ZCLOSED && scanptr.p->scanNextFragId < scanptr.p->scanNoFrag){ + /** + * Start on next fragment + */ + ndbrequire(noCompletedOps == 0); + scanFragptr.p->scanFragState = ScanFragRec::WAIT_GET_PRIMCONF; + scanFragptr.p->startFragTimer(ctcTimer); + tcConnectptr.i = scanptr.p->scanTcrec; + ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord); + scanFragptr.p->scanFragId = scanptr.p->scanNextFragId++; + signal->theData[0] = tcConnectptr.p->dihConnectptr; + signal->theData[1] = scanFragptr.i; + signal->theData[2] = scanptr.p->scanTableref; + signal->theData[3] = scanFragptr.p->scanFragId; + sendSignal(cdihblockref, GSN_DIGETPRIMREQ, signal, 4, JBB); + return; + } + + Uint32 chksum = 0; + Uint32 totalLen = 0; + for(Uint32 i = 0; iopReturnDataLen[i]; + chksum += (tmp << i); + totalLen += tmp; + } + + { + ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags); + ScanFragList queued(c_scan_frag_pool, scanptr.p->m_queued_scan_frags); + + run.remove(scanFragptr); + queued.add(scanFragptr); + scanptr.p->m_queued_count++; + } + + scanFragptr.p->m_ops = noCompletedOps; + scanFragptr.p->m_chksum = chksum; + scanFragptr.p->m_totalLen = totalLen; + scanFragptr.p->scanFragState = ScanFragRec::QUEUED_FOR_DELIVERY; + scanFragptr.p->stopFragTimer(); + + if(scanptr.p->m_queued_count > /** Min */ 0){ + jam(); + sendScanTabConf(signal); + } +}//Dbtc::execSCAN_FRAGCONF() /**************************************************************************** * execSCAN_NEXTREQ @@ -9541,7 +9191,7 @@ void Dbtc::execSCAN_NEXTREQ(Signal* signal) scanTabRefLab(signal, ZSTATE_ERROR); return; }//if - + /******************************************************* * START THE ACTUAL LOGIC OF SCAN_NEXTREQ. ********************************************************/ @@ -9549,202 +9199,176 @@ void Dbtc::execSCAN_NEXTREQ(Signal* signal) setApiConTimer(apiConnectptr.i, 0, __LINE__); scanptr.i = apiConnectptr.p->apiScanRec; ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord); + ScanRecord* scanP = scanptr.p; - if (scanptr.p->apiIsClosed == true) { - jam(); - /** - * The close is already started. Api has failed or - * has not responded in time so this signal is not allowed - */ - DEBUG("execSCAN_NEXTREQ: apiIsClosed == true"); - DEBUG(" apiConnectstate="<apiConnectstate); - DEBUG(" scanState="<scanState); - return; - }//if - - - if (scanptr.p->scanState == ScanRecord::CLOSING_SCAN) { - jam(); - /********************************************************************* - * WE HAVE STARTED A CLOSE OF THIS SCAN OPERATION. NOW WE CAN REPORT - * THIS TO THE APPLICATION. BEFORE WE REPORT IT TO THE APPLICATION WE - * MUST COMPLETE THE CLOSE FIRST. - *********************************************************************/ - if (scanptr.p->scanCompletedStatus == ZTRUE) { - jam(); - /********************************************************************* - * THE SCAN IS ALREADY COMPLETED. WE ARE NOW READY TO COMPLETE THE SCAN - * BY RELEASING ALL RESOURCES AND SENDING THE CONFIRMATION TO THE - * APPLICATION. - *********************************************************************/ - scanReleaseResourcesLab(signal); - return; - } else { - jam(); - /********************************************************************* - * THE CLOSE IS ONGOING BUT NOT YET COMPLETED. WE WILL SET THE STATE - * TO INDICATE THAT THE APPLICATION IS WAITING FOR THE RESPONSE. - *********************************************************************/ - scanptr.p->apiIsClosed = true; - return; - }//if - }//if + const Uint32 len = signal->getLength() - 4; if (stopScan == ZTRUE) { jam(); /********************************************************************* * APPLICATION IS CLOSING THE SCAN. **********************************************************************/ - scanptr.p->apiIsClosed = true; - scanCompletedLab(signal); + ndbrequire(len == 0); + close_scan_req(signal, scanptr); return; }//if - /********************************************************************* - * THOSE SCAN PROCESSES THAT WAS SENT IN PREVIOUS MESSAGE ARE - * ACKNOWLEDGED BY THIS REQUEST FOR MORE SCANNED OPERATIONS. WE CAN - * THUS RESTART THOSE SCAN PROCESSES. - *********************************************************************/ - for (Uint32 i = 0; i < 16; i++) { - jam(); - scanFragptr.i = scanptr.p->scanFragrec[i]; - if (scanFragptr.i != RNIL) { - jam(); - ptrCheckGuard(scanFragptr, cscanFragrecFileSize, scanFragmentRecord); - if (scanFragptr.p->scanFragState == ScanFragRec::DELIVERED) { - jam(); - scanFragptr.p->scanFragState = ScanFragRec::RETURNING_FROM_DELIVERY; - signal->theData[0] = TcContinueB::ZRETURN_FROM_QUEUED_DELIVERY; - signal->theData[1] = scanptr.i; - signal->theData[2] = scanFragptr.i; - sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB); - } - }//if - }//for + // Copy op ptrs so I dont overwrite them when sending... + memcpy(signal->getDataPtrSend()+25, signal->getDataPtr()+4, 4 * len); - switch (scanptr.p->scanState) { - case ScanRecord::QUEUED_DELIVERED: - /********************************************************************* - * A NUMBER OF SCAN PROCESSES ARE READY TO DELIVER. DELIVER AND SET - * STATE TO DELIVERED. ALSO CONTINUE PROCESS QUEUED SCAN PROCESSES. - *********************************************************************/ + ScanFragNextReq * nextReq = (ScanFragNextReq*)&signal->theData[0]; + nextReq->closeFlag = ZFALSE; + nextReq->transId1 = apiConnectptr.p->transid[0]; + nextReq->transId2 = apiConnectptr.p->transid[1]; + + ScanFragList running(c_scan_frag_pool, scanP->m_running_scan_frags); + ScanFragList delivered(c_scan_frag_pool, scanP->m_delivered_scan_frags); + for(Uint32 i = 0 ; iscanState = ScanRecord::DELIVERED; - /********************************************************************* - * UPDATE STATUS OF THE SCAN PROCESSES THAT WAS NOW SENT TO THE - * APPLICATION TO DELIVERED. PREVIOUSLY THEY WERE QUEUED FOR DELIVERY. - *********************************************************************/ - for (Uint32 i = 0; i < 16; i++) { - jam(); - scanFragptr.i = scanptr.p->scanFragrec[i]; - if (scanFragptr.i != RNIL) { - ptrCheckGuard(scanFragptr, cscanFragrecFileSize, scanFragmentRecord); - if (scanFragptr.p->scanFragState == ScanFragRec::QUEUED_FOR_DELIVERY) { - jam(); - scanFragptr.p->scanFragState = ScanFragRec::DELIVERED; - }//if - }//if - }//for - return; - case ScanRecord::DELIVERED: - jam(); - /********************************************************************* - * WE HAVE NOT ANY QUEUED DELIVERIES. SET STATE TO INDICATE IT IS OK - * TO SEND SCAN_TABCONF AS SOON AS ANY FRAGMENT IS READY TO DELIVER. - *********************************************************************/ - scanptr.p->scanState = ScanRecord::SCAN_NEXT_ORDERED; - return; - case ScanRecord::SCAN_NEXT_ORDERED: - jam(); - /* empty */ - return; - default: - jam(); - systemErrorLab(signal); - return; - }//switch -}//Dbtc::execSCAN_NEXTREQ() + scanFragptr.i = signal->theData[i+25]; + c_scan_frag_pool.getPtr(scanFragptr); + ndbrequire(scanFragptr.p->scanFragState == ScanFragRec::DELIVERED); + + scanFragptr.p->scanFragState = ScanFragRec::LQH_ACTIVE; + scanFragptr.p->startFragTimer(ctcTimer); -void Dbtc::scanCompletedLab(Signal* signal) { - scanptr.p->scanReceivedOperations = 0; - scanptr.p->scanState = ScanRecord::CLOSING_SCAN; - - // Iterate over all fragment scans and check if - // they need to be closed in LQH - for (Uint32 i = 0; i < 16; i++) { - if (scanptr.p->scanFragrec[i] == RNIL) { - jam(); - continue; - } - scanFragptr.i = scanptr.p->scanFragrec[i]; - ptrCheckGuard(scanFragptr, cscanFragrecFileSize, scanFragmentRecord); - - if (scanFragptr.p->lqhBlockref == RNIL){ - // The connection to this LQH has been closed - jam(); - continue; - } - - if (scanFragptr.p->scanFragCompletedStatus == ZCLOSED){ - // The fragment scan is already completed - jam(); - continue; - } - - if (scanFragptr.p->scanFragState == ScanFragRec::RETURNING_FROM_DELIVERY){ - // The scan process is soon to continue executing - // Set scanFragCompletedStatus to ZTRUE so that LQH is properly closed - // when this scan process "returns from delivery" - jam(); - DEBUG("scanCompletedLab: setting scanFragCompletedStatus to ZTRUE"); - scanFragptr.p->scanFragCompletedStatus = ZTRUE; - continue; - } - - apiConnectptr.i = scanptr.p->scanApiRec; - ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord); - - ScanFragNextReq * nextReq = (ScanFragNextReq*)&signal->theData[0]; + scanFragptr.p->m_ops = 0; nextReq->senderData = scanFragptr.i; - nextReq->closeFlag = ZTRUE; - nextReq->transId1 = apiConnectptr.p->transid[0]; - nextReq->transId2 = apiConnectptr.p->transid[1]; sendSignal(scanFragptr.p->lqhBlockref, GSN_SCAN_NEXTREQ, signal, ScanFragNextReq::SignalLength, JBB); - updateBuddyTimer(apiConnectptr); - - updateBuddyTimer(apiConnectptr); - scanFragptr.p->startFragTimer(ctcTimer); - scanFragptr.p->scanFragState = ScanFragRec::LQH_ACTIVE_CLOSE; - + delivered.remove(scanFragptr); + running.add(scanFragptr); }//for -}//Dbtc::scanCompletedLab() + +}//Dbtc::execSCAN_NEXTREQ() -void Dbtc::sendScanProcConf(Signal* signal){ - signal->theData[0] = scanptr.i; - signal->theData[1] = scanFragptr.i; - sendSignal(cownref, GSN_SCAN_PROCCONF, signal, 2, JBB); +void +Dbtc::close_scan_req(Signal* signal, ScanRecordPtr scanPtr){ +#ifdef VM_TRACE + ndbout_c("%d close_scan_req", apiConnectptr.i); +#endif + ScanRecord* scanP = scanPtr.p; + scanPtr.p->scanState = ScanRecord::CLOSING_SCAN; + + /** + * Queue : Action + * ========== : ================= + * completed : - + * running : - + * delivered : close -> LQH + * queued w/ : close -> LQH + * queued wo/ : move to completed + */ + + /** + * All delivered should to be closed + */ + ScanFragNextReq * nextReq = (ScanFragNextReq*)&signal->theData[0]; + nextReq->closeFlag = ZTRUE; + nextReq->transId1 = apiConnectptr.p->transid[0]; + nextReq->transId2 = apiConnectptr.p->transid[1]; + + { + ScanFragRecPtr ptr; + ScanFragList running(c_scan_frag_pool, scanP->m_running_scan_frags); + ScanFragList completed(c_scan_frag_pool, scanP->m_completed_scan_frags); + ScanFragList delivered(c_scan_frag_pool, scanP->m_delivered_scan_frags); + for(delivered.first(ptr); !ptr.isNull(); ){ + jam(); + ScanFragRecPtr curr = ptr; // Remove while iterating... + delivered.next(ptr); + + ndbrequire(curr.p->scanFragState == ScanFragRec::DELIVERED); + delivered.remove(curr); + + if(curr.p->m_ops > 0){ + jam(); + running.add(curr); + curr.p->scanFragState = ScanFragRec::LQH_ACTIVE; + curr.p->startFragTimer(ctcTimer); + nextReq->senderData = curr.i; + sendSignal(curr.p->lqhBlockref, GSN_SCAN_NEXTREQ, signal, + ScanFragNextReq::SignalLength, JBB); + + ndbout_c("delivered -> running"); + } else { + jam(); + completed.add(curr); + curr.p->scanFragState = ScanFragRec::COMPLETED; + curr.p->stopFragTimer(); + ndbout_c("delivered -> completed"); + } + }//for + + /** + * All queued with data should be closed + */ + ScanFragList queued(c_scan_frag_pool, scanP->m_queued_scan_frags); + for(queued.first(ptr); !ptr.isNull(); ){ + jam(); + ndbrequire(ptr.p->scanFragState == ScanFragRec::QUEUED_FOR_DELIVERY); + ScanFragRecPtr curr = ptr; // Remove while iterating... + queued.next(ptr); + + queued.remove(curr); + scanP->m_queued_count--; + + if(curr.p->m_ops > 0){ + jam(); + running.add(curr); + curr.p->scanFragState = ScanFragRec::LQH_ACTIVE; + curr.p->startFragTimer(ctcTimer); + nextReq->senderData = curr.i; + sendSignal(curr.p->lqhBlockref, GSN_SCAN_NEXTREQ, signal, + ScanFragNextReq::SignalLength, JBB); + + ndbout_c("queued -> running"); + } else { + jam(); + completed.add(curr); + curr.p->scanFragState = ScanFragRec::COMPLETED; + curr.p->stopFragTimer(); + ndbout_c("queued -> completed"); + } + } + } + close_scan_req_send_conf(signal, scanptr); } -void Dbtc::releaseScanrec(Signal* signal) { - scanptr.p->nextScan = cfirstfreeScanrec; - scanptr.p->scanState = ScanRecord::IDLE; - scanptr.p->scanTcrec = RNIL; - cfirstfreeScanrec = scanptr.i; -}//Dbtc::releaseScanrec() +void +Dbtc::close_scan_req_send_conf(Signal* signal, ScanRecordPtr scanPtr){ -void Dbtc::releaseScanFragrec(Signal* signal) { - scanFragptr.p->nextScanFrag = cfirstfreeScanFragrec; - scanFragptr.p->scanFragState = ScanFragRec::IDLE; - cfirstfreeScanFragrec = scanFragptr.i; - scanFragptr.p->stopFragTimer(); -}//Dbtc::releaseScanFragrec() + jam(); + ndbrequire(scanPtr.p->m_queued_scan_frags.isEmpty()); + ndbrequire(scanPtr.p->m_delivered_scan_frags.isEmpty()); + if(!scanPtr.p->m_running_scan_frags.isEmpty()){ + jam(); + return; + } + + const bool apiFail = (apiConnectptr.p->apiFailState == ZTRUE); + + if(!apiFail){ + jam(); + Uint32 ref = apiConnectptr.p->ndbapiBlockref; + ScanTabConf * conf = (ScanTabConf*)&signal->theData[0]; + conf->apiConnectPtr = apiConnectptr.p->ndbapiConnect; + conf->requestInfo = ScanTabConf::EndOfData; + conf->transId1 = apiConnectptr.p->transid[0]; + conf->transId2 = apiConnectptr.p->transid[1]; + sendSignal(ref, GSN_SCAN_TABCONF, signal, ScanTabConf::SignalLength, JBB); + } -void Dbtc::releaseScanOprec(Signal* signal) { - scanOpptr.p->nextScanOp = cfirstfreeScanOprec; - cfirstfreeScanOprec = scanOpptr.i; -}//Dbtc::releaseScanOprec() + releaseScanResources(scanPtr); + + if(apiFail){ + jam(); + /** + * API has failed + */ + handleApiFailState(signal, apiConnectptr.i); + } +} void Dbtc::seizeScanrec(Signal* signal) { scanptr.i = cfirstfreeScanrec; @@ -9754,27 +9378,7 @@ void Dbtc::seizeScanrec(Signal* signal) { ndbrequire(scanptr.p->scanState == ScanRecord::IDLE); }//Dbtc::seizeScanrec() -void Dbtc::seizeScanFragrec(Signal* signal) { - scanFragptr.i = cfirstfreeScanFragrec; - ptrCheckGuard(scanFragptr, cscanFragrecFileSize, scanFragmentRecord); - cfirstfreeScanFragrec = scanFragptr.p->nextScanFrag; - scanFragptr.p->nextScanFrag = RNIL; - ndbrequire(scanFragptr.p->scanFragState == ScanFragRec::IDLE); -}//Dbtc::seizeScanFragrec() - -void Dbtc::seizeScanOprec(Signal* signal) { - scanOpptr.i = cfirstfreeScanOprec; - ptrCheckGuard(scanOpptr, cscanOprecFileSize, scanOperationRecord); - cfirstfreeScanOprec = scanOpptr.p->nextScanOp; - scanOpptr.p->nextScanOp = RNIL; -}//Dbtc::seizeScanOprec() - - void Dbtc::sendScanFragReq(Signal* signal) { - arrGuard(scanFragptr.p->scanFragProcId, 16); - scanOpptr.i = scanptr.p->scanOprec[scanFragptr.p->scanFragProcId]; - ptrCheckGuard(scanOpptr, cscanOprecFileSize, scanOperationRecord); - Uint32 requestInfo = 0; ScanFragReq::setConcurrency(requestInfo, scanFragptr.p->scanFragConcurrency); ScanFragReq::setLockMode(requestInfo, scanptr.p->scanLockMode); @@ -9800,96 +9404,72 @@ void Dbtc::sendScanFragReq(Signal* signal) { req->transId1 = apiConnectptr.p->transid[0]; req->transId2 = apiConnectptr.p->transid[1]; for(int i = 0; i<16; i++){ - req->clientOpPtr[i] = scanOpptr.p->apiOpptr[i]; + req->clientOpPtr[i] = scanFragptr.p->m_apiPtr; } sendSignal(scanFragptr.p->lqhBlockref, GSN_SCAN_FRAGREQ, signal, 25, JBB); updateBuddyTimer(apiConnectptr); scanFragptr.p->startFragTimer(ctcTimer); - scanFragptr.p->scanFragCompletedStatus = ZFALSE; }//Dbtc::sendScanFragReq() void Dbtc::sendScanTabConf(Signal* signal) { jam(); - /******************************************************* - * Send SCAN_TABINFO with information about all - * received operations - *******************************************************/ - Int32 operationsToSend = scanptr.p->scanReceivedOperations; - Uint32 sstOpIndex = 0; - - while (operationsToSend > 0){ + Uint32* ops = signal->getDataPtrSend()+4; + Uint32 op_count = scanptr.p->m_queued_count; + if(4 + 3 * op_count > 25){ jam(); - - ScanTabInfo * info = (ScanTabInfo*)&signal->theData[0]; - info->apiConnectPtr = apiConnectptr.p->ndbapiConnect; - - for (int i = 0; i < 16; i++){ - jam(); - arrGuard(sstOpIndex, 16); - scanOpptr.i = scanptr.p->scanOprec[sstOpIndex]; - ptrCheckGuard(scanOpptr, cscanOprecFileSize, scanOperationRecord); - info->operLenAndIdx[i] = scanOpptr.p->scanOpLength[i]; - operationsToSend--; - scanOpptr.p->scanOpLength[i] = RNIL; - } - sstOpIndex++; - sendSignal(apiConnectptr.p->ndbapiBlockref, - GSN_SCAN_TABINFO, signal, ScanTabInfo::SignalLength, JBB); + ops += 21; } - - /******************************************************** - * Send SCAN_TABCONF signaling that a result set have - * been sent to the API - *********************************************************/ - Uint32 requestInfo = 0; - ScanTabConf::setOperations(requestInfo, scanptr.p->scanReceivedOperations); - ScanTabConf::setScanStatus(requestInfo, scanptr.p->scanCompletedStatus); - + ScanTabConf * conf = (ScanTabConf*)&signal->theData[0]; conf->apiConnectPtr = apiConnectptr.p->ndbapiConnect; - conf->requestInfo = requestInfo; + conf->requestInfo = op_count; conf->transId1 = apiConnectptr.p->transid[0]; conf->transId2 = apiConnectptr.p->transid[1]; - sendSignal(apiConnectptr.p->ndbapiBlockref, - GSN_SCAN_TABCONF, signal, ScanTabConf::SignalLength, JBB); + ScanFragRecPtr ptr; + ScanRecord* scanP = scanptr.p; + ScanFragList queued(c_scan_frag_pool, scanP->m_queued_scan_frags); + ScanFragList completed(c_scan_frag_pool, scanP->m_completed_scan_frags); + ScanFragList delivered(c_scan_frag_pool, scanP->m_delivered_scan_frags); + for(queued.first(ptr); !ptr.isNull(); ){ + ndbrequire(ptr.p->scanFragState == ScanFragRec::QUEUED_FOR_DELIVERY); + ScanFragRecPtr curr = ptr; // Remove while iterating... + queued.next(ptr); - scanptr.p->scanReceivedOperations = 0; - // Start the scanRec-timer again and wait for response from the API. - setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__); - updateBuddyTimer(apiConnectptr); + * ops++ = curr.p->m_apiPtr; + * ops++ = curr.i; + * ops++ = (curr.p->m_totalLen << 5) + curr.p->m_ops; + + queued.remove(curr); + if(curr.p->m_ops > 0){ + delivered.add(curr); + curr.p->scanFragState = ScanFragRec::DELIVERED; + curr.p->stopFragTimer(); + } else { + (* --ops) = ScanTabConf::EndOfData; ops++; + completed.add(curr); + curr.p->scanFragState = ScanFragRec::COMPLETED; + curr.p->stopFragTimer(); + } + } + + if(4 + 3 * op_count > 25){ + jam(); + LinearSectionPtr ptr[3]; + ptr[0].p = signal->getDataPtrSend()+25; + ptr[0].sz = 3 * op_count; + sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_SCAN_TABCONF, signal, + ScanTabConf::SignalLength, JBB, ptr, 1); + } else { + jam(); + sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_SCAN_TABCONF, signal, + ScanTabConf::SignalLength + 3 * op_count, JBB); + } + scanptr.p->m_queued_count = 0; }//Dbtc::sendScanTabConf() -/* - * Write index and length of all operations received into - * scanOprec->scanOpLength buffer - */ -void Dbtc::setScanReceived(Signal* signal, Uint32 noCompletedOps) -{ - UintR tssrIndividual; - UintR tssrOprecIndex; - UintR tssrLengthPlusIndex; - UintR tssrOpIndex; - - ndbrequire(noCompletedOps <= 16); - tssrIndividual = scanFragptr.p->scanIndividual; - for (Uint32 i = 0; i < noCompletedOps; i++) { - jam(); - tssrOprecIndex = scanptr.p->scanReceivedOperations >> 4; - arrGuard(tssrOprecIndex, 16); - scanOpptr.i = scanptr.p->scanOprec[tssrOprecIndex]; - ptrCheckGuard(scanOpptr, cscanOprecFileSize, scanOperationRecord); - tssrLengthPlusIndex = tssrIndividual << 24; - tssrLengthPlusIndex += cdata[i]; - tssrOpIndex = scanptr.p->scanReceivedOperations & 15; - scanOpptr.p->scanOpLength[tssrOpIndex] = tssrLengthPlusIndex; - scanptr.p->scanReceivedOperations++; - tssrIndividual++; - }//for -}//Dbtc::setScanReceived() - void Dbtc::gcpTcfinished(Signal* signal) { signal->theData[1] = tcheckGcpId; @@ -10139,6 +9719,7 @@ void Dbtc::initialiseScanrec(Signal* signal) for (scanptr.i = 0; scanptr.i < cscanrecFileSize; scanptr.i++) { jam(); ptrAss(scanptr, scanRecord); + new (scanptr.p) ScanRecord(); scanptr.p->scanState = ScanRecord::IDLE; scanptr.p->nextScan = scanptr.i + 1; }//for @@ -10150,34 +9731,10 @@ void Dbtc::initialiseScanrec(Signal* signal) void Dbtc::initialiseScanFragrec(Signal* signal) { - ndbrequire(cscanFragrecFileSize > 0); - for (scanFragptr.i = 0; scanFragptr.i < cscanFragrecFileSize; - scanFragptr.i++) { - jam(); - ptrAss(scanFragptr, scanFragmentRecord); - scanFragptr.p->scanFragState = ScanFragRec::IDLE; - scanFragptr.p->stopFragTimer(); - scanFragptr.p->nextScanFrag = scanFragptr.i + 1; - }//for - scanFragptr.i = cscanFragrecFileSize - 1; - ptrAss(scanFragptr, scanFragmentRecord); - scanFragptr.p->nextScanFrag = RNIL; - cfirstfreeScanFragrec = 0; }//Dbtc::initialiseScanFragrec() void Dbtc::initialiseScanOprec(Signal* signal) { - ndbrequire(cscanOprecFileSize > 0); - for (scanOpptr.i = 0; scanOpptr.i < cscanOprecFileSize; scanOpptr.i++) { - jam(); - ptrAss(scanOpptr, scanOperationRecord); - scanOpptr.p->nextScanOp = scanOpptr.i + 1; - }//for - scanOpptr.i = cscanOprecFileSize - 1; - ptrAss(scanOpptr, scanOperationRecord); - scanOpptr.p->nextScanOp = RNIL; - cfirstfreeScanOprec = 0; - cnoFreeScanOprec = cscanOprecFileSize; }//Dbtc::initialiseScanOprec() void Dbtc::initTable(Signal* signal) @@ -10302,8 +9859,8 @@ void Dbtc::releaseAbortResources(Signal* signal) if (apiConnectptr.p->cachePtr != RNIL) { cachePtr.i = apiConnectptr.p->cachePtr; ptrCheckGuard(cachePtr, ccacheFilesize, cacheRecord); - releaseAttrinfo(signal); - releaseKeys(signal); + releaseAttrinfo(); + releaseKeys(); }//if tcConnectptr.i = apiConnectptr.p->firstTcConnect; while (tcConnectptr.i != RNIL) { @@ -10312,7 +9869,7 @@ void Dbtc::releaseAbortResources(Signal* signal) // Clear any markers that were set in CS_RECEIVING state clearCommitAckMarker(apiConnectptr.p, tcConnectptr.p); rarTcConnectptr.i = tcConnectptr.p->nextTcConnect; - releaseTcCon(signal); + releaseTcCon(); tcConnectptr.i = rarTcConnectptr.i; }//while apiConnectptr.p->firstTcConnect = RNIL; @@ -10403,7 +9960,7 @@ void Dbtc::releaseGcp(Signal* signal) cfirstfreeGcp = gcpPtr.i; }//Dbtc::releaseGcp() -void Dbtc::releaseKeys(Signal* signal) +void Dbtc::releaseKeys() { UintR Tmp; databufptr.i = cachePtr.p->firstKeybuf; @@ -10682,20 +10239,15 @@ Dbtc::execDUMP_STATE_ORD(Signal* signal) ScanFragRecPtr sfp; sfp.i = recordNo; - ptrAss(sfp, scanFragmentRecord); - infoEvent("Dbtc::ScanFragRec[%d]: state=%d, status=%d, " - "fragid=%d, procid=%d, ", + c_scan_frag_pool.getPtr(sfp); + infoEvent("Dbtc::ScanFragRec[%d]: state=%d fragid=%d", sfp.i, sfp.p->scanFragState, - sfp.p->scanFragCompletedStatus, - sfp.p->scanFragId, - sfp.p->scanFragProcId); - infoEvent(" nodeid=%d, ind=%d, concurr=%d, timer=%d, next=%d", - sfp.p->scanFragNodeId, - sfp.p->scanIndividual, + sfp.p->scanFragId); + infoEvent(" nodeid=%d, concurr=%d, timer=%d", + refToNode(sfp.p->lqhBlockref), sfp.p->scanFragConcurrency, - sfp.p->scanFragTimer, - sfp.p->nextScanFrag); + sfp.p->scanFragTimer); } // Dump all ScanRecords @@ -10762,11 +10314,10 @@ Dbtc::execDUMP_STATE_ORD(Signal* signal) ScanRecordPtr sp; sp.i = recordNo; ptrAss(sp, scanRecord); - infoEvent("Dbtc::ScanRecord[%d]: state=%d, scanOprec=%d, " + infoEvent("Dbtc::ScanRecord[%d]: state=%d" "nextfrag=%d, nofrag=%d", sp.i, sp.p->scanState, - sp.p->noScanOprec, sp.p->scanNextFragId, sp.p->scanNoFrag); infoEvent(" ailen=%d, para=%d, receivedop=%d, noOprePperFrag=%d", @@ -10774,17 +10325,11 @@ Dbtc::execDUMP_STATE_ORD(Signal* signal) sp.p->scanParallel, sp.p->scanReceivedOperations, sp.p->noOprecPerFrag); - infoEvent(" schv=%d, tab=%d, sproc=%d, noTI=%d, norecTI=%d", + infoEvent(" schv=%d, tab=%d, sproc=%d", sp.p->scanSchemaVersion, sp.p->scanTableref, - sp.p->scanStoredProcId, - sp.p->noScanTabInfo, - sp.p->scanTabInfoReceived); - infoEvent(" apiclosed=%d, noProcCompl=%d, " - "complStat=%d, lhold=%d, lmode=%d", - sp.p->apiIsClosed, - sp.p->scanProcessesCompleted, - sp.p->scanCompletedStatus, + sp.p->scanStoredProcId); + infoEvent(" lhold=%d, lmode=%d", sp.p->scanLockHold, sp.p->scanLockMode); infoEvent(" apiRec=%d, next=%d", @@ -10792,13 +10337,20 @@ Dbtc::execDUMP_STATE_ORD(Signal* signal) if (sp.p->scanState != ScanRecord::IDLE){ // Request dump of ScanFragRec - for (Uint32 i = 0; i < 16; i++){ - if (sp.p->scanFragrec[i] != RNIL){ - dumpState->args[0] = DumpStateOrd::TcDumpOneScanFragRec; - dumpState->args[1] = sp.p->scanFragrec[i]; - execDUMP_STATE_ORD(signal); - } - } + ScanFragRecPtr sfptr; +#define DUMP_SFR(x){\ + ScanFragList list(c_scan_frag_pool, x);\ + for(list.first(sfptr); !sfptr.isNull(); list.next(sfptr)){\ + dumpState->args[0] = DumpStateOrd::TcDumpOneScanFragRec; \ + dumpState->args[1] = sfptr.i;\ + execDUMP_STATE_ORD(signal);\ + }} + + DUMP_SFR(sp.p->m_running_scan_frags); + DUMP_SFR(sp.p->m_queued_scan_frags); + DUMP_SFR(sp.p->m_delivered_scan_frags); + DUMP_SFR(sp.p->m_completed_scan_frags); + // Request dump of ApiConnectRecord dumpState->args[0] = DumpStateOrd::TcDumpOneApiConnectRec; dumpState->args[1] = sp.p->scanApiRec; diff --git a/ndb/src/kernel/blocks/dbtup/Dbtup.hpp b/ndb/src/kernel/blocks/dbtup/Dbtup.hpp index c09c8984ce2..70b8a739fef 100644 --- a/ndb/src/kernel/blocks/dbtup/Dbtup.hpp +++ b/ndb/src/kernel/blocks/dbtup/Dbtup.hpp @@ -950,9 +950,6 @@ typedef Ptr TableDescriptorPtr; struct HostBuffer { bool inPackedList; - Uint32 packetLenRC; - Uint32 noOfPacketsRC; - Uint32 packetBufferRC[29]; Uint32 packetLenTA; Uint32 noOfPacketsTA; Uint32 packetBufferTA[30]; @@ -1637,11 +1634,7 @@ private: //------------------------------------------------------------------ //------------------------------------------------------------------ - void bufferREADCONF(Signal* signal, BlockReference aRef, Uint32* buffer, Uint32 Tlen); - -//------------------------------------------------------------------ -//------------------------------------------------------------------ - void bufferTRANSID_AI(Signal* signal, BlockReference aRef, Uint32* buffer, Uint32 Tlen); + void bufferTRANSID_AI(Signal* signal, BlockReference aRef, Uint32 Tlen); //------------------------------------------------------------------ // Trigger handling routines diff --git a/ndb/src/kernel/blocks/dbtup/DbtupBuffer.cpp b/ndb/src/kernel/blocks/dbtup/DbtupBuffer.cpp index 90c6dbc6802..cd5057d8a62 100644 --- a/ndb/src/kernel/blocks/dbtup/DbtupBuffer.cpp +++ b/ndb/src/kernel/blocks/dbtup/DbtupBuffer.cpp @@ -35,7 +35,6 @@ void Dbtup::execSEND_PACKED(Signal* signal) hostId = cpackedList[i]; ndbrequire((hostId - 1) < (MAX_NODES - 1)); // Also check not zero Uint32 TpacketTA = hostBuffer[hostId].noOfPacketsTA; - Uint32 TpacketRC = hostBuffer[hostId].noOfPacketsRC; if (TpacketTA != 0) { ljam(); BlockReference TBref = numberToRef(API_PACKED, hostId); @@ -47,91 +46,17 @@ void Dbtup::execSEND_PACKED(Signal* signal) hostBuffer[hostId].noOfPacketsTA = 0; hostBuffer[hostId].packetLenTA = 0; }//if - if (TpacketRC != 0) { - ljam(); - BlockReference TBref = numberToRef(API_PACKED, hostId); - Uint32 TpacketLen = hostBuffer[hostId].packetLenRC; - MEMCOPY_NO_WORDS(&signal->theData[0], - &hostBuffer[hostId].packetBufferRC[0], - TpacketLen); - sendSignal(TBref, GSN_READCONF, signal, TpacketLen, JBB); - hostBuffer[hostId].noOfPacketsRC = 0; - hostBuffer[hostId].packetLenRC = 0; - }//if hostBuffer[hostId].inPackedList = false; }//for cpackedListIndex = 0; }//Dbtup::execSEND_PACKED() -void Dbtup::bufferREADCONF(Signal* signal, BlockReference aRef, - Uint32* buffer, Uint32 Tlen) -{ - Uint32 hostId = refToNode(aRef); - Uint32 Theader = ((refToBlock(aRef) << 16) + (Tlen-3)); - - ndbrequire(hostId < MAX_NODES); - Uint32 TpacketLen = hostBuffer[hostId].packetLenRC; - Uint32 TnoOfPackets = hostBuffer[hostId].noOfPacketsRC; - Uint32 sig0 = signal->theData[0]; - Uint32 sig1 = signal->theData[1]; - Uint32 sig2 = signal->theData[2]; - Uint32 sig3 = signal->theData[3]; - - BlockReference TBref = numberToRef(API_PACKED, hostId); - - if ((Tlen + TpacketLen + 1) <= 25) { -// ---------------------------------------------------------------- -// There is still space in the buffer. We will copy it into the -// buffer. -// ---------------------------------------------------------------- - ljam(); - updatePackedList(signal, hostId); - } else if (TnoOfPackets == 1) { -// ---------------------------------------------------------------- -// The buffer is full and there was only one packet buffered. We -// will send this as a normal signal. -// ---------------------------------------------------------------- - Uint32 TnewRef = numberToRef((hostBuffer[hostId].packetBufferRC[0] >> 16), - hostId); - MEMCOPY_NO_WORDS(&signal->theData[0], - &hostBuffer[hostId].packetBufferRC[1], - TpacketLen - 1); - sendSignal(TnewRef, GSN_READCONF, signal, (TpacketLen - 1), JBB); - TpacketLen = 0; - TnoOfPackets = 0; - } else { -// ---------------------------------------------------------------- -// The buffer is full but at least two packets. Send those in -// packed form. -// ---------------------------------------------------------------- - MEMCOPY_NO_WORDS(&signal->theData[0], - &hostBuffer[hostId].packetBufferRC[0], - TpacketLen); - sendSignal(TBref, GSN_READCONF, signal, TpacketLen, JBB); - TpacketLen = 0; - TnoOfPackets = 0; - }//if -// ---------------------------------------------------------------- -// Copy the signal into the buffer -// ---------------------------------------------------------------- - hostBuffer[hostId].packetBufferRC[TpacketLen + 0] = Theader; - hostBuffer[hostId].packetBufferRC[TpacketLen + 1] = sig0; - hostBuffer[hostId].packetBufferRC[TpacketLen + 2] = sig1; - hostBuffer[hostId].packetBufferRC[TpacketLen + 3] = sig2; - hostBuffer[hostId].packetBufferRC[TpacketLen + 4] = sig3; - hostBuffer[hostId].noOfPacketsRC = TnoOfPackets + 1; - hostBuffer[hostId].packetLenRC = Tlen + TpacketLen + 1; - MEMCOPY_NO_WORDS(&hostBuffer[hostId].packetBufferRC[TpacketLen + 5], - buffer, - Tlen - 4); -}//Dbtup::bufferREADCONF() - void Dbtup::bufferTRANSID_AI(Signal* signal, BlockReference aRef, - Uint32* buffer, Uint32 Tlen) + Uint32 Tlen) { Uint32 hostId = refToNode(aRef); Uint32 Theader = ((refToBlock(aRef) << 16)+(Tlen-3)); - + ndbrequire(hostId < MAX_NODES); Uint32 TpacketLen = hostBuffer[hostId].packetLenTA; Uint32 TnoOfPackets = hostBuffer[hostId].noOfPacketsTA; @@ -148,7 +73,7 @@ void Dbtup::bufferTRANSID_AI(Signal* signal, BlockReference aRef, // ---------------------------------------------------------------- ljam(); updatePackedList(signal, hostId); - } else if (TnoOfPackets == 1) { + } else if (false && TnoOfPackets == 1) { // ---------------------------------------------------------------- // The buffer is full and there was only one packet buffered. We // will send this as a normal signal. @@ -183,7 +108,7 @@ void Dbtup::bufferTRANSID_AI(Signal* signal, BlockReference aRef, hostBuffer[hostId].noOfPacketsTA = TnoOfPackets + 1; hostBuffer[hostId].packetLenTA = Tlen + TpacketLen + 1; MEMCOPY_NO_WORDS(&hostBuffer[hostId].packetBufferTA[TpacketLen + 4], - buffer, + &signal->theData[25], Tlen - 3); }//Dbtup::bufferTRANSID_AI() @@ -206,124 +131,122 @@ void Dbtup::sendReadAttrinfo(Signal* signal, const Operationrec * const regOperPtr) { const BlockReference recBlockref = regOperPtr->recBlockref; - bool toOwnNode = refToNode(recBlockref) == getOwnNodeId(); - bool connectedToNode = getNodeInfo(refToNode(recBlockref)).m_connected; - const Uint32 type = getNodeInfo(refToNode(recBlockref)).m_type; + const Uint32 block = refToBlock(recBlockref); + const Uint32 nodeId = refToNode(recBlockref); + + bool connectedToNode = getNodeInfo(nodeId).m_connected; + const Uint32 type = getNodeInfo(nodeId).m_type; bool is_api = (type >= NodeInfo::API && type <= NodeInfo::REP); + bool old_dest = (getNodeInfo(nodeId).m_version < MAKE_VERSION(3,5,0)); - if (ERROR_INSERTED(4006)){ + if (ERROR_INSERTED(4006) && (nodeId != getOwnNodeId())){ // Use error insert to turn routing on ljam(); connectedToNode = false; } - if (!toOwnNode && !connectedToNode){ - /** - * If this node does not have a direct connection - * to the receiving node we want to send the signals - * routed via the node that controls this read - */ - Uint32 routeBlockref = regOperPtr->coordinatorTC; - - /** - * Fill in a TRANSID_AI signal, use last word to store - * final destination and send it to route node - * as signal TRANSID_AI_R (R as in Routed) - */ - TransIdAI * const transIdAI = (TransIdAI *)signal->getDataPtr(); - transIdAI->connectPtr = regOperPtr->tcOperationPtr; - transIdAI->transId[0] = regOperPtr->transid1; - transIdAI->transId[1] = regOperPtr->transid2; - - Uint32 tot = ToutBufIndex; - Uint32 sent = 0; - Uint32 maxLen = TransIdAI::DataLength - 1; - while (sent < tot) { - ljam(); - Uint32 dataLen = (tot - sent > maxLen) ? maxLen : tot - sent; - Uint32 sigLen = dataLen + TransIdAI::HeaderLength + 1; - MEMCOPY_NO_WORDS(&transIdAI->attrData, - &coutBuffer[sent], - dataLen); - // Set final destination in last word - transIdAI->attrData[dataLen] = recBlockref; - - sendSignal(routeBlockref, GSN_TRANSID_AI_R, - signal, sigLen, JBB); - sent += dataLen; - - } - return; - } - - Uint32 TbufIndex = 0; Uint32 sig0 = regOperPtr->tcOperationPtr; Uint32 sig1 = regOperPtr->transid1; Uint32 sig2 = regOperPtr->transid2; - signal->theData[0] = sig0; - signal->theData[1] = sig1; - signal->theData[2] = sig2; + + TransIdAI * transIdAI = (TransIdAI *)signal->getDataPtrSend(); + transIdAI->connectPtr = sig0; + transIdAI->transId[0] = sig1; + transIdAI->transId[1] = sig2; + + if (connectedToNode){ + /** + * Own node -> execute direct + */ + if(nodeId != getOwnNodeId()){ + ljam(); + + /** + * Send long sig + */ + if(ToutBufIndex >= 22 && is_api && !old_dest) { + ljam(); + LinearSectionPtr ptr[3]; + ptr[0].p = &signal->theData[25]; + ptr[0].sz = ToutBufIndex; + sendSignal(recBlockref, GSN_TRANSID_AI, signal, 3, JBB, ptr, 1); + return; + } + + /** + * short sig + api -> buffer + */ +#ifndef NDB_NO_DROPPED_SIGNAL + if (ToutBufIndex < 22 && is_api){ + ljam(); + bufferTRANSID_AI(signal, recBlockref, 3+ToutBufIndex); + return; + }//if +#endif - while (ToutBufIndex > 21) { - ljam(); - MEMCOPY_NO_WORDS(&signal->theData[3], - &coutBuffer[TbufIndex], - 22); - TbufIndex += 22; - ToutBufIndex -= 22; - const BlockReference sendBref = regOperPtr->recBlockref; - if (refToNode(sendBref) != getOwnNodeId()) { - ljam(); - sendSignal(sendBref, GSN_TRANSID_AI, signal, 25, JBB); - ljam(); - } else { - ljam(); - EXECUTE_DIRECT(refToBlock(sendBref), GSN_TRANSID_AI, signal, 25); - ljamEntry(); - }//if - }//while - - Uint32 TsigNumber; - Uint32 TsigLen; - Uint32 TdataIndex; - if ((regOperPtr->opSimple == ZTRUE) && - (regOperPtr->optype == ZREAD)) { - /* DIRTY OPERATIONS ARE ALSO SIMPLE */ - ljam(); - Uint32 sig3 = regOperPtr->attroutbufLen; - TdataIndex = 4; - TsigLen = 4 + ToutBufIndex; - TsigNumber = GSN_READCONF; - signal->theData[3] = sig3; - if ((TsigLen < 18) && is_api){ - bufferREADCONF(signal, regOperPtr->recBlockref, - &coutBuffer[TbufIndex], TsigLen); + /** + * rest -> old send sig + */ + Uint32 * src = signal->theData+25; + if(ToutBufIndex >= 22){ + do { + ljam(); + MEMCOPY_NO_WORDS(&signal->theData[3], src, 22); + sendSignal(recBlockref, GSN_TRANSID_AI, signal, 25, JBB); + ToutBufIndex -= 22; + src += 22; + } while(ToutBufIndex >= 22); + } + + if(ToutBufIndex > 0){ + ljam(); + MEMCOPY_NO_WORDS(&signal->theData[3], src, ToutBufIndex); + sendSignal(recBlockref, GSN_TRANSID_AI, signal, 3+ToutBufIndex, JBB); + } return; - }//if - } else if (ToutBufIndex > 0) { - ljam(); - TdataIndex = 3; - TsigLen = 3 + ToutBufIndex; - TsigNumber = GSN_TRANSID_AI; - if ((TsigLen < 18) && is_api){ - ljam(); - bufferTRANSID_AI(signal, regOperPtr->recBlockref, - &coutBuffer[TbufIndex], TsigLen); - return; - }//if - } else { - ljam(); - return; - }//if - MEMCOPY_NO_WORDS(&signal->theData[TdataIndex], - &coutBuffer[TbufIndex], - ToutBufIndex); - const BlockReference sendBref = regOperPtr->recBlockref; - if (refToNode(sendBref) != getOwnNodeId()) { - ljam(); - sendSignal(sendBref, TsigNumber, signal, TsigLen, JBB); - } else { - EXECUTE_DIRECT(refToBlock(sendBref), GSN_TRANSID_AI, signal, TsigLen); + } + EXECUTE_DIRECT(block, GSN_TRANSID_AI, signal, 3 + ToutBufIndex); ljamEntry(); - }//if + return; + } + + /** + * If this node does not have a direct connection + * to the receiving node we want to send the signals + * routed via the node that controls this read + */ + Uint32 routeBlockref = regOperPtr->coordinatorTC; + + if(is_api && !old_dest){ + ljam(); + transIdAI->attrData[0] = recBlockref; + LinearSectionPtr ptr[3]; + ptr[0].p = &signal->theData[25]; + ptr[0].sz = ToutBufIndex; + sendSignal(routeBlockref, GSN_TRANSID_AI_R, signal, 4, JBB, ptr, 1); + return; + } + + /** + * Fill in a TRANSID_AI signal, use last word to store + * final destination and send it to route node + * as signal TRANSID_AI_R (R as in Routed) + */ + Uint32 tot = ToutBufIndex; + Uint32 sent = 0; + Uint32 maxLen = TransIdAI::DataLength - 1; + while (sent < tot) { + ljam(); + Uint32 dataLen = (tot - sent > maxLen) ? maxLen : tot - sent; + Uint32 sigLen = dataLen + TransIdAI::HeaderLength + 1; + MEMCOPY_NO_WORDS(&transIdAI->attrData, + &signal->theData[25+sent], + dataLen); + // Set final destination in last word + transIdAI->attrData[dataLen] = recBlockref; + + sendSignal(routeBlockref, GSN_TRANSID_AI_R, + signal, sigLen, JBB); + sent += dataLen; + } }//Dbtup::sendReadAttrinfo() diff --git a/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp b/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp index 07bad00acf1..eb9ff08c2b1 100644 --- a/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp +++ b/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp @@ -873,6 +873,7 @@ int Dbtup::handleReadReq(Signal* signal, Page* pagePtr) { Uint32 Ttupheadoffset = regOperPtr->pageOffset; + const BlockReference sendBref = regOperPtr->recBlockref; if (regTabPtr->checksumIndicator && (calculateChecksum(pagePtr, Ttupheadoffset, regTabPtr->tupheadsize) != 0)) { @@ -882,14 +883,29 @@ int Dbtup::handleReadReq(Signal* signal, return -1; }//if + Uint32 * dst = &signal->theData[25]; + Uint32 dstLen = (sizeof(signal->theData) / 4) - 25; + const Uint32 node = refToNode(sendBref); + if(node != 0 && node != getOwnNodeId()) { + ; + } else { + jam(); + /** + * execute direct + */ + dst = &signal->theData[3]; + dstLen = (sizeof(signal->theData) / 4) - 3; + } + if (regOperPtr->interpretedExec != 1) { jam(); + Uint32 TnoOfDataRead = readAttributes(pagePtr, Ttupheadoffset, &cinBuffer[0], regOperPtr->attrinbufLen, - &coutBuffer[0], - (Uint32)ZATTR_BUFFER_SIZE); + dst, + dstLen); if (TnoOfDataRead != (Uint32)-1) { /* ------------------------------------------------------------------------- */ // We have read all data into coutBuffer. Now send it to the API. @@ -1214,11 +1230,8 @@ int Dbtup::interpreterStartLab(Signal* signal, Uint32 RattrinbufLen = regOperPtr->attrinbufLen; const BlockReference sendBref = regOperPtr->recBlockref; - Uint32 * dst = &coutBuffer[0]; - Uint32 dstLen = sizeof(coutBuffer) / 4; - Uint32 * tmp = &signal->theData[3]; - Uint32 tmpLen = (sizeof(signal->theData) / 4) - 3; - bool executeDirect = false; + Uint32 * dst = &signal->theData[25]; + Uint32 dstLen = (sizeof(signal->theData) / 4) - 25; const Uint32 node = refToNode(sendBref); if(node != 0 && node != getOwnNodeId()) { ; @@ -1227,12 +1240,8 @@ int Dbtup::interpreterStartLab(Signal* signal, /** * execute direct */ - executeDirect = true; dst = &signal->theData[3]; dstLen = (sizeof(signal->theData) / 4) - 3; - - tmp = &coutBuffer[0]; - tmpLen = sizeof(coutBuffer) / 4; } RtotalLen = RinitReadLen; @@ -1292,8 +1301,8 @@ int Dbtup::interpreterStartLab(Signal* signal, RexecRegionLen, &cinBuffer[RsubPC], RsubLen, - tmp, - tmpLen); + &coutBuffer[0], + sizeof(coutBuffer) / 4); if (TnoDataRW != (Uint32)-1) { RinstructionCounter += RexecRegionLen; RlogSize = TnoDataRW; @@ -1350,20 +1359,7 @@ int Dbtup::interpreterStartLab(Signal* signal, }//if regOperPtr->logSize = RlogSize; regOperPtr->attroutbufLen = RattroutCounter; - if(!executeDirect) { - jam(); - sendReadAttrinfo(signal, RattroutCounter, regOperPtr); - } else { - jam(); - Uint32 sig0 = regOperPtr->tcOperationPtr; - Uint32 sig1 = regOperPtr->transid1; - Uint32 sig2 = regOperPtr->transid2; - signal->theData[0] = sig0; - signal->theData[1] = sig1; - signal->theData[2] = sig2; - EXECUTE_DIRECT(refToBlock(sendBref), GSN_TRANSID_AI, signal, - 3 + RattroutCounter); - }//if + sendReadAttrinfo(signal, RattroutCounter, regOperPtr); if (RlogSize > 0) { sendLogAttrinfo(signal, RlogSize, regOperPtr); }//if diff --git a/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp b/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp index 095ea412701..3b54817edb0 100644 --- a/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp +++ b/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp @@ -966,9 +966,7 @@ void Dbtup::initializeHostBuffer() for (hostId = 0; hostId < MAX_NODES; hostId++) { hostBuffer[hostId].inPackedList = false; hostBuffer[hostId].noOfPacketsTA = 0; - hostBuffer[hostId].noOfPacketsRC = 0; hostBuffer[hostId].packetLenTA = 0; - hostBuffer[hostId].packetLenRC = 0; }//for }//Dbtup::initializeHostBuffer() diff --git a/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp b/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp index b5a5d0948bb..5965673f25f 100644 --- a/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp +++ b/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp @@ -1667,7 +1667,7 @@ void Ndbcntr::crSystab7Lab(Signal* signal) tcKeyReq->requestInfo = reqInfo; tcKeyReq->tableSchemaVersion = ZSYSTAB_VERSION; tcKeyReq->transId1 = 0; - tcKeyReq->transId2 = 0; + tcKeyReq->transId2 = ckey; //------------------------------------------------------------- // There is no optional part in this TCKEYREQ. There is one diff --git a/ndb/src/ndbapi/Makefile b/ndb/src/ndbapi/Makefile index f2dd21fdaa3..648c8cbb016 100644 --- a/ndb/src/ndbapi/Makefile +++ b/ndb/src/ndbapi/Makefile @@ -34,31 +34,25 @@ SOURCES = \ Ndblist.cpp \ Ndbif.cpp \ Ndbinit.cpp \ - Ndberr.cpp \ - ndberror.c \ - NdbErrorOut.cpp \ - NdbConnection.cpp \ + ndberror.c Ndberr.cpp NdbErrorOut.cpp \ + NdbConnection.cpp \ NdbConnectionScan.cpp \ NdbOperation.cpp \ NdbOperationSearch.cpp \ - NdbOperationScan.cpp \ NdbOperationInt.cpp \ NdbOperationDefine.cpp \ NdbOperationExec.cpp \ - NdbScanReceiver.cpp \ NdbResultSet.cpp \ - NdbCursorOperation.cpp \ NdbScanOperation.cpp NdbScanFilter.cpp \ NdbIndexOperation.cpp \ NdbEventOperation.cpp \ NdbEventOperationImpl.cpp \ NdbApiSignal.cpp \ NdbRecAttr.cpp \ - NdbSchemaCon.cpp \ - NdbSchemaOp.cpp \ NdbUtil.cpp \ NdbReceiver.cpp \ - NdbDictionary.cpp NdbDictionaryImpl.cpp DictCache.cpp + NdbDictionary.cpp NdbDictionaryImpl.cpp DictCache.cpp \ + NdbSchemaCon.cpp NdbSchemaOp.cpp include $(NDB_TOP)/Epilogue.mk diff --git a/ndb/src/ndbapi/Ndb.cpp b/ndb/src/ndbapi/Ndb.cpp index 2a8abf1870c..63cc871b707 100644 --- a/ndb/src/ndbapi/Ndb.cpp +++ b/ndb/src/ndbapi/Ndb.cpp @@ -158,26 +158,22 @@ Ndb::NDB_connect(Uint32 tNode) tNdbCon->Status(Connecting); // Set status to connecting Uint32 nodeSequence; { // send and receive signal - tp->lock_mutex(); + Guard guard(tp->theMutexPtr); nodeSequence = tp->getNodeSequence(tNode); bool node_is_alive = tp->get_node_alive(tNode); if (node_is_alive) { tReturnCode = tp->sendSignal(tSignal, tNode); releaseSignal(tSignal); - if (tReturnCode == -1) { - tp->unlock_mutex(); - } else { + if (tReturnCode != -1) { theWaiter.m_node = tNode; theWaiter.m_state = WAIT_TC_SEIZE; tReturnCode = receiveResponse(); }//if } else { releaseSignal(tSignal); - tp->unlock_mutex(); tReturnCode = -1; }//if } - if ((tReturnCode == 0) && (tNdbCon->Status() == Connected)) { //************************************************ // Send and receive was successful @@ -467,9 +463,9 @@ Ndb::closeTransaction(NdbConnection* aConnection) CHECK_STATUS_MACRO_VOID; tCon = theTransactionList; - + if (aConnection == tCon) { // Remove the active connection object - theTransactionList = tCon->next(); // from the transaction list. + theTransactionList = tCon->next(); // from the transaction list. } else { while (aConnection != tCon) { if (tCon == NULL) { @@ -477,44 +473,33 @@ Ndb::closeTransaction(NdbConnection* aConnection) // closeTransaction called on non-existing transaction //----------------------------------------------------- - if(aConnection->theError.code == 4008){ - /** - * When a SCAN timed-out, returning the NdbConnection leads - * to reuse. And TC crashes when the API tries to reuse it to - * something else... - */ + if(aConnection->theError.code == 4008){ + /** + * When a SCAN timed-out, returning the NdbConnection leads + * to reuse. And TC crashes when the API tries to reuse it to + * something else... + */ #ifdef VM_TRACE - printf("Scan timeout:ed NdbConnection-> not returning it-> memory leak\n"); + printf("Scan timeout:ed NdbConnection-> " + "not returning it-> memory leak\n"); #endif - return; - } + return; + } #ifdef VM_TRACE - printf("Non-existing transaction into closeTransaction\n"); + printf("Non-existing transaction into closeTransaction\n"); abort(); #endif - return; + return; }//if tPreviousCon = tCon; tCon = tCon->next(); }//while tPreviousCon->next(tCon->next()); }//if - + aConnection->release(); - - if(aConnection->theError.code == 4008){ - /** - * When a SCAN timed-out, returning the NdbConnection leads - * to reuse. And TC crashes when the API tries to reuse it to - * something else... - */ -#ifdef VM_TRACE - printf("Scan timeout:ed NdbConnection-> not returning it-> memory leak\n"); -#endif - return; - } - + if(aConnection->theError.code == 4008){ /** * Something timed-out, returning the NdbConnection leads @@ -526,7 +511,7 @@ Ndb::closeTransaction(NdbConnection* aConnection) #endif return; } - + if (aConnection->theReleaseOnClose == false) { /** * Put it back in idle list for that node diff --git a/ndb/src/ndbapi/NdbApiSignal.cpp b/ndb/src/ndbapi/NdbApiSignal.cpp index a9cd5b1d53a..91e4aa5976d 100644 --- a/ndb/src/ndbapi/NdbApiSignal.cpp +++ b/ndb/src/ndbapi/NdbApiSignal.cpp @@ -47,6 +47,7 @@ Adjust: 971114 UABMNST First version. #include #include #include +#include #include @@ -189,7 +190,7 @@ NdbApiSignal::setSignal(int aNdbSignalType) theTrace = TestOrd::TraceAPI; theReceiversBlockNumber = DBTC; theVerId_signalNumber = GSN_SCAN_TABREQ; - theLength = 25; + theLength = 9; // ScanTabReq::SignalLength; } break; diff --git a/ndb/src/ndbapi/NdbConnection.cpp b/ndb/src/ndbapi/NdbConnection.cpp index 4ec098c3c60..84254b94612 100644 --- a/ndb/src/ndbapi/NdbConnection.cpp +++ b/ndb/src/ndbapi/NdbConnection.cpp @@ -27,11 +27,12 @@ Description: Interface between TIS and NDB Documentation: Adjust: 971022 UABMNST First version. *****************************************************************************/ -#include "NdbOut.hpp" -#include "NdbConnection.hpp" -#include "NdbOperation.hpp" -#include "NdbScanOperation.hpp" -#include "NdbIndexOperation.hpp" +#include +#include +#include +#include +#include +#include #include "NdbApiSignal.hpp" #include "TransporterFacade.hpp" #include "API.hpp" @@ -79,15 +80,12 @@ NdbConnection::NdbConnection( Ndb* aNdb ) : theTransactionIsStarted(false), theDBnode(0), theReleaseOnClose(false), - // Cursor operations - m_waitForReply(true), - m_theFirstCursorOperation(NULL), - m_theLastCursorOperation(NULL), - m_firstExecutedCursorOp(NULL), // Scan operations - theScanFinished(0), - theCurrentScanRec(NULL), - thePreviousScanRec(NULL), + m_waitForReply(true), + m_theFirstScanOperation(NULL), + m_theLastScanOperation(NULL), + m_firstExecutedScanOp(NULL), + // Scan operations theScanningOp(NULL), theBuddyConPtr(0xFFFFFFFF) { @@ -117,7 +115,6 @@ NdbConnection::init() theListState = NotInList; theInUseState = true; theTransactionIsStarted = false; - theScanFinished = 0; theNext = NULL; theFirstOpInList = NULL; @@ -128,9 +125,6 @@ NdbConnection::init() theFirstExecOpInList = NULL; theLastExecOpInList = NULL; - theCurrentScanRec = NULL; - thePreviousScanRec = NULL; - theCompletedFirstOp = NULL; theGlobalCheckpointId = 0; @@ -146,11 +140,11 @@ NdbConnection::init() theSimpleState = true; theSendStatus = InitState; theMagicNumber = 0x37412619; - // Cursor operations + // Scan operations m_waitForReply = true; - m_theFirstCursorOperation = NULL; - m_theLastCursorOperation = NULL; - m_firstExecutedCursorOp = 0; + m_theFirstScanOperation = NULL; + m_theLastScanOperation = NULL; + m_firstExecutedScanOp = 0; theBuddyConPtr = 0xFFFFFFFF; }//NdbConnection::init() @@ -331,7 +325,7 @@ NdbConnection::executeAsynchPrepare( ExecType aTypeOfExec, */ theError.code = 0; - NdbCursorOperation* tcOp = m_theFirstCursorOperation; + NdbScanOperation* tcOp = m_theFirstScanOperation; if (tcOp != 0){ // Execute any cursor operations while (tcOp != NULL) { @@ -340,14 +334,14 @@ NdbConnection::executeAsynchPrepare( ExecType aTypeOfExec, if (tReturnCode == -1) { return; }//if - tcOp = (NdbCursorOperation*)tcOp->next(); + tcOp = (NdbScanOperation*)tcOp->next(); } // while - m_theLastCursorOperation->next(m_firstExecutedCursorOp); - m_firstExecutedCursorOp = m_theFirstCursorOperation; + m_theLastScanOperation->next(m_firstExecutedScanOp); + m_firstExecutedScanOp = m_theFirstScanOperation; // Discard cursor operations, since these are also // in the complete operations list we do not need // to release them. - m_theFirstCursorOperation = m_theLastCursorOperation = NULL; + m_theFirstScanOperation = m_theLastScanOperation = NULL; } bool tTransactionIsStarted = theTransactionIsStarted; @@ -714,17 +708,14 @@ Remark: Release all operations. ******************************************************************************/ void NdbConnection::release(){ - if (theTransactionIsStarted == true && theScanningOp != NULL ) - stopScan(); - releaseOperations(); if ( (theTransactionIsStarted == true) && - ((theCommitStatus != Committed) && - (theCommitStatus != Aborted))) { -/**************************************************************************** - * The user did not perform any rollback but simply closed the - * transaction. We must rollback Ndb since Ndb have been contacted. -******************************************************************************/ + ((theCommitStatus != Committed) && + (theCommitStatus != Aborted))) { + /************************************************************************ + * The user did not perform any rollback but simply closed the + * transaction. We must rollback Ndb since Ndb have been contacted. + ************************************************************************/ execute(Rollback); }//if theMagicNumber = 0xFE11DC; @@ -756,8 +747,8 @@ void NdbConnection::releaseOperations() { // Release any open scans - releaseCursorOperations(m_theFirstCursorOperation); - releaseCursorOperations(m_firstExecutedCursorOp); + releaseScanOperations(m_theFirstScanOperation); + releaseScanOperations(m_firstExecutedScanOp); releaseOps(theCompletedFirstOp); releaseOps(theFirstOpInList); @@ -769,9 +760,9 @@ NdbConnection::releaseOperations() theLastOpInList = NULL; theLastExecOpInList = NULL; theScanningOp = NULL; - m_theFirstCursorOperation = NULL; - m_theLastCursorOperation = NULL; - m_firstExecutedCursorOp = NULL; + m_theFirstScanOperation = NULL; + m_theLastScanOperation = NULL; + m_firstExecutedScanOp = NULL; }//NdbConnection::releaseOperations() void @@ -782,24 +773,21 @@ NdbConnection::releaseCompletedOperations() }//NdbConnection::releaseOperations() /****************************************************************************** -void releaseCursorOperations(); +void releaseScanOperations(); Remark: Release all cursor operations. (NdbScanOperation and NdbIndexOperation) ******************************************************************************/ void -NdbConnection::releaseCursorOperations(NdbCursorOperation* cursorOp) +NdbConnection::releaseScanOperations(NdbIndexScanOperation* cursorOp) { while(cursorOp != 0){ - NdbCursorOperation* next = (NdbCursorOperation*)cursorOp->next(); + NdbIndexScanOperation* next = (NdbIndexScanOperation*)cursorOp->next(); cursorOp->release(); - if (cursorOp->cursorType() == NdbCursorOperation::ScanCursor) - theNdb->releaseScanOperation((NdbScanOperation*)cursorOp); - else - theNdb->releaseOperation(cursorOp); + theNdb->releaseScanOperation(cursorOp); cursorOp = next; } -}//NdbConnection::releaseCursorOperations() +}//NdbConnection::releaseScanOperations() /***************************************************************************** NdbOperation* getNdbOperation(const char* aTableName); @@ -832,45 +820,6 @@ NdbConnection::getNdbOperation(const char* aTableName) return NULL; }//NdbConnection::getNdbOperation() -/***************************************************************************** -NdbOperation* getNdbOperation(const char* anIndexName, const char* aTableName); - -Return Value Return a pointer to a NdbOperation object if getNdbOperation - was succesful. - Return NULL : In all other case. -Parameters: anIndexName : Name of the index to use. - aTableName : Name of the database table. -Remark: Get an operation from NdbOperation idlelist and get the - NdbConnection object - who was fetch by startTransaction pointing to this operation - getOperation will set the theTableId in the NdbOperation object. - synchronous -******************************************************************************/ -NdbOperation* -NdbConnection::getNdbOperation(const char* anIndexName, const char* aTableName) -{ - if ((theError.code == 0) && - (theCommitStatus == Started)){ - NdbIndexImpl* index = - theNdb->theDictionary->getIndex(anIndexName, aTableName); - NdbTableImpl* table = theNdb->theDictionary->getTable(aTableName); - NdbTableImpl* indexTable = - theNdb->theDictionary->getIndexTable(index, table); - if (indexTable != 0){ - return getNdbOperation(indexTable); - } else { - setErrorCode(theNdb->theDictionary->getNdbError().code); - return NULL; - }//if - } else { - if (theError.code == 0) { - setOperationErrorCodeAbort(4114); - }//if - - return NULL; - }//if -}//NdbConnection::getNdbOperation() - /***************************************************************************** NdbOperation* getNdbOperation(int aTableId); @@ -956,8 +905,9 @@ Remark: Get an operation from NdbScanOperation idlelist and get the NdbC who was fetch by startTransaction pointing to this operation getOperation will set the theTableId in the NdbOperation object.synchronous ******************************************************************************/ -NdbScanOperation* -NdbConnection::getNdbScanOperation(const char* anIndexName, const char* aTableName) +NdbIndexScanOperation* +NdbConnection::getNdbIndexScanOperation(const char* anIndexName, + const char* aTableName) { if (theCommitStatus == Started){ NdbIndexImpl* index = @@ -966,7 +916,9 @@ NdbConnection::getNdbScanOperation(const char* anIndexName, const char* aTableNa NdbTableImpl* indexTable = theNdb->theDictionary->getIndexTable(index, table); if (indexTable != 0){ - return getNdbScanOperation(indexTable); + NdbIndexScanOperation* tOp = getNdbScanOperation(indexTable); + if(tOp) tOp->m_cursor_type = NdbScanOperation::IndexCursor; + return tOp; } else { setOperationErrorCodeAbort(theNdb->theError.code); return NULL; @@ -987,21 +939,21 @@ Remark: Get an operation from NdbScanOperation object idlelist and get t object who was fetch by startTransaction pointing to this operation getOperation will set the theTableId in the NdbOperation object, synchronous. *****************************************************************************/ -NdbScanOperation* +NdbIndexScanOperation* NdbConnection::getNdbScanOperation(NdbTableImpl * tab) { - NdbScanOperation* tOp; + NdbIndexScanOperation* tOp; tOp = theNdb->getScanOperation(); if (tOp == NULL) goto getNdbOp_error1; // Link scan operation into list of cursor operations - if (m_theLastCursorOperation == NULL) - m_theFirstCursorOperation = m_theLastCursorOperation = tOp; + if (m_theLastScanOperation == NULL) + m_theFirstScanOperation = m_theLastScanOperation = tOp; else { - m_theLastCursorOperation->next(tOp); - m_theLastCursorOperation = tOp; + m_theLastScanOperation->next(tOp); + m_theLastScanOperation = tOp; } tOp->next(NULL); if (tOp->init(tab, this) != -1) { @@ -1211,12 +1163,12 @@ Remark: int NdbConnection::receiveTC_COMMITCONF(const TcCommitConf * commitConf) { - if(theStatus != Connected){ - return -1; + if(checkState_TransId(&commitConf->transId1)){ + theCommitStatus = Committed; + theCompletionStatus = CompletedSuccess; + return 0; } - theCommitStatus = Committed; - theCompletionStatus = CompletedSuccess; - return 0; + return -1; }//NdbConnection::receiveTC_COMMITCONF() /****************************************************************************** @@ -1230,33 +1182,33 @@ Remark: int NdbConnection::receiveTC_COMMITREF(NdbApiSignal* aSignal) { - if(theStatus != Connected){ - return -1; + const TcCommitRef * ref = CAST_CONSTPTR(TcCommitRef, aSignal->getDataPtr()); + if(checkState_TransId(&ref->transId1)){ + setOperationErrorCodeAbort(ref->errorCode); + theCommitStatus = Aborted; + theCompletionStatus = CompletedFailure; + return 0; } - const TcCommitRef * const ref = CAST_CONSTPTR(TcCommitRef, aSignal->getDataPtr()); - setOperationErrorCodeAbort(ref->errorCode); - theCommitStatus = Aborted; - theCompletionStatus = CompletedFailure; - return 0; + return -1; }//NdbConnection::receiveTC_COMMITREF() -/******************************************************************************* +/****************************************************************************** int receiveTCROLLBACKCONF(NdbApiSignal* aSignal); Return Value: Return 0 : receiveTCROLLBACKCONF was successful. Return -1: In all other case. Parameters: aSignal: The signal object pointer. Remark: -*******************************************************************************/ +******************************************************************************/ int NdbConnection::receiveTCROLLBACKCONF(NdbApiSignal* aSignal) { - if(theStatus != Connected){ - return -1; + if(checkState_TransId(aSignal->getDataPtr() + 1)){ + theCommitStatus = Aborted; + theCompletionStatus = CompletedSuccess; + return 0; } - theCommitStatus = Aborted; - theCompletionStatus = CompletedSuccess; - return 0; + return -1; }//NdbConnection::receiveTCROLLBACKCONF() /******************************************************************************* @@ -1270,13 +1222,13 @@ Remark: int NdbConnection::receiveTCROLLBACKREF(NdbApiSignal* aSignal) { - if(theStatus != Connected){ - return -1; + if(checkState_TransId(aSignal->getDataPtr() + 1)){ + setOperationErrorCodeAbort(aSignal->readData(4)); + theCommitStatus = Aborted; + theCompletionStatus = CompletedFailure; + return 0; } - setOperationErrorCodeAbort(aSignal->readData(2)); - theCommitStatus = Aborted; - theCompletionStatus = CompletedFailure; - return 0; + return -1; }//NdbConnection::receiveTCROLLBACKREF() /***************************************************************************** @@ -1291,36 +1243,26 @@ Remark: Handles the reception of the ROLLBACKREP signal. int NdbConnection::receiveTCROLLBACKREP( NdbApiSignal* aSignal) { - Uint64 tRecTransId, tCurrTransId; - Uint32 tTmp1, tTmp2; - - if (theStatus != Connected) { - return -1; - }//if -/***************************************************************************** + /**************************************************************************** Check that we are expecting signals from this transaction and that it doesn't belong to a transaction already completed. Simply ignore messages from other transactions. -******************************************************************************/ - tTmp1 = aSignal->readData(2); - tTmp2 = aSignal->readData(3); - tRecTransId = (Uint64)tTmp1 + ((Uint64)tTmp2 << 32); - tCurrTransId = this->getTransactionId(); - if (tCurrTransId != tRecTransId) { - return -1; - }//if - theError.code = aSignal->readData(4); // Override any previous errors + ****************************************************************************/ + if(checkState_TransId(aSignal->getDataPtr() + 1)){ + theError.code = aSignal->readData(4);// Override any previous errors -/**********************************************************************/ -/* A serious error has occured. This could be due to deadlock or */ -/* lack of resources or simply a programming error in NDB. This */ -/* transaction will be aborted. Actually it has already been */ -/* and we only need to report completion and return with the */ -/* error code to the application. */ -/**********************************************************************/ - theCompletionStatus = CompletedFailure; - theCommitStatus = Aborted; - return 0; + /**********************************************************************/ + /* A serious error has occured. This could be due to deadlock or */ + /* lack of resources or simply a programming error in NDB. This */ + /* transaction will be aborted. Actually it has already been */ + /* and we only need to report completion and return with the */ + /* error code to the application. */ + /**********************************************************************/ + theCompletionStatus = CompletedFailure; + theCommitStatus = Aborted; + return 0; + } + return -1; }//NdbConnection::receiveTCROLLBACKREP() /******************************************************************************* @@ -1334,47 +1276,38 @@ Remark: int NdbConnection::receiveTCKEYCONF(const TcKeyConf * keyConf, Uint32 aDataLength) { - Uint64 tRecTransId; - NdbOperation* tOp; - Uint32 tConditionFlag; - + NdbReceiver* tOp; const Uint32 tTemp = keyConf->confInfo; - const Uint32 tTmp1 = keyConf->transId1; - const Uint32 tTmp2 = keyConf->transId2; -/****************************************************************************** + /*************************************************************************** Check that we are expecting signals from this transaction and that it doesn't belong to a transaction already completed. Simply ignore messages from other transactions. -******************************************************************************/ - tRecTransId = (Uint64)tTmp1 + ((Uint64)tTmp2 << 32); + ***************************************************************************/ + if(checkState_TransId(&keyConf->transId1)){ - const Uint32 tNoOfOperations = TcKeyConf::getNoOfOperations(tTemp); - const Uint32 tCommitFlag = TcKeyConf::getCommitFlag(tTemp); - tConditionFlag = (Uint32)(((aDataLength - 5) >> 1) - tNoOfOperations); - tConditionFlag |= (Uint32)(tNoOfOperations > 10); - tConditionFlag |= (Uint32)(tNoOfOperations <= 0); - tConditionFlag |= (Uint32)(theTransactionId - tRecTransId); - tConditionFlag |= (Uint32)(theStatus - Connected); + const Uint32 tNoOfOperations = TcKeyConf::getNoOfOperations(tTemp); + const Uint32 tCommitFlag = TcKeyConf::getCommitFlag(tTemp); - if (tConditionFlag == 0) { const Uint32* tPtr = (Uint32 *)&keyConf->operations[0]; + Uint32 tNoComp = theNoOfOpCompleted; for (Uint32 i = 0; i < tNoOfOperations ; i++) { - tOp = theNdb->void2rec_op(theNdb->int2void(*tPtr)); + tOp = theNdb->void2rec(theNdb->int2void(*tPtr)); tPtr++; const Uint32 tAttrInfoLen = *tPtr; tPtr++; - if (tOp && tOp->checkMagicNumber() != -1) { - tOp->TCOPCONF(tAttrInfoLen); + if (tOp && tOp->checkMagicNumber()) { + tNoComp += tOp->execTCOPCONF(tAttrInfoLen); } else { return -1; }//if }//for - Uint32 tNoComp = theNoOfOpCompleted; Uint32 tNoSent = theNoOfOpSent; + theNoOfOpCompleted = tNoComp; Uint32 tGCI = keyConf->gci; if (tCommitFlag == 1) { theCommitStatus = Committed; theGlobalCheckpointId = tGCI; + theTransactionId++; } else if ((tNoComp >= tNoSent) && (theLastExecOpInList->theCommitIndicator == 1)){ /**********************************************************************/ @@ -1406,50 +1339,46 @@ Remark: Handles the reception of the TCKEY_FAILCONF signal. int NdbConnection::receiveTCKEY_FAILCONF(const TcKeyFailConf * failConf) { - Uint64 tRecTransId, tCurrTransId; - Uint32 tTmp1, tTmp2; NdbOperation* tOp; - if (theStatus != Connected) { - return -1; - }//if /* - Check that we are expecting signals from this transaction and that it - doesn't belong to a transaction already completed. Simply ignore - messages from other transactions. + Check that we are expecting signals from this transaction and that it + doesn't belong to a transaction already completed. Simply ignore + messages from other transactions. */ - tTmp1 = failConf->transId1; - tTmp2 = failConf->transId2; - tRecTransId = (Uint64)tTmp1 + ((Uint64)tTmp2 << 32); - tCurrTransId = this->getTransactionId(); - if (tCurrTransId != tRecTransId) { - return -1; - }//if - /* - A node failure of the TC node occured. The transaction has - been committed. - */ - theCommitStatus = Committed; - tOp = theFirstExecOpInList; - while (tOp != NULL) { + if(checkState_TransId(&failConf->transId1)){ /* - Check if the transaction expected read values... - If it did some of them might have gotten lost even if we succeeded - in committing the transaction. + A node failure of the TC node occured. The transaction has + been committed. */ - if (tOp->theAI_ElementLen != 0) { - theCompletionStatus = CompletedFailure; - setOperationErrorCodeAbort(4115); - break; - }//if - if (tOp->theCurrentRecAttr != NULL) { - theCompletionStatus = CompletedFailure; - setOperationErrorCodeAbort(4115); - break; - }//if - tOp = tOp->next(); - }//while - theReleaseOnClose = true; - return 0; + theCommitStatus = Committed; + tOp = theFirstExecOpInList; + while (tOp != NULL) { + /* + * Check if the transaction expected read values... + * If it did some of them might have gotten lost even if we succeeded + * in committing the transaction. + */ + switch(tOp->theOperationType){ + case UpdateRequest: + case InsertRequest: + case DeleteRequest: + case WriteRequest: + tOp = tOp->next(); + break; + case ReadRequest: + case ReadExclusive: + case OpenScanRequest: + case OpenRangeScanRequest: + theCompletionStatus = CompletedFailure; + setOperationErrorCodeAbort(4115); + tOp = NULL; + break; + }//if + }//while + theReleaseOnClose = true; + return 0; + } + return -1; }//NdbConnection::receiveTCKEY_FAILCONF() /************************************************************************* @@ -1464,101 +1393,75 @@ Remark: Handles the reception of the TCKEY_FAILREF signal. int NdbConnection::receiveTCKEY_FAILREF(NdbApiSignal* aSignal) { - Uint64 tRecTransId, tCurrTransId; - Uint32 tTmp1, tTmp2; - - if (theStatus != Connected) { - return -1; - }//if /* - Check that we are expecting signals from this transaction and - that it doesn't belong to a transaction already - completed. Simply ignore messages from other transactions. + Check that we are expecting signals from this transaction and + that it doesn't belong to a transaction already + completed. Simply ignore messages from other transactions. */ - tTmp1 = aSignal->readData(2); - tTmp2 = aSignal->readData(3); - tRecTransId = (Uint64)tTmp1 + ((Uint64)tTmp2 << 32); - tCurrTransId = this->getTransactionId(); - if (tCurrTransId != tRecTransId) { - return -1; - }//if - /* - We received an indication of that this transaction was aborted due to a - node failure. - */ - if (theSendStatus == sendTC_ROLLBACK) { + if(checkState_TransId(aSignal->getDataPtr()+1)){ /* - We were in the process of sending a rollback anyways. We will - report it as a success. + We received an indication of that this transaction was aborted due to a + node failure. */ - theCompletionStatus = CompletedSuccess; - } else { - theCompletionStatus = CompletedFailure; - theError.code = 4031; - }//if - theReleaseOnClose = true; - theCommitStatus = Aborted; - return 0; + if (theSendStatus == sendTC_ROLLBACK) { + /* + We were in the process of sending a rollback anyways. We will + report it as a success. + */ + theCompletionStatus = CompletedSuccess; + } else { + theCompletionStatus = CompletedFailure; + theError.code = 4031; + }//if + theReleaseOnClose = true; + theCommitStatus = Aborted; + return 0; + } + return -1; }//NdbConnection::receiveTCKEY_FAILREF() -/******************************************************************************* +/****************************************************************************** int receiveTCINDXCONF(NdbApiSignal* aSignal, Uint32 long_short_ind); Return Value: Return 0 : receiveTCINDXCONF was successful. Return -1: In all other case. Parameters: aSignal: The signal object pointer. Remark: -*******************************************************************************/ -int -NdbConnection::receiveTCINDXCONF(const TcIndxConf * indxConf, Uint32 aDataLength) -{ - Uint64 tRecTransId; - Uint32 tConditionFlag; - - const Uint32 tTemp = indxConf->confInfo; - const Uint32 tTmp1 = indxConf->transId1; - const Uint32 tTmp2 = indxConf->transId2; -/****************************************************************************** -Check that we are expecting signals from this transaction and that it -doesn't belong to a transaction already completed. Simply ignore messages -from other transactions. ******************************************************************************/ - tRecTransId = (Uint64)tTmp1 + ((Uint64)tTmp2 << 32); - - const Uint32 tNoOfOperations = TcIndxConf::getNoOfOperations(tTemp); - const Uint32 tCommitFlag = TcKeyConf::getCommitFlag(tTemp); - - tConditionFlag = (Uint32)(((aDataLength - 5) >> 1) - tNoOfOperations); - tConditionFlag |= (Uint32)(tNoOfOperations > 10); - tConditionFlag |= (Uint32)(tNoOfOperations <= 0); - tConditionFlag |= (Uint32)(theTransactionId - tRecTransId); - tConditionFlag |= (Uint32)(theStatus - Connected); - - if (tConditionFlag == 0) { +int +NdbConnection::receiveTCINDXCONF(const TcIndxConf * indxConf, + Uint32 aDataLength) +{ + if(checkState_TransId(&indxConf->transId1)){ + const Uint32 tTemp = indxConf->confInfo; + const Uint32 tNoOfOperations = TcIndxConf::getNoOfOperations(tTemp); + const Uint32 tCommitFlag = TcKeyConf::getCommitFlag(tTemp); + const Uint32* tPtr = (Uint32 *)&indxConf->operations[0]; + Uint32 tNoComp = theNoOfOpCompleted; for (Uint32 i = 0; i < tNoOfOperations ; i++) { - NdbIndexOperation* tOp = theNdb->void2rec_iop(theNdb->int2void(*tPtr)); + NdbReceiver* tOp = theNdb->void2rec(theNdb->int2void(*tPtr)); tPtr++; const Uint32 tAttrInfoLen = *tPtr; tPtr++; - if (tOp && tOp->checkMagicNumber() != -1) { - tOp->TCOPCONF(tAttrInfoLen); + if (tOp && tOp->checkMagicNumber()) { + tNoComp += tOp->execTCOPCONF(tAttrInfoLen); } else { return -1; }//if }//for - Uint32 tNoComp = theNoOfOpCompleted; Uint32 tNoSent = theNoOfOpSent; Uint32 tGCI = indxConf->gci; + theNoOfOpCompleted = tNoComp; if (tCommitFlag == 1) { theCommitStatus = Committed; theGlobalCheckpointId = tGCI; } else if ((tNoComp >= tNoSent) && (theLastExecOpInList->theCommitIndicator == 1)){ -/**********************************************************************/ -// We sent the transaction with Commit flag set and received a CONF with -// no Commit flag set. This is clearly an anomaly. -/**********************************************************************/ + /**********************************************************************/ + // We sent the transaction with Commit flag set and received a CONF with + // no Commit flag set. This is clearly an anomaly. + /**********************************************************************/ theError.code = 4011; theCompletionStatus = CompletedFailure; theCommitStatus = Aborted; @@ -1584,36 +1487,21 @@ Remark: Handles the reception of the TCINDXREF signal. int NdbConnection::receiveTCINDXREF( NdbApiSignal* aSignal) { - Uint64 tRecTransId, tCurrTransId; - Uint32 tTmp1, tTmp2; + if(checkState_TransId(aSignal->getDataPtr()+1)){ + theError.code = aSignal->readData(4); // Override any previous errors - if (theStatus != Connected) { - return -1; - }//if -/***************************************************************************** -Check that we are expecting signals from this transaction and that it doesn't -belong to a transaction already completed. Simply ignore messages from other -transactions. -******************************************************************************/ - tTmp1 = aSignal->readData(2); - tTmp2 = aSignal->readData(3); - tRecTransId = (Uint64)tTmp1 + ((Uint64)tTmp2 << 32); - tCurrTransId = this->getTransactionId(); - if (tCurrTransId != tRecTransId) { - return -1; - }//if - theError.code = aSignal->readData(4); // Override any previous errors - -/**********************************************************************/ -/* A serious error has occured. This could be due to deadlock or */ -/* lack of resources or simply a programming error in NDB. This */ -/* transaction will be aborted. Actually it has already been */ -/* and we only need to report completion and return with the */ -/* error code to the application. */ -/**********************************************************************/ - theCompletionStatus = CompletedFailure; - theCommitStatus = Aborted; - return 0; + /**********************************************************************/ + /* A serious error has occured. This could be due to deadlock or */ + /* lack of resources or simply a programming error in NDB. This */ + /* transaction will be aborted. Actually it has already been */ + /* and we only need to report completion and return with the */ + /* error code to the application. */ + /**********************************************************************/ + theCompletionStatus = CompletedFailure; + theCommitStatus = Aborted; + return 0; + } + return -1; }//NdbConnection::receiveTCINDXREF() /******************************************************************************* diff --git a/ndb/src/ndbapi/NdbConnectionScan.cpp b/ndb/src/ndbapi/NdbConnectionScan.cpp index 962acc0bdac..ea45f2b5a00 100644 --- a/ndb/src/ndbapi/NdbConnectionScan.cpp +++ b/ndb/src/ndbapi/NdbConnectionScan.cpp @@ -33,7 +33,6 @@ #include #include #include -#include "NdbScanReceiver.hpp" #include "NdbApiSignal.hpp" #include "TransporterFacade.hpp" #include "NdbUtil.hpp" @@ -49,299 +48,6 @@ #define WAITFOR_SCAN_TIMEOUT 120000 -/***************************************************************************** - * int executeScan(); - * - * 1. Check that the transaction is started and other important preconditions - * 2. Tell the kernel to start scanning by sending one SCAN_TABREQ, if - * parallelism is greater than 16 also send one SCAN_TABINFO for each - * additional 16 - * Define which attributes to scan in ATTRINFO, this signal also holds the - * interpreted program - * 3. Wait for the answer of the SCAN_TABREQ. This is either a SCAN_TABCONF if - * the scan was correctly defined and a SCAN_TABREF if the scan couldn't - * be started. - * 4. Check the result, if scan was not started return -1 - * - ****************************************************************************/ -int -NdbConnection::executeScan(){ - if (theTransactionIsStarted == true){ // Transaction already started. - setErrorCode(4600); - return -1; - } - if (theStatus != Connected) { // Lost connection - setErrorCode(4601); - return -1; - } - if (theScanningOp == NULL){ - setErrorCode(4602); // getNdbOperation must be called before executeScan - return -1; - } - TransporterFacade* tp = TransporterFacade::instance(); - theNoOfOpCompleted = 0; - theNoOfSCANTABCONFRecv = 0; - tp->lock_mutex(); - if (tp->get_node_alive(theDBnode) && - (tp->getNodeSequence(theDBnode) == theNodeSequence)) { - if (tp->check_send_size(theDBnode, get_send_size())) { - theTransactionIsStarted = true; - if (sendScanStart() == -1){ - tp->unlock_mutex(); - return -1; - }//if - theNdb->theWaiter.m_node = theDBnode; - theNdb->theWaiter.m_state = WAIT_SCAN; - int res = theNdb->receiveResponse(WAITFOR_SCAN_TIMEOUT); - if (res == 0) { - return 0; - } else { - if (res == -1) { - setErrorCode(4008); - } else if (res == -2) { - theTransactionIsStarted = false; - theReleaseOnClose = true; - setErrorCode(4028); - } else { - ndbout << "Impossible return from receiveResponse in executeScan"; - ndbout << endl; - abort(); - }//if - theCommitStatus = Aborted; - return -1; - }//if - } else { - TRACE_DEBUG("Start a scan with send buffer full attempted"); - setErrorCode(4022); - theCommitStatus = Aborted; - }//if - } else { - if (!(tp->get_node_stopping(theDBnode) && - (tp->getNodeSequence(theDBnode) == theNodeSequence))) { - TRACE_DEBUG("The node is hard dead when attempting to start a scan"); - setErrorCode(4029); - theReleaseOnClose = true; - } else { - TRACE_DEBUG("The node is stopping when attempting to start a scan"); - setErrorCode(4030); - }//if - theCommitStatus = Aborted; - }//if - tp->unlock_mutex(); - return -1; -} - -/****************************************************************************** - * int nextScanResult(); - * Remark: - * This method is used to distribute data received to the application. - * Iterate through the list and search for operations that haven't - * been distributed yet (status != Finished). - * If there are no more operations/records still waiting to be exececuted - * we have to send SCAN_NEXTREQ to fetch next set of records. - * - * TODO - This function should be able to return a value indicating if - * there are any more records already fetched from memory or if it has to - * ask the db for more. This would mean we could get better performance when - * takeOver is used wince we can take over all ops already fetched, put them - * in another trans and send them of to the db when there are no more records - * already fetched. Maybe use a new argument to the function for this -******************************************************************************/ -int -NdbConnection::nextScanResult(bool fetchAllowed){ - - if (theTransactionIsStarted != true){ // Transaction not started. - setErrorCode(4601); - return -1; - } - // Scan has finished ok but no operations recived = empty recordset. - if(theScanFinished == true){ - return 1; // No more records - } - if (theStatus != Connected){// Lost connection - setErrorCode(4601); - return -1; - } - // Something went wrong, probably we got a SCAN_TABREF earlier. - if (theCompletionStatus == CompletedFailure) { - return -1; - } - if (theNoOfOpCompleted == theNoOfOpFetched) { - // There are no more records cached in NdbApi - if (fetchAllowed == true){ - // Get some more records from db - - if (fetchNextScanResult() == -1){ - return -1; - } - if (theScanFinished == true) { // The scan has finished. - return 1; // 1 = No more records - } - if (theCompletionStatus == CompletedFailure) { - return -1; // Something went wrong, probably we got a SCAN_TABREF. - } - } else { - // There where no more cached records in NdbApi - // and we where not allowed to go to db and ask for - // more - return 2; - } - } - - // It's not allowed to come here without any cached records - if (theCurrentScanRec == NULL){ -#ifdef VM_TRACE - ndbout << "nextScanResult("<theWaiter.m_node = " <theWaiter.m_node<theWaiter.m_state = " << theNdb->theWaiter.m_state << endl; - abort(); -#endif - return -1; - } - - // Execute the saved signals for this operation. - NdbScanReceiver* tScanRec = theCurrentScanRec; - theScanningOp->theCurrRecAI_Len = 0; - theScanningOp->theCurrentRecAttr = theScanningOp->theFirstRecAttr; - if(tScanRec->executeSavedSignals() != 0) - return -1; - theNoOfOpCompleted++; - // Remember for next iteration and takeOverScanOp - thePreviousScanRec = tScanRec; - theCurrentScanRec = tScanRec->next(); - return 0; // 0 = There are more rows to be fetched. -} - -/****************************************************************************** - * int stopScan() - * Remark: By sending SCAN_NEXTREQ with data word 2 set to TRUE we - * abort the scan process. - *****************************************************************************/ -int -NdbConnection::stopScan() -{ - if(theScanFinished == true){ - return 0; - } - if (theCompletionStatus == CompletedFailure){ - return 0; - } - - if (theScanningOp == 0){ - return 0; - } - - theNoOfOpCompleted = 0; - theNoOfSCANTABCONFRecv = 0; - theScanningOp->prepareNextScanResult(); - return sendScanNext(1); -} - - -/******************************************************************** - * int sendScanStart() - * - * Send the signals reuired to define and start the scan - * 1. Send SCAN_TABREQ - * 2. Send SCAN_TABINFO(if any, parallelism must be > 16) - * 3. Send ATTRINFO signals - * - * Returns -1 if an error occurs otherwise 0. - * - ********************************************************************/ -int -NdbConnection::sendScanStart(){ - - /***** 0. Prepare signals ******************/ - // This might modify variables and signals - if(theScanningOp->prepareSendScan(theTCConPtr, - theTransactionId) == -1) - return -1; - - /***** 1. Send SCAN_TABREQ **************/ - /***** 2. Send SCAN_TABINFO *************/ - /***** 3. Send ATTRINFO signals *********/ - if (theScanningOp->doSendScan(theDBnode) == -1) - return -1; - return 0; -} - - -int -NdbConnection::fetchNextScanResult(){ - theNoOfOpCompleted = 0; - theNoOfSCANTABCONFRecv = 0; - theScanningOp->prepareNextScanResult(); - return sendScanNext(0); -} - - - -/*********************************************************** - * int sendScanNext(int stopScanFlag) - * - * ************************************************************/ -int NdbConnection::sendScanNext(bool stopScanFlag){ - NdbApiSignal tSignal(theNdb->theMyRef); - Uint32 tTransId1, tTransId2; - tSignal.setSignal(GSN_SCAN_NEXTREQ); - tSignal.setData(theTCConPtr, 1); - // Set the stop flag in word 2(1 = stop) - Uint32 tStopValue; - tStopValue = stopScanFlag == true ? 1 : 0; - tSignal.setData(tStopValue, 2); - tTransId1 = (Uint32) theTransactionId; - tTransId2 = (Uint32) (theTransactionId >> 32); - tSignal.setData(tTransId1, 3); - tSignal.setData(tTransId2, 4); - tSignal.setLength(4); - Uint32 conn_seq = theNodeSequence; - int return_code = theNdb->sendRecSignal(theDBnode, - WAIT_SCAN, - &tSignal, - conn_seq); - if (return_code == 0) { - return 0; - } else if (return_code == -1) { // Time-out - TRACE_DEBUG("Time-out when sending sendScanNext"); - setErrorCode(4024); - theTransactionIsStarted = false; - theReleaseOnClose = true; - theCommitStatus = Aborted; - } else if (return_code == -2) { // Node failed - TRACE_DEBUG("Node failed when sendScanNext"); - setErrorCode(4027); - theTransactionIsStarted = false; - theReleaseOnClose = true; - theCommitStatus = Aborted; - } else if (return_code == -3) { - TRACE_DEBUG("Send failed when sendScanNext"); - setErrorCode(4033); - theTransactionIsStarted = false; - theReleaseOnClose = true; - theCommitStatus = Aborted; - } else if (return_code == -4) { - TRACE_DEBUG("Send buffer full when sendScanNext"); - setErrorCode(4032); - } else if (return_code == -5) { - TRACE_DEBUG("Node stopping when sendScanNext"); - setErrorCode(4034); - } else { - ndbout << "Impossible return from sendRecSignal" << endl; - abort(); - }//if - return -1; -} - /*************************************************************************** * int receiveSCAN_TABREF(NdbApiSignal* aSignal) @@ -352,39 +58,13 @@ int NdbConnection::sendScanNext(bool stopScanFlag){ ****************************************************************************/ int NdbConnection::receiveSCAN_TABREF(NdbApiSignal* aSignal){ - const ScanTabRef * const scanTabRef = CAST_CONSTPTR(ScanTabRef, aSignal->getDataPtr()); - if (theStatus != Connected){ -#ifdef VM_TRACE - ndbout << "SCAN_TABREF dropped, theStatus = " << theStatus << endl; -#endif - return -1; + const ScanTabRef * ref = CAST_CONSTPTR(ScanTabRef, aSignal->getDataPtr()); + + if(checkState_TransId(&ref->transId1)){ + theScanningOp->execCLOSE_SCAN_REP(ref->errorCode); + return 0; } - if (aSignal->getLength() != ScanTabRef::SignalLength){ -#ifdef VM_TRACE - ndbout << "SCAN_TABREF dropped, signal length " << aSignal->getLength() << endl; -#endif - return -1; - } - const Uint64 tCurrTransId = this->getTransactionId(); - const Uint64 tRecTransId = (Uint64)scanTabRef->transId1 + - ((Uint64)scanTabRef->transId2 << 32); - if ((tRecTransId - tCurrTransId) != (Uint64)0){ -#ifdef VM_TRACE - ndbout << "SCAN_TABREF dropped, wrong transid" << endl; -#endif - return -1; - } -#if 0 - ndbout << "SCAN_TABREF, " - <<"transid=("<transId1<<", "<transId2<<")" - <<", err="<errorCode << endl; -#endif - setErrorCode(scanTabRef->errorCode); - theCompletionStatus = CompletedFailure; - theCommitStatus = Aborted; // Indicate that this "transaction" was aborted - theTransactionIsStarted = false; - theScanningOp->releaseSignals(); - return 0; + return -1; } /***************************************************************************** @@ -401,173 +81,43 @@ NdbConnection::receiveSCAN_TABREF(NdbApiSignal* aSignal){ * *****************************************************************************/ int -NdbConnection::receiveSCAN_TABCONF(NdbApiSignal* aSignal) +NdbConnection::receiveSCAN_TABCONF(NdbApiSignal* aSignal, + const Uint32 * ops, Uint32 len) { - const ScanTabConf * const conf = CAST_CONSTPTR(ScanTabConf, aSignal->getDataPtr()); - if (theStatus != Connected){ -#ifdef VM_TRACE - ndbout << "Dropping SCAN_TABCONF, theStatus = "<< theStatus << endl; -#endif - return -1; - } - if(aSignal->getLength() != ScanTabConf::SignalLength){ -#ifdef VM_TRACE - ndbout << "Dropping SCAN_TABCONF, getLength = "<< aSignal->getLength() << endl; -#endif - return -1; - } - const Uint64 tCurrTransId = this->getTransactionId(); - const Uint64 tRecTransId = - (Uint64)conf->transId1 + ((Uint64)conf->transId2 << 32); - if ((tRecTransId - tCurrTransId) != (Uint64)0){ -#ifdef VM_TRACE - ndbout << "Dropping SCAN_TABCONF, wrong transid" << endl; -#endif - return -1; - } - - const Uint8 scanStatus = - ScanTabConf::getScanStatus(conf->requestInfo); - - if (scanStatus != 0) { - theCompletionStatus = CompletedSuccess; - theCommitStatus = Committed; - theScanFinished = true; - return 0; - } - - // There can only be one SCANTABCONF - assert(theNoOfSCANTABCONFRecv == 0); - theNoOfSCANTABCONFRecv++; - - // Save a copy of the signal - NdbApiSignal * tCopy = new NdbApiSignal(0);//getSignal(); - if (tCopy == NULL){ - setErrorCode(4000); - return 2; // theWaiter.m_state = NO_WAIT - } - tCopy->copyFrom(aSignal); - tCopy->next(NULL); - theScanningOp->theSCAN_TABCONF_Recv = tCopy; - - return checkNextScanResultComplete(); - -} - -/***************************************************************************** - * int receiveSCAN_TABINFO(NdbApiSignal* aSignal) - * - * Receive SCAN_TABINFO - * - *****************************************************************************/ -int -NdbConnection::receiveSCAN_TABINFO(NdbApiSignal* aSignal) -{ - if (theStatus != Connected){ - //ndbout << "SCAN_TABINFO dropped, theStatus = " << theStatus << endl; - return -1; - } - if (aSignal->getLength() != ScanTabInfo::SignalLength){ - //ndbout << "SCAN_TABINFO dropped, length = " << aSignal->getLength() << endl; - return -1; - } - - NdbApiSignal * tCopy = new NdbApiSignal(0);//getSignal(); - if (tCopy == NULL){ - setErrorCode(4000); - return 2; // theWaiter.m_state = NO_WAIT - } - tCopy->copyFrom(aSignal); - tCopy->next(NULL); - - // Put the signal last in list - if (theScanningOp->theFirstSCAN_TABINFO_Recv == NULL) - theScanningOp->theFirstSCAN_TABINFO_Recv = tCopy; - else - theScanningOp->theLastSCAN_TABINFO_Recv->next(tCopy); - theScanningOp->theLastSCAN_TABINFO_Recv = tCopy; - - return checkNextScanResultComplete(); -} - -/****************************************************************************** - * int checkNextScanResultComplete(NdbApiSignal* aSignal) - * - * Remark Traverses all the lists that are associated with - * this resultset and checks if all signals are there. - * If all required signal are received return 0 - * - * - *****************************************************************************/ -int -NdbConnection::checkNextScanResultComplete(){ - - if (theNoOfSCANTABCONFRecv != 1) { - return -1; - } - - Uint32 tNoOfOpFetched = 0; - theCurrentScanRec = NULL; - thePreviousScanRec = NULL; - - const ScanTabConf * const conf = - CAST_CONSTPTR(ScanTabConf, theScanningOp->theSCAN_TABCONF_Recv->getDataPtr()); - const Uint32 numOperations = ScanTabConf::getOperations(conf->requestInfo); - Uint32 sigIndex = 0; - NdbApiSignal* tSignal = theScanningOp->theFirstSCAN_TABINFO_Recv; - while(tSignal != NULL){ - const ScanTabInfo * const info = CAST_CONSTPTR(ScanTabInfo, tSignal->getDataPtr()); - // Loop through the operations for this SCAN_TABINFO - // tOpAndLength is allowed to be zero, this means no - // TRANSID_AI signals where sent for this record - // I.e getValue was called 0 times when defining scan - - // The max number of operations in each signal is 16 - Uint32 numOpsInSig = numOperations - sigIndex*16; - if (numOpsInSig > 16) - numOpsInSig = 16; - for(Uint32 i = 0; i < numOpsInSig; i++){ - const Uint32 tOpAndLength = info->operLenAndIdx[i]; - const Uint32 tOpIndex = ScanTabInfo::getIdx(tOpAndLength); - const Uint32 tOpLen = ScanTabInfo::getLen(tOpAndLength); - - assert(tOpIndex < 256); - NdbScanReceiver* tScanRec = - theScanningOp->theScanReceiversArray[tOpIndex]; - assert(tScanRec != NULL); - if(tScanRec->isCompleted(tOpLen)) - tScanRec->setCompleted(); - else{ - return -1; // At least one receiver was not ready - } - - // Build list of scan receivers - if (theCurrentScanRec == NULL) { - theCurrentScanRec = tScanRec; - thePreviousScanRec = tScanRec; - } else { - thePreviousScanRec->next(tScanRec); - thePreviousScanRec = tScanRec; - } - tNoOfOpFetched++; + const ScanTabConf * conf = CAST_CONSTPTR(ScanTabConf, aSignal->getDataPtr()); + if(checkState_TransId(&conf->transId1)){ + + if (conf->requestInfo == ScanTabConf::EndOfData) { + theScanningOp->execCLOSE_SCAN_REP(0); + return 0; } - tSignal = tSignal->next(); - sigIndex++; - } - - // Check number of operations fetched against value in SCANTAB_CONF - if (tNoOfOpFetched != numOperations) { - setErrorCode(4113); - return 2; // theWaiter.m_state = NO_WAIT + + int noComp = -1; + for(Uint32 i = 0; iint2void(ptrI); + assert(tPtr); // For now + NdbReceiver* tOp = theNdb->void2rec(tPtr); + if (tOp && tOp->checkMagicNumber()){ + if(tOp->execSCANOPCONF(tcPtrI, totalLen, opCount)){ + /** + * + */ + noComp++; + theScanningOp->receiver_delivered(tOp); + } else if(info == ScanTabConf::EndOfData){ + noComp++; + theScanningOp->receiver_completed(tOp); + } + } + } + return noComp; } - // All signals for this resultset recieved - // release SCAN_TAB signals - theNoOfSCANTABCONFRecv = 0; - theScanningOp->releaseSignals(); - - // We have received all operations with correct lengths. - thePreviousScanRec = NULL; - theNoOfOpFetched = tNoOfOpFetched; - return 0; + return -1; } diff --git a/ndb/src/ndbapi/NdbCursorOperation.cpp b/ndb/src/ndbapi/NdbCursorOperation.cpp index e4dd600c57f..a9f84c4c110 100644 --- a/ndb/src/ndbapi/NdbCursorOperation.cpp +++ b/ndb/src/ndbapi/NdbCursorOperation.cpp @@ -30,8 +30,6 @@ #include NdbCursorOperation::NdbCursorOperation(Ndb* aNdb) : - NdbOperation(aNdb), - m_resultSet(0) { } @@ -48,10 +46,6 @@ void NdbCursorOperation::cursInit() NdbResultSet* NdbCursorOperation::getResultSet() { - if (!m_resultSet) - m_resultSet = new NdbResultSet(this); - - return m_resultSet; } diff --git a/ndb/src/ndbapi/NdbDictionaryImpl.cpp b/ndb/src/ndbapi/NdbDictionaryImpl.cpp index 89c4fb19399..0478bed3237 100644 --- a/ndb/src/ndbapi/NdbDictionaryImpl.cpp +++ b/ndb/src/ndbapi/NdbDictionaryImpl.cpp @@ -258,6 +258,7 @@ NdbTableImpl::init(){ m_indexType = NdbDictionary::Index::Undefined; m_noOfKeys = 0; + m_fragmentCount = 0; } bool @@ -276,11 +277,9 @@ NdbTableImpl::equal(const NdbTableImpl& obj) const if(strcmp(m_internalName.c_str(), obj.m_internalName.c_str()) != 0){ return false; } - if(m_fragmentType != obj.m_fragmentType){ return false; } - if(m_columns.size() != obj.m_columns.size()){ return false; } @@ -319,6 +318,7 @@ NdbTableImpl::assign(const NdbTableImpl& org) m_newExternalName.assign(org.m_newExternalName); m_frm.assign(org.m_frm.get_data(), org.m_frm.length()); m_fragmentType = org.m_fragmentType; + m_fragmentCount = org.m_fragmentCount; for(unsigned i = 0; iunlock_mutex(); // End of Protected area if(m_waiter.m_state == NO_WAIT && m_error.code == 0){ @@ -1116,6 +1117,7 @@ NdbDictInterface::parseTableInfo(NdbTableImpl ** ret, impl->m_kvalue = tableDesc.TableKValue; impl->m_minLoadFactor = tableDesc.MinLoadFactor; impl->m_maxLoadFactor = tableDesc.MaxLoadFactor; + impl->m_fragmentCount = tableDesc.FragmentCount; impl->m_indexType = (NdbDictionary::Index::Type) getApiConstant(tableDesc.TableType, @@ -1199,6 +1201,8 @@ NdbDictInterface::parseTableInfo(NdbTableImpl ** ret, it.next(); } impl->m_noOfKeys = keyCount; + impl->m_keyLenInWords = keyInfoPos; + * ret = impl; return 0; } @@ -2708,6 +2712,7 @@ NdbDictInterface::listObjects(NdbApiSignal* signal) m_waiter.m_node = aNodeId; m_waiter.m_state = WAIT_LIST_TABLES_CONF; m_waiter.wait(WAITFOR_RESPONSE_TIMEOUT); + m_transporter->unlock_mutex(); // end protected if (m_waiter.m_state == NO_WAIT && m_error.code == 0) return 0; diff --git a/ndb/src/ndbapi/NdbDictionaryImpl.hpp b/ndb/src/ndbapi/NdbDictionaryImpl.hpp index 3263a636a79..311d101f8f4 100644 --- a/ndb/src/ndbapi/NdbDictionaryImpl.hpp +++ b/ndb/src/ndbapi/NdbDictionaryImpl.hpp @@ -123,7 +123,9 @@ public: int m_kvalue; int m_minLoadFactor; int m_maxLoadFactor; - + int m_keyLenInWords; + int m_fragmentCount; + NdbDictionaryImpl * m_dictionary; NdbIndexImpl * m_index; NdbColumnImpl * getColumn(unsigned attrId); diff --git a/ndb/src/ndbapi/NdbEventOperationImpl.cpp b/ndb/src/ndbapi/NdbEventOperationImpl.cpp index acc726e28c5..efac193746c 100644 --- a/ndb/src/ndbapi/NdbEventOperationImpl.cpp +++ b/ndb/src/ndbapi/NdbEventOperationImpl.cpp @@ -167,7 +167,7 @@ NdbEventOperationImpl::getValue(const NdbColumnImpl *tAttrInfo, char *aValue, in } //theErrorLine++; - tRecAttr->setUNDEFINED(); + tRecAttr->setNULL(); // We want to keep the list sorted to make data insertion easier later if (theFirstRecAttr == NULL) { @@ -388,7 +388,7 @@ NdbEventOperationImpl::next(int *pOverrun) while (tAttrId > tRecAttrId) { //printf("[%u] %u %u [%u]\n", tAttrId, tDataSz, *aDataPtr, tRecAttrId); - tWorkingRecAttr->setUNDEFINED(); + tWorkingRecAttr->setNULL(); tWorkingRecAttr = tWorkingRecAttr->next(); if (tWorkingRecAttr == NULL) break; @@ -400,19 +400,16 @@ NdbEventOperationImpl::next(int *pOverrun) //printf("[%u] %u %u [%u]\n", tAttrId, tDataSz, *aDataPtr, tRecAttrId); if (tAttrId == tRecAttrId) { - tWorkingRecAttr->setNotNULL(); if (!m_eventImpl->m_tableImpl->getColumn(tRecAttrId)->getPrimaryKey()) hasSomeData++; //printf("set!\n"); - Uint32 *theRef = (Uint32*)tWorkingRecAttr->aRef(); - Uint32 *theEndRef = theRef + tDataSz; - while (theRef < theEndRef) - *theRef++ = *aDataPtr++; + tWorkingRecAttr->receive_data(aDataPtr, tDataSz); // move forward, data has already moved forward aAttrPtr++; + aDataPtr += tDataSz; tWorkingRecAttr = tWorkingRecAttr->next(); } else { // move only attr forward @@ -424,7 +421,7 @@ NdbEventOperationImpl::next(int *pOverrun) while (tWorkingRecAttr != NULL) { tRecAttrId = tWorkingRecAttr->attrId(); //printf("set undefined [%u] %u %u [%u]\n", tAttrId, tDataSz, *aDataPtr, tRecAttrId); - tWorkingRecAttr->setUNDEFINED(); + tWorkingRecAttr->setNULL(); tWorkingRecAttr = tWorkingRecAttr->next(); } @@ -437,7 +434,7 @@ NdbEventOperationImpl::next(int *pOverrun) tDataSz = AttributeHeader(*aDataPtr).getDataSize(); aDataPtr++; while (tAttrId > tRecAttrId) { - tWorkingRecAttr->setUNDEFINED(); + tWorkingRecAttr->setNULL(); tWorkingRecAttr = tWorkingRecAttr->next(); if (tWorkingRecAttr == NULL) break; @@ -446,16 +443,11 @@ NdbEventOperationImpl::next(int *pOverrun) if (tWorkingRecAttr == NULL) break; if (tAttrId == tRecAttrId) { - tWorkingRecAttr->setNotNULL(); - if (!m_eventImpl->m_tableImpl->getColumn(tRecAttrId)->getPrimaryKey()) hasSomeData++; - Uint32 *theRef = (Uint32*)tWorkingRecAttr->aRef(); - Uint32 *theEndRef = theRef + tDataSz; - while (theRef < theEndRef) - *theRef++ = *aDataPtr++; - + tWorkingRecAttr->receive_data(aDataPtr, tDataSz); + aDataPtr += tDataSz; // move forward, data+attr has already moved forward tWorkingRecAttr = tWorkingRecAttr->next(); } else { @@ -464,7 +456,7 @@ NdbEventOperationImpl::next(int *pOverrun) } } while (tWorkingRecAttr != NULL) { - tWorkingRecAttr->setUNDEFINED(); + tWorkingRecAttr->setNULL(); tWorkingRecAttr = tWorkingRecAttr->next(); } diff --git a/ndb/src/ndbapi/NdbImpl.hpp b/ndb/src/ndbapi/NdbImpl.hpp index cd05335b337..1fb1969b589 100644 --- a/ndb/src/ndbapi/NdbImpl.hpp +++ b/ndb/src/ndbapi/NdbImpl.hpp @@ -35,6 +35,7 @@ public: #include #include #include +#include #include @@ -83,12 +84,13 @@ Ndb::void2rec_iop(void* val){ return (NdbIndexOperation*)(void2rec(val)->getOwner()); } -inline -NdbScanReceiver* -Ndb::void2rec_srec(void* val){ - return (NdbScanReceiver*)(void2rec(val)->getOwner()); +inline +NdbConnection * +NdbReceiver::getTransaction(){ + return ((NdbOperation*)m_owner)->theNdbCon; } + inline int Ndb::checkInitState() @@ -151,7 +153,6 @@ NdbWaiter::wait(int waitTime) waitTime = maxTime - NdbTick_CurrentMillisecond(); } } - NdbMutex_Unlock((NdbMutex*)m_mutex); } inline diff --git a/ndb/src/ndbapi/NdbIndexOperation.cpp b/ndb/src/ndbapi/NdbIndexOperation.cpp index ee5491d72a8..5bab52e0e0f 100644 --- a/ndb/src/ndbapi/NdbIndexOperation.cpp +++ b/ndb/src/ndbapi/NdbIndexOperation.cpp @@ -52,7 +52,7 @@ NdbIndexOperation::NdbIndexOperation(Ndb* aNdb) : /** * Change receiver type */ - theReceiver.init(NdbReceiver::NDB_INDEX_OPERATION, this); + theReceiver.init(NdbReceiver::NDB_INDEX_OPERATION, this, false); } NdbIndexOperation::~NdbIndexOperation() @@ -664,10 +664,8 @@ NdbIndexOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64 aTransactionId) tSignal = tnextSignal; } while (tSignal != NULL); }//if - NdbRecAttr* tRecAttrObject = theFirstRecAttr; theStatus = WaitResponse; - theCurrentRecAttr = tRecAttrObject; - + theReceiver.prepareSend(); return 0; } diff --git a/ndb/src/ndbapi/NdbOperation.cpp b/ndb/src/ndbapi/NdbOperation.cpp index ccbfa767542..1e1448bdf9a 100644 --- a/ndb/src/ndbapi/NdbOperation.cpp +++ b/ndb/src/ndbapi/NdbOperation.cpp @@ -54,7 +54,6 @@ NdbOperation::NdbOperation(Ndb* aNdb) : //theTable(aTable), theNdbCon(NULL), theNext(NULL), - theNextScanOp(NULL), theTCREQ(NULL), theFirstATTRINFO(NULL), theCurrentATTRINFO(NULL), @@ -62,8 +61,6 @@ NdbOperation::NdbOperation(Ndb* aNdb) : theAI_LenInCurrAI(0), theFirstKEYINFO(NULL), theLastKEYINFO(NULL), - theFirstRecAttr(NULL), - theCurrentRecAttr(NULL), theFirstLabel(NULL), theLastLabel(NULL), @@ -76,10 +73,6 @@ NdbOperation::NdbOperation(Ndb* aNdb) : theNoOfLabels(0), theNoOfSubroutines(0), - theTotalRecAI_Len(0), - theCurrRecAI_Len(0), - theAI_ElementLen(0), - theCurrElemPtr(NULL), m_currentTable(NULL), //theTableId(0xFFFF), m_accessTable(NULL), //theAccessTableId(0xFFFF), //theSchemaVersion(0), @@ -95,17 +88,9 @@ NdbOperation::NdbOperation(Ndb* aNdb) : m_tcReqGSN(GSN_TCKEYREQ), m_keyInfoGSN(GSN_KEYINFO), m_attrInfoGSN(GSN_ATTRINFO), - theParallelism(0), - theScanReceiversArray(NULL), - theSCAN_TABREQ(NULL), - theFirstSCAN_TABINFO_Send(NULL), - theLastSCAN_TABINFO_Send(NULL), - theFirstSCAN_TABINFO_Recv(NULL), - theLastSCAN_TABINFO_Recv(NULL), - theSCAN_TABCONF_Recv(NULL), theBoundATTRINFO(NULL) { - theReceiver.init(NdbReceiver::NDB_OPERATION, this); + theReceiver.init(NdbReceiver::NDB_OPERATION, this, false); theError.code = 0; } /***************************************************************************** @@ -165,7 +150,7 @@ NdbOperation::init(NdbTableImpl* tab, NdbConnection* myConnection){ theNdbCon = myConnection; for (Uint32 i=0; iscanInfo = 0; theKEYINFOptr = &tcKeyReq->keyInfo[0]; theATTRINFOptr = &tcKeyReq->attrInfo[0]; + theReceiver.init(NdbReceiver::NDB_OPERATION, this, false); return 0; } @@ -226,8 +207,6 @@ NdbOperation::release() { NdbApiSignal* tSignal; NdbApiSignal* tSaveSignal; - NdbRecAttr* tRecAttr; - NdbRecAttr* tSaveRecAttr; NdbBranch* tBranch; NdbBranch* tSaveBranch; NdbLabel* tLabel; @@ -260,15 +239,6 @@ NdbOperation::release() } theFirstKEYINFO = NULL; theLastKEYINFO = NULL; - tRecAttr = theFirstRecAttr; - while (tRecAttr != NULL) - { - tSaveRecAttr = tRecAttr; - tRecAttr = tRecAttr->next(); - theNdb->releaseRecAttr(tSaveRecAttr); - } - theFirstRecAttr = NULL; - theCurrentRecAttr = NULL; if (theInterpretIndicator == 1) { tBranch = theFirstBranch; @@ -308,19 +278,18 @@ NdbOperation::release() } theBoundATTRINFO = NULL; } - releaseScan(); } NdbRecAttr* NdbOperation::getValue(const char* anAttrName, char* aValue) { - return getValue(m_currentTable->getColumn(anAttrName), aValue); + return getValue_impl(m_currentTable->getColumn(anAttrName), aValue); } NdbRecAttr* NdbOperation::getValue(Uint32 anAttrId, char* aValue) { - return getValue(m_currentTable->getColumn(anAttrId), aValue); + return getValue_impl(m_currentTable->getColumn(anAttrId), aValue); } int @@ -416,16 +385,4 @@ NdbOperation::write_attr(Uint32 anAttrId, Uint32 RegDest) return write_attr(m_currentTable->getColumn(anAttrId), RegDest); } -int -NdbOperation::setBound(const char* anAttrName, int type, const void* aValue, Uint32 len) -{ - return setBound(m_accessTable->getColumn(anAttrName), type, aValue, len); -} - -int -NdbOperation::setBound(Uint32 anAttrId, int type, const void* aValue, Uint32 len) -{ - return setBound(m_accessTable->getColumn(anAttrId), type, aValue, len); -} - diff --git a/ndb/src/ndbapi/NdbOperationDefine.cpp b/ndb/src/ndbapi/NdbOperationDefine.cpp index 18f8b79d12e..a54081ae6dc 100644 --- a/ndb/src/ndbapi/NdbOperationDefine.cpp +++ b/ndb/src/ndbapi/NdbOperationDefine.cpp @@ -35,6 +35,7 @@ #include "NdbUtil.hpp" #include "NdbOut.hpp" #include "NdbImpl.hpp" +#include #include @@ -262,30 +263,10 @@ NdbOperation::interpretedUpdateTuple() theStatus = OperationDefined; tNdbCon->theSimpleState = 0; theOperationType = UpdateRequest; - theInterpretIndicator = 1; theAI_LenInCurrAI = 25; theErrorLine = tErrorLine++; - theTotalCurrAI_Len = 5; - theSubroutineSize = 0; - theInitialReadSize = 0; - theInterpretedSize = 0; - theFinalUpdateSize = 0; - theFinalReadSize = 0; - - theFirstLabel = NULL; - theLastLabel = NULL; - theFirstBranch = NULL; - theLastBranch = NULL; - - theFirstCall = NULL; - theLastCall = NULL; - theFirstSubroutine = NULL; - theLastSubroutine = NULL; - - theNoOfLabels = 0; - theNoOfSubroutines = 0; - + initInterpreter(); return 0; } else { setErrorCode(4200); @@ -305,30 +286,11 @@ NdbOperation::interpretedDeleteTuple() theStatus = OperationDefined; tNdbCon->theSimpleState = 0; theOperationType = DeleteRequest; - theInterpretIndicator = 1; theErrorLine = tErrorLine++; theAI_LenInCurrAI = 25; - theTotalCurrAI_Len = 5; - theSubroutineSize = 0; - theInitialReadSize = 0; - theInterpretedSize = 0; - theFinalUpdateSize = 0; - theFinalReadSize = 0; - - theFirstLabel = NULL; - theLastLabel = NULL; - theFirstBranch = NULL; - theLastBranch = NULL; - - theFirstCall = NULL; - theLastCall = NULL; - theFirstSubroutine = NULL; - theLastSubroutine = NULL; - - theNoOfLabels = 0; - theNoOfSubroutines = 0; + initInterpreter(); return 0; } else { setErrorCode(4200); @@ -348,14 +310,14 @@ NdbOperation::interpretedDeleteTuple() * Remark: Define an attribute to retrieve in query. *****************************************************************************/ NdbRecAttr* -NdbOperation::getValue(const NdbColumnImpl* tAttrInfo, char* aValue) +NdbOperation::getValue_impl(const NdbColumnImpl* tAttrInfo, char* aValue) { NdbRecAttr* tRecAttr; if ((tAttrInfo != NULL) && (!tAttrInfo->m_indexOnly) && (theStatus != Init)){ if (theStatus == SetBound) { - saveBoundATTRINFO(); + ((NdbScanOperation*)this)->saveBoundATTRINFO(); theStatus = GetValue; } if (theStatus != GetValue) { @@ -387,33 +349,15 @@ NdbOperation::getValue(const NdbColumnImpl* tAttrInfo, char* aValue) // Insert Attribute Id into ATTRINFO part. /************************************************************************ - * Get a Receive Attribute object and link it into the operation object. - ************************************************************************/ - tRecAttr = theNdb->getRecAttr(); - if (tRecAttr != NULL) { - if (theFirstRecAttr == NULL) - theFirstRecAttr = tRecAttr; - else - theCurrentRecAttr->next(tRecAttr); - theCurrentRecAttr = tRecAttr; - tRecAttr->next(NULL); - - /********************************************************************** - * Now set the attribute identity and the pointer to the data in - * the RecAttr object - * Also set attribute size, array size and attribute type - ********************************************************************/ - if (tRecAttr->setup(tAttrInfo, aValue) == 0) { - theErrorLine++; - return tRecAttr; - } else { - setErrorCodeAbort(4000); - return NULL; - } - } else { + * Get a Receive Attribute object and link it into the operation object. + ***********************************************************************/ + if((tRecAttr = theReceiver.getValue(tAttrInfo, aValue)) != 0){ + theErrorLine++; + return tRecAttr; + } else { setErrorCodeAbort(4000); return NULL; - }//if getRecAttr failure + } } else { return NULL; }//if insertATTRINFO failure @@ -604,47 +548,6 @@ NdbOperation::setValue( const NdbColumnImpl* tAttrInfo, return 0; }//NdbOperation::setValue() -/* - * Define bound on index column in range scan. - */ -int -NdbOperation::setBound(const NdbColumnImpl* tAttrInfo, int type, const void* aValue, Uint32 len) -{ - if (theOperationType == OpenRangeScanRequest && - theStatus == SetBound && - (0 <= type && type <= 4) && - aValue != NULL && - len <= 8000) { - // bound type - insertATTRINFO(type); - // attribute header - Uint32 sizeInBytes = tAttrInfo->m_attrSize * tAttrInfo->m_arraySize; - if (len != sizeInBytes && (len != 0)) { - setErrorCodeAbort(4209); - return -1; - } - len = sizeInBytes; - Uint32 tIndexAttrId = tAttrInfo->m_attrId; - Uint32 sizeInWords = (len + 3) / 4; - AttributeHeader ah(tIndexAttrId, sizeInWords); - insertATTRINFO(ah.m_value); - // attribute data - if ((UintPtr(aValue) & 0x3) == 0 && (len & 0x3) == 0) - insertATTRINFOloop((const Uint32*)aValue, sizeInWords); - else { - Uint32 temp[2000]; - memcpy(temp, aValue, len); - while ((len & 0x3) != 0) - ((char*)temp)[len++] = 0; - insertATTRINFOloop(temp, sizeInWords); - } - return 0; - } else { - setErrorCodeAbort(4228); // XXX wrong code - return -1; - } -} - /**************************************************************************** * int insertATTRINFO( Uint32 aData ); * diff --git a/ndb/src/ndbapi/NdbOperationExec.cpp b/ndb/src/ndbapi/NdbOperationExec.cpp index b2a6f99880c..9ae4f9f3cbd 100644 --- a/ndb/src/ndbapi/NdbOperationExec.cpp +++ b/ndb/src/ndbapi/NdbOperationExec.cpp @@ -46,83 +46,6 @@ Documentation: #include -/****************************************************************************** -int doSend() - -Return Value: Return >0 : send was succesful, returns number of signals sent - Return -1: In all other case. -Parameters: aProcessorId: Receiving processor node -Remark: Sends the ATTRINFO signal(s) -******************************************************************************/ -int -NdbOperation::doSendScan(int aProcessorId) -{ - Uint32 tSignalCount = 0; - NdbApiSignal* tSignal; - - if (theInterpretIndicator != 1 || - (theOperationType != OpenScanRequest && - theOperationType != OpenRangeScanRequest)) { - setErrorCodeAbort(4005); - return -1; - } - - assert(theSCAN_TABREQ != NULL); - tSignal = theSCAN_TABREQ; - if (tSignal->setSignal(GSN_SCAN_TABREQ) == -1) { - setErrorCode(4001); - return -1; - } - // Update the "attribute info length in words" in SCAN_TABREQ before - // sending it. This could not be done in openScan because - // we created the ATTRINFO signals after the SCAN_TABREQ signal. - ScanTabReq * const scanTabReq = CAST_PTR(ScanTabReq, tSignal->getDataPtrSend()); - scanTabReq->attrLen = theTotalCurrAI_Len; - if (theOperationType == OpenRangeScanRequest) - scanTabReq->attrLen += theTotalBoundAI_Len; - TransporterFacade *tp = TransporterFacade::instance(); - if (tp->sendSignal(tSignal, aProcessorId) == -1) { - setErrorCode(4002); - return -1; - } - tSignalCount++; - - tSignal = theFirstSCAN_TABINFO_Send; - while (tSignal != NULL){ - if (tp->sendSignal(tSignal, aProcessorId)) { - setErrorCode(4002); - return -1; - } - tSignalCount++; - tSignal = tSignal->next(); - } - - if (theOperationType == OpenRangeScanRequest) { - // must have at least one signal since it contains attrLen for bounds - assert(theBoundATTRINFO != NULL); - tSignal = theBoundATTRINFO; - while (tSignal != NULL) { - if (tp->sendSignal(tSignal,aProcessorId) == -1){ - setErrorCode(4002); - return -1; - } - tSignalCount++; - tSignal = tSignal->next(); - } - } - - tSignal = theFirstATTRINFO; - while (tSignal != NULL) { - if (tp->sendSignal(tSignal,aProcessorId) == -1){ - setErrorCode(4002); - return -1; - } - tSignalCount++; - tSignal = tSignal->next(); - } - theStatus = WaitResponse; - return tSignalCount; -}//NdbOperation::doSendScan() void NdbOperation::setLastFlag(NdbApiSignal* signal, Uint32 lastFlag) @@ -177,62 +100,6 @@ NdbOperation::doSend(int aNodeId, Uint32 lastFlag) return tSignalCount; }//NdbOperation::doSend() -/*************************************************************************** -int prepareSendScan(Uint32 aTC_ConnectPtr, - Uint64 aTransactionId) - -Return Value: Return 0 : preparation of send was succesful. - Return -1: In all other case. -Parameters: aTC_ConnectPtr: the Connect pointer to TC. - aTransactionId: the Transaction identity of the transaction. -Remark: Puts the the final data into ATTRINFO signal(s) after this - we know the how many signal to send and their sizes -***************************************************************************/ -int NdbOperation::prepareSendScan(Uint32 aTC_ConnectPtr, - Uint64 aTransactionId){ - - if (theInterpretIndicator != 1 || - (theOperationType != OpenScanRequest && - theOperationType != OpenRangeScanRequest)) { - setErrorCodeAbort(4005); - return -1; - } - - if (theStatus == SetBound) { - saveBoundATTRINFO(); - theStatus = GetValue; - } - - theErrorLine = 0; - - // In preapareSendInterpreted we set the sizes (word 4-8) in the - // first ATTRINFO signal. - if (prepareSendInterpreted() == -1) - return -1; - - const Uint32 transId1 = (Uint32) (aTransactionId & 0xFFFFFFFF); - const Uint32 transId2 = (Uint32) (aTransactionId >> 32); - - if (theOperationType == OpenRangeScanRequest) { - NdbApiSignal* tSignal = theBoundATTRINFO; - do{ - tSignal->setData(aTC_ConnectPtr, 1); - tSignal->setData(transId1, 2); - tSignal->setData(transId2, 3); - tSignal = tSignal->next(); - } while (tSignal != NULL); - } - theCurrentATTRINFO->setLength(theAI_LenInCurrAI); - NdbApiSignal* tSignal = theFirstATTRINFO; - do{ - tSignal->setData(aTC_ConnectPtr, 1); - tSignal->setData(transId1, 2); - tSignal->setData(transId2, 3); - tSignal = tSignal->next(); - } while (tSignal != NULL); - return 0; -} - /*************************************************************************** int prepareSend(Uint32 aTC_ConnectPtr, Uint64 aTransactionId) @@ -457,6 +324,7 @@ NdbOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64 aTransId) theTCREQ->setLength(tcKeyReq->getAIInTcKeyReq(tReqInfo) + tAttrInfoIndex + TcKeyReq::StaticLength); + tAIDataPtr[0] = Tdata1; tAIDataPtr[1] = Tdata2; tAIDataPtr[2] = Tdata3; @@ -479,9 +347,8 @@ NdbOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64 aTransId) tSignal = tnextSignal; } while (tSignal != NULL); }//if - NdbRecAttr* tRecAttrObject = theFirstRecAttr; theStatus = WaitResponse; - theCurrentRecAttr = tRecAttrObject; + theReceiver.prepareSend(); return 0; }//NdbOperation::prepareSend() @@ -648,71 +515,10 @@ NdbOperation::prepareSendInterpreted() theFirstATTRINFO->setData(tFinalReadSize, 7); theFirstATTRINFO->setData(tSubroutineSize, 8); }//if + theReceiver.prepareSend(); return 0; }//NdbOperation::prepareSendInterpreted() -/*************************************************************************** -int TCOPCONF(int anAttrInfoLen) - -Return Value: Return 0 : send was succesful. - Return -1: In all other case. -Parameters: anAttrInfoLen: The length of the attribute information from TC. -Remark: Handles the reception of the TC[KEY/INDX]CONF signal. -***************************************************************************/ -void -NdbOperation::TCOPCONF(Uint32 anAttrInfoLen) -{ - Uint32 tCurrRecLen = theCurrRecAI_Len; - if (theStatus == WaitResponse) { - theTotalRecAI_Len = anAttrInfoLen; - if (anAttrInfoLen == tCurrRecLen) { - Uint32 tAI_ElemLen = theAI_ElementLen; - NdbRecAttr* tCurrRecAttr = theCurrentRecAttr; - theStatus = Finished; - - if ((tAI_ElemLen == 0) && - (tCurrRecAttr == NULL)) { - NdbRecAttr* tRecAttr = theFirstRecAttr; - while (tRecAttr != NULL) { - if (tRecAttr->copyoutRequired()) // copy to application buffer - tRecAttr->copyout(); - tRecAttr = tRecAttr->next(); - } - theNdbCon->OpCompleteSuccess(); - return; - } else if (tAI_ElemLen != 0) { - setErrorCode(4213); - theNdbCon->OpCompleteFailure(); - return; - } else { - setErrorCode(4214); - theNdbCon->OpCompleteFailure(); - return; - }//if - } else if (anAttrInfoLen > tCurrRecLen) { - return; - } else { - theStatus = Finished; - - if (theAI_ElementLen != 0) { - setErrorCode(4213); - theNdbCon->OpCompleteFailure(); - return; - }//if - if (theCurrentRecAttr != NULL) { - setErrorCode(4214); - theNdbCon->OpCompleteFailure(); - return; - }//if - theNdbCon->OpCompleteFailure(); - return; - }//if - } else { - setErrorCode(4004); - }//if - return; -}//NdbOperation::TCKEYOPCONF() - int NdbOperation::checkState_TransId(NdbApiSignal* aSignal) { @@ -777,188 +583,13 @@ NdbOperation::receiveTCKEYREF( NdbApiSignal* aSignal) }//NdbOperation::receiveTCKEYREF() -/*************************************************************************** -int receiveREAD_CONF( NdbApiSignal* aSignal) - -Return Value: Return 0 : send was succesful. - Return -1: In all other case. -Parameters: aSignal: the signal object that contains the READCONF signal from TUP. -Remark: Handles the reception of the READCONF signal. -***************************************************************************/ -int -NdbOperation::receiveREAD_CONF(const Uint32* aDataPtr, Uint32 aDataLength) -{ - Uint64 tRecTransId, tCurrTransId; - Uint32 tCondFlag = (Uint32)(theStatus - WaitResponse); - Uint32 tTotLen = aDataPtr[3]; - - tRecTransId = (Uint64)aDataPtr[1] + ((Uint64)aDataPtr[2] << 32); - tCurrTransId = theNdbCon->getTransactionId(); - tCondFlag |= (Uint32)((tRecTransId - tCurrTransId) != (Uint64)0); - tCondFlag |= (Uint32)(aDataLength < 4); - - if (tCondFlag == 0) { - theTotalRecAI_Len = tTotLen; - int tRetValue = receiveREAD_AI((Uint32*)&aDataPtr[4], (aDataLength - 4)); - if (theStatus == Finished) { - return tRetValue; - } else { - theStatus = Finished; - return theNdbCon->OpCompleteFailure(); - }//if - }//if -#ifdef NDB_NO_DROPPED_SIGNAL - abort(); -#endif - return -1; -}//NdbOperation::receiveREAD_CONF() - -/*************************************************************************** -int receiveTRANSID_AI( NdbApiSignal* aSignal) - -Return Value: Return 0 : send was succesful. - Return -1: In all other case. -Parameters: aSignal: the signal object that contains the TRANSID_AI signal. -Remark: Handles the reception of the TRANSID_AI signal. -***************************************************************************/ -int -NdbOperation::receiveTRANSID_AI(const Uint32* aDataPtr, Uint32 aDataLength) -{ - Uint64 tRecTransId, tCurrTransId; - Uint32 tCondFlag = (Uint32)(theStatus - WaitResponse); - - tRecTransId = (Uint64)aDataPtr[1] + ((Uint64)aDataPtr[2] << 32); - tCurrTransId = theNdbCon->getTransactionId(); - tCondFlag |= (Uint32)((tRecTransId - tCurrTransId) != (Uint64)0); - tCondFlag |= (Uint32)(aDataLength < 3); - - if (tCondFlag == 0) { - return receiveREAD_AI((Uint32*)&aDataPtr[3], (aDataLength - 3)); - }//if -#ifdef NDB_NO_DROPPED_SIGNAL - abort(); -#endif - return -1; -}//NdbOperation::receiveTRANSID_AI() - -/*************************************************************************** -int receiveREAD_AI( NdbApiSignal* aSignal, int aLength, int aStartPos) - -Return Value: Return 0 : send was succesoccurredful. - Return -1: In all other case. -Parameters: aSignal: the signal object that contains the LEN_ATTRINFO11 signal. - aLength: - aStartPos: -Remark: Handles the reception of the LEN_ATTRINFO11 signal. -***************************************************************************/ -int -NdbOperation::receiveREAD_AI(Uint32* aDataPtr, Uint32 aLength) -{ - - register Uint32 tAI_ElementLen = theAI_ElementLen; - register Uint32* tCurrElemPtr = theCurrElemPtr; - if (theError.code == 0) { - // If inconsistency error occurred we will still continue - // receiving signals since we need to know whether commit - // has occurred. - - register Uint32 tData; - for (register Uint32 i = 0; i < aLength ; i++, aDataPtr++) - { - // Code to receive Attribute Information - tData = *aDataPtr; - if (tAI_ElementLen != 0) { - tAI_ElementLen--; - *tCurrElemPtr = tData; - tCurrElemPtr++; - continue; - } else { - // Waiting for a new attribute element - NdbRecAttr* tWorkingRecAttr; - - tWorkingRecAttr = theCurrentRecAttr; - AttributeHeader ah(tData); - const Uint32 tAttrId = ah.getAttributeId(); - const Uint32 tAttrSize = ah.getDataSize(); - if ((tWorkingRecAttr != NULL) && - (tWorkingRecAttr->attrId() == tAttrId)) { - ; - } else { - setErrorCode(4211); - break; - }//if - theCurrentRecAttr = tWorkingRecAttr->next(); - NdbColumnImpl * col = m_currentTable->getColumn(tAttrId); - if (ah.isNULL()) { - // Return a Null value from the NDB to the attribute. - if(col != 0 && col->m_nullable) { - tWorkingRecAttr->setNULL(); - tAI_ElementLen = 0; - } else { - setErrorCode(4212); - break; - }//if - } else { - // Return a value from the NDB to the attribute. - tWorkingRecAttr->setNotNULL(); - const Uint32 sizeInBytes = col->m_attrSize * col->m_arraySize; - const Uint32 sizeInWords = (sizeInBytes + 3) / 4; - tAI_ElementLen = tAttrSize; - tCurrElemPtr = (Uint32*)tWorkingRecAttr->aRef(); - if (sizeInWords == tAttrSize){ - continue; - } else { - setErrorCode(4201); - break; - }//if - }//if - }//if - }//for - }//if - Uint32 tCurrRecLen = theCurrRecAI_Len; - Uint32 tTotRecLen = theTotalRecAI_Len; - theAI_ElementLen = tAI_ElementLen; - theCurrElemPtr = tCurrElemPtr; - tCurrRecLen = tCurrRecLen + aLength; - theCurrRecAI_Len = tCurrRecLen; // Update Current Received AI Length - if (tTotRecLen == tCurrRecLen){ // Operation completed - NdbRecAttr* tCurrRecAttr = theCurrentRecAttr; - theStatus = Finished; - - NdbConnection* tNdbCon = theNdbCon; - if ((tAI_ElementLen == 0) && - (tCurrRecAttr == NULL)) { - NdbRecAttr* tRecAttr = theFirstRecAttr; - while (tRecAttr != NULL) { - if (tRecAttr->copyoutRequired()) // copy to application buffer - tRecAttr->copyout(); - tRecAttr = tRecAttr->next(); - } - return tNdbCon->OpCompleteSuccess(); - } else if (tAI_ElementLen != 0) { - setErrorCode(4213); - return tNdbCon->OpCompleteFailure(); - } else { - setErrorCode(4214); - return tNdbCon->OpCompleteFailure(); - }//if - } - else if ((tCurrRecLen > tTotRecLen) && - (tTotRecLen > 0)) { /* == 0 if TCKEYCONF not yet received */ - setErrorCode(4215); - theStatus = Finished; - - return theNdbCon->OpCompleteFailure(); - }//if - return -1; // Continue waiting for more signals of this operation -}//NdbOperation::receiveREAD_AI() void NdbOperation::handleFailedAI_ElemLen() { - NdbRecAttr* tRecAttr = theFirstRecAttr; + NdbRecAttr* tRecAttr = theReceiver.theFirstRecAttr; while (tRecAttr != NULL) { - tRecAttr->setUNDEFINED(); + tRecAttr->setNULL(); tRecAttr = tRecAttr->next(); }//while }//NdbOperation::handleFailedAI_ElemLen() diff --git a/ndb/src/ndbapi/NdbOperationInt.cpp b/ndb/src/ndbapi/NdbOperationInt.cpp index be23a1c274c..dda4eded59c 100644 --- a/ndb/src/ndbapi/NdbOperationInt.cpp +++ b/ndb/src/ndbapi/NdbOperationInt.cpp @@ -34,6 +34,7 @@ Adjust: 991029 UABRONM First version. #include "AttrType.hpp" #include "NdbUtil.hpp" #include "Interpreter.hpp" +#include #ifdef VM_TRACE #include @@ -44,6 +45,31 @@ Adjust: 991029 UABRONM First version. #define INT_DEBUG(x) #endif +void +NdbOperation::initInterpreter(){ + theFirstLabel = NULL; + theLastLabel = NULL; + theFirstBranch = NULL; + theLastBranch = NULL; + + theFirstCall = NULL; + theLastCall = NULL; + theFirstSubroutine = NULL; + theLastSubroutine = NULL; + + theNoOfLabels = 0; + theNoOfSubroutines = 0; + + theSubroutineSize = 0; + theInitialReadSize = 0; + theInterpretedSize = 0; + theFinalUpdateSize = 0; + theFinalReadSize = 0; + theInterpretIndicator = 1; + + theTotalCurrAI_Len = 5; +} + int NdbOperation::incCheck(const NdbColumnImpl* tNdbColumnImpl) { @@ -192,7 +218,7 @@ NdbOperation::initial_interpreterCheck() { if ((theInterpretIndicator == 1)) { if (theStatus == SetBound) { - saveBoundATTRINFO(); + ((NdbScanOperation*)this)->saveBoundATTRINFO(); theStatus = GetValue; } if (theStatus == ExecInterpretedValue) { diff --git a/ndb/src/ndbapi/NdbOperationScan.cpp b/ndb/src/ndbapi/NdbOperationScan.cpp index df4f2421ec0..283eb591bdb 100644 --- a/ndb/src/ndbapi/NdbOperationScan.cpp +++ b/ndb/src/ndbapi/NdbOperationScan.cpp @@ -14,563 +14,3 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "NdbOperation.hpp" -#include "NdbScanReceiver.hpp" - -#include -#include -#include -#include - - -/****************************************************************************** - * int openScanRead(); - *****************************************************************************/ -int -NdbOperation::openScanRead(Uint32 aParallelism) -{ - aParallelism = checkParallelism(aParallelism); - - if ((theNdbCon->theCommitStatus != Started) && - (theStatus != Init) && - (aParallelism == 0)) { - setErrorCode(4200); - return -1; - } - return openScan(aParallelism, false, false, false); -} - -/**************************************************************************** - * int openScanExclusive(); - ****************************************************************************/ -int -NdbOperation::openScanExclusive(Uint32 aParallelism) -{ - aParallelism = checkParallelism(aParallelism); - - if ((theNdbCon->theCommitStatus != Started) && - (theStatus != Init) && - (aParallelism == 0)) { - setErrorCode(4200); - return -1; - } - return openScan(aParallelism, true, true, false); -} - -/****************************************************************************** - * int openScanReadHoldLock(); - *****************************************************************************/ -int -NdbOperation::openScanReadHoldLock(Uint32 aParallelism) -{ - aParallelism = checkParallelism(aParallelism); - - if ((theNdbCon->theCommitStatus != Started) && - (theStatus != Init) && - (aParallelism == 0)) { - setErrorCode(4200); - return -1; - } - return openScan(aParallelism, false, true, false); -} - -/****************************************************************************** - * int openScanReadCommitted(); - *****************************************************************************/ -int -NdbOperation::openScanReadCommitted(Uint32 aParallelism) -{ - aParallelism = checkParallelism(aParallelism); - - if ((theNdbCon->theCommitStatus != Started) && - (theStatus != Init) && - (aParallelism == 0)) { - setErrorCode(4200); - return -1; - } - return openScan(aParallelism, false, false, true); -} - -/**************************************************************************** - * int checkParallelism(); - * Remark If the parallelism is set wrong the number of scan-operations - * will not correspond to the number of TRANSID_AI signals returned - * from NDB and the result will be a crash, therefore - * we adjust it or return an error if the value is totally wrong. - ****************************************************************************/ -int -NdbOperation::checkParallelism(Uint32 aParallelism) -{ - if (aParallelism == 0) { - setErrorCodeAbort(4232); - return 0; - } - if (aParallelism > 16) { - if (aParallelism <= 240) { - - /** - * If tscanConcurrency > 16 it must be a multiple of 16 - */ - if (((aParallelism >> 4) << 4) < aParallelism) { - aParallelism = ((aParallelism >> 4) << 4) + 16; - }//if - - /*---------------------------------------------------------------*/ - /* We cannot have a parallelism > 16 per node */ - /*---------------------------------------------------------------*/ - if ((aParallelism / theNdb->theNoOfDBnodes) > 16) { - aParallelism = theNdb->theNoOfDBnodes * 16; - }//if - - } else { - setErrorCodeAbort(4232); - aParallelism = 0; - }//if - }//if - return aParallelism; -}//NdbOperation::checkParallelism() - -/********************************************************************** - * int openScan(); - *************************************************************************/ -int -NdbOperation::openScan(Uint32 aParallelism, - bool lockMode, bool lockHoldMode, bool readCommitted) -{ - aParallelism = checkParallelism(aParallelism); - if(aParallelism == 0){ - return 0; - } - NdbScanReceiver* tScanRec; - // It is only possible to call openScan if - // 1. this transcation don't already contain another scan operation - // 2. this transaction don't already contain other operations - // 3. theScanOp contains a NdbScanOperation - if (theNdbCon->theScanningOp != NULL){ - setErrorCode(4605); - return -1; - } - - if ((theNdbCon->theFirstOpInList != this) || - (theNdbCon->theLastOpInList != this)) { - setErrorCode(4603); - return -1; - } - theNdbCon->theScanningOp = this; - - initScan(); - theParallelism = aParallelism; - - // If the scan is on ordered index then it is a range scan - if (m_currentTable->m_indexType == NdbDictionary::Index::OrderedIndex || - m_currentTable->m_indexType == NdbDictionary::Index::UniqueOrderedIndex) { - assert(m_currentTable == m_accessTable); - m_currentTable = theNdb->theDictionary->getTable(m_currentTable->m_primaryTable.c_str()); - assert(m_currentTable != NULL); - // Modify operation state - theStatus = SetBound; - theOperationType = OpenRangeScanRequest; - } - - theScanReceiversArray = new NdbScanReceiver* [aParallelism]; - if (theScanReceiversArray == NULL){ - setErrorCodeAbort(4000); - return -1; - } - - for (Uint32 i = 0; i < aParallelism; i ++) { - tScanRec = theNdb->getNdbScanRec(); - if (tScanRec == NULL) { - setErrorCodeAbort(4000); - return -1; - }//if - tScanRec->init(this, lockMode); - theScanReceiversArray[i] = tScanRec; - } - - theSCAN_TABREQ = theNdb->getSignal(); - if (theSCAN_TABREQ == NULL) { - setErrorCodeAbort(4000); - return -1; - }//if - ScanTabReq * const scanTabReq = CAST_PTR(ScanTabReq, theSCAN_TABREQ->getDataPtrSend()); - scanTabReq->apiConnectPtr = theNdbCon->theTCConPtr; - scanTabReq->tableId = m_accessTable->m_tableId; - scanTabReq->tableSchemaVersion = m_accessTable->m_version; - scanTabReq->storedProcId = 0xFFFF; - scanTabReq->buddyConPtr = theNdbCon->theBuddyConPtr; - - Uint32 reqInfo = 0; - ScanTabReq::setParallelism(reqInfo, aParallelism); - ScanTabReq::setLockMode(reqInfo, lockMode); - ScanTabReq::setHoldLockFlag(reqInfo, lockHoldMode); - ScanTabReq::setReadCommittedFlag(reqInfo, readCommitted); - if (theOperationType == OpenRangeScanRequest) - ScanTabReq::setRangeScanFlag(reqInfo, true); - scanTabReq->requestInfo = reqInfo; - - Uint64 transId = theNdbCon->getTransactionId(); - scanTabReq->transId1 = (Uint32) transId; - scanTabReq->transId2 = (Uint32) (transId >> 32); - - for (Uint32 i = 0; i < 16 && i < aParallelism ; i++) { - scanTabReq->apiOperationPtr[i] = theScanReceiversArray[i]->ptr2int(); - }//for - - // Create one additional SCAN_TABINFO for each - // 16 of parallelism - NdbApiSignal* tSignal; - Uint32 tParallelism = aParallelism; - while (tParallelism > 16) { - tSignal = theNdb->getSignal(); - if (tSignal == NULL) { - setErrorCodeAbort(4000); - return -1; - }//if - if (tSignal->setSignal(GSN_SCAN_TABINFO) == -1) { - setErrorCode(4001); - return -1; - } - tSignal->next(theFirstSCAN_TABINFO_Send); - theFirstSCAN_TABINFO_Send = tSignal; - tParallelism -= 16; - }//while - - // Format all SCAN_TABINFO signals - tParallelism = 16; - tSignal = theFirstSCAN_TABINFO_Send; - while (tSignal != NULL) { - tSignal->setData(theNdbCon->theTCConPtr, 1); - for (int i = 0; i < 16 ; i++) { - tSignal->setData(theScanReceiversArray[i + tParallelism]->ptr2int(), i + 2); - }//for - tSignal = tSignal->next(); - tParallelism += 16; - }//while - - getFirstATTRINFOScan(); - return 0; -}//NdbScanOperation::openScan() - -/***************************************************************************** - * int getFirstATTRINFOScan( U_int32 aData ) - * - * Return Value: Return 0: Successful - * Return -1: All other cases - * Parameters: None: Only allocate the first signal. - * Remark: When a scan is defined we need to use this method instead - * of insertATTRINFO for the first signal. - * This is because we need not to mess up the code in - * insertATTRINFO with if statements since we are not - * interested in the TCKEYREQ signal. - *****************************************************************************/ -int -NdbOperation::getFirstATTRINFOScan() -{ - NdbApiSignal* tSignal; - - tSignal = theNdb->getSignal(); - if (tSignal == NULL){ - setErrorCodeAbort(4000); - return -1; - } - tSignal->setSignal(m_attrInfoGSN); - theAI_LenInCurrAI = 8; - theATTRINFOptr = &tSignal->getDataPtrSend()[8]; - theFirstATTRINFO = tSignal; - theCurrentATTRINFO = tSignal; - theCurrentATTRINFO->next(NULL); - return 0; -} - -/* - * After setBound() are done, move the accumulated ATTRINFO signals to - * a separate list. Then continue with normal scan. - */ -int -NdbOperation::saveBoundATTRINFO() -{ - theCurrentATTRINFO->setLength(theAI_LenInCurrAI); - theBoundATTRINFO = theFirstATTRINFO; - theTotalBoundAI_Len = theTotalCurrAI_Len; - theTotalCurrAI_Len = 5; - theBoundATTRINFO->setData(theTotalBoundAI_Len, 4); - theBoundATTRINFO->setData(0, 5); - theBoundATTRINFO->setData(0, 6); - theBoundATTRINFO->setData(0, 7); - theBoundATTRINFO->setData(0, 8); - theStatus = GetValue; - return getFirstATTRINFOScan(); -} - -/***************************************************************************** - * void releaseScan() - * - * Return Value No return value. - * Parameters: No parameters. - * Remark: Release objects after scanning. - *****************************************************************************/ -void -NdbOperation::releaseScan() -{ - NdbScanReceiver* tScanRec; - TransporterFacade::instance()->lock_mutex(); - for (Uint32 i = 0; i < theParallelism && theScanReceiversArray != NULL; i++) { - tScanRec = theScanReceiversArray[i]; - if (tScanRec != NULL) { - tScanRec->release(); - tScanRec->next(NULL); - } - } - TransporterFacade::instance()->unlock_mutex(); - releaseSignals(); - - if (theScanReceiversArray != NULL) { - for (Uint32 i = 0; i < theParallelism; i++) { - NdbScanReceiver* tScanRec; - tScanRec = theScanReceiversArray[i]; - if (tScanRec != NULL) { - theNdb->releaseNdbScanRec(tScanRec); - theScanReceiversArray[i] = NULL; - } - } - - delete [] theScanReceiversArray; - }//if - theScanReceiversArray = NULL; - - if (theSCAN_TABREQ != NULL){ - theNdb->releaseSignal(theSCAN_TABREQ); - theSCAN_TABREQ = NULL; - } -} - -void NdbOperation::releaseSignals(){ - theNdb->releaseSignalsInList(&theFirstSCAN_TABINFO_Send); - theFirstSCAN_TABINFO_Send = NULL; - theLastSCAN_TABINFO_Send = NULL; - // theNdb->releaseSignalsInList(&theFirstSCAN_TABINFO_Recv); - - while(theFirstSCAN_TABINFO_Recv != NULL){ - NdbApiSignal* tmp = theFirstSCAN_TABINFO_Recv; - theFirstSCAN_TABINFO_Recv = tmp->next(); - delete tmp; - } - theFirstSCAN_TABINFO_Recv = NULL; - theLastSCAN_TABINFO_Recv = NULL; - if (theSCAN_TABCONF_Recv != NULL){ - // theNdb->releaseSignal(theSCAN_TABCONF_Recv); - delete theSCAN_TABCONF_Recv; - theSCAN_TABCONF_Recv = NULL; - } -} - - -void NdbOperation::prepareNextScanResult(){ - NdbScanReceiver* tScanRec; - for (Uint32 i = 0; i < theParallelism; i++) { - tScanRec = theScanReceiversArray[i]; - assert(tScanRec != NULL); - tScanRec->prepareNextScanResult(); - tScanRec->next(NULL); - } - releaseSignals(); -} - -/****************************************************************************** - * void initScan(); - * - * Return Value: Return 0 : init was successful. - * Return -1: In all other case. - * Remark: Initiates operation record after allocation. - *****************************************************************************/ -void -NdbOperation::initScan() -{ - theTotalRecAI_Len = 0; - theCurrRecAI_Len = 0; - theStatus = GetValue; - theOperationType = OpenScanRequest; - theCurrentRecAttr = theFirstRecAttr; - theScanInfo = 0; - theMagicNumber = 0xABCDEF01; - theTotalCurrAI_Len = 5; - - theFirstLabel = NULL; - theLastLabel = NULL; - theFirstBranch = NULL; - theLastBranch = NULL; - - theFirstCall = NULL; - theLastCall = NULL; - theFirstSubroutine = NULL; - theLastSubroutine = NULL; - - theNoOfLabels = 0; - theNoOfSubroutines = 0; - - theSubroutineSize = 0; - theInitialReadSize = 0; - theInterpretedSize = 0; - theFinalUpdateSize = 0; - theFinalReadSize = 0; - theInterpretIndicator = 1; - - - theFirstSCAN_TABINFO_Send = NULL; - theLastSCAN_TABINFO_Send = NULL; - theFirstSCAN_TABINFO_Recv = NULL; - theLastSCAN_TABINFO_Recv = NULL; - theSCAN_TABCONF_Recv = NULL; - - theScanReceiversArray = NULL; - - theTotalBoundAI_Len = 0; - theBoundATTRINFO = NULL; - return; -} - -NdbOperation* NdbOperation::takeOverForDelete(NdbConnection* updateTrans){ - return takeOverScanOp(DeleteRequest, updateTrans); -} - -NdbOperation* NdbOperation::takeOverForUpdate(NdbConnection* updateTrans){ - return takeOverScanOp(UpdateRequest, updateTrans); -} -/****************************************************************************** - * NdbOperation* takeOverScanOp(NdbConnection* updateTrans); - * - * Parameters: The update transactions NdbConnection pointer. - * Return Value: A reference to the transferred operation object - * or NULL if no success. - * Remark: Take over the scanning transactions NdbOperation - * object for a tuple to an update transaction, - * which is the last operation read in nextScanResult() - * (theNdbCon->thePreviousScanRec) - * - * FUTURE IMPLEMENTATION: (This note was moved from header file.) - * In the future, it will even be possible to transfer - * to a NdbConnection on another Ndb-object. - * In this case the receiving NdbConnection-object must call - * a method receiveOpFromScan to actually receive the information. - * This means that the updating transactions can be placed - * in separate threads and thus increasing the parallelism during - * the scan process. - *****************************************************************************/ -NdbOperation* -NdbOperation::takeOverScanOp(OperationType opType, NdbConnection* updateTrans) -{ - if (opType != UpdateRequest && opType != DeleteRequest) { - setErrorCode(4604); - return NULL; - } - - const NdbScanReceiver* tScanRec = theNdbCon->thePreviousScanRec; - if (tScanRec == NULL){ - // No operation read by nextScanResult - setErrorCode(4609); - return NULL; - } - - if (tScanRec->theFirstKEYINFO20_Recv == NULL){ - // No KEYINFO20 received - setErrorCode(4608); - return NULL; - } - - NdbOperation * newOp = updateTrans->getNdbOperation(m_currentTable); - if (newOp == NULL){ - return NULL; - } - - /** - * Copy and caclulate attributes from the scanned operation to the - * new operation - */ - const KeyInfo20 * const firstKeyInfo20 = - CAST_CONSTPTR(KeyInfo20, tScanRec->theFirstKEYINFO20_Recv->getDataPtr()); - const Uint32 totalKeyLen = firstKeyInfo20->keyLen; - newOp->theTupKeyLen = totalKeyLen; - - newOp->theOperationType = opType; - if (opType == DeleteRequest) { - newOp->theStatus = GetValue; - } else { - newOp->theStatus = SetValue; - } - const Uint32 tScanInfo = firstKeyInfo20->scanInfo_Node & 0xFFFF; - const Uint32 tTakeOverNode = firstKeyInfo20->scanInfo_Node >> 16; - { - UintR scanInfo = 0; - TcKeyReq::setTakeOverScanFlag(scanInfo, 1); - TcKeyReq::setTakeOverScanNode(scanInfo, tTakeOverNode); - TcKeyReq::setTakeOverScanInfo(scanInfo, tScanInfo); - newOp->theScanInfo = scanInfo; - } - - /** - * Copy received KEYINFO20 signals into TCKEYREQ and KEYINFO signals - * put them in list of the new op - */ - TcKeyReq * const tcKeyReq = - CAST_PTR(TcKeyReq, newOp->theTCREQ->getDataPtrSend()); - - // Copy the first 8 words of key info from KEYINF20 into TCKEYREQ - for (Uint32 i = 0; i < TcKeyReq::MaxKeyInfo; i++) { - tcKeyReq->keyInfo[i] = firstKeyInfo20->keyData[i]; - } - if (totalKeyLen > TcKeyReq::MaxKeyInfo) { - - Uint32 keyWordsCopied = TcKeyReq::MaxKeyInfo; - - // Create KEYINFO signals in newOp - for (Uint32 i = keyWordsCopied; i < totalKeyLen; i += KeyInfo::DataLength){ - NdbApiSignal* tSignal = theNdb->getSignal(); - if (tSignal == NULL){ - setErrorCodeAbort(4000); - return NULL; - } - if (tSignal->setSignal(GSN_KEYINFO) == -1){ - setErrorCodeAbort(4001); - return NULL; - } - tSignal->next(newOp->theFirstKEYINFO); - newOp->theFirstKEYINFO = tSignal; - } - - // Init pointers to KEYINFO20 signal - NdbApiSignal* currKeyInfo20 = tScanRec->theFirstKEYINFO20_Recv; - const KeyInfo20 * keyInfo20 = - CAST_CONSTPTR(KeyInfo20, currKeyInfo20->getDataPtr()); - Uint32 posInKeyInfo20 = keyWordsCopied; - - // Init pointers to KEYINFO signal - NdbApiSignal* currKeyInfo = newOp->theFirstKEYINFO; - KeyInfo * keyInfo = CAST_PTR(KeyInfo, currKeyInfo->getDataPtrSend()); - Uint32 posInKeyInfo = 0; - - // Copy from KEYINFO20 to KEYINFO - while(keyWordsCopied < totalKeyLen){ - keyInfo->keyData[posInKeyInfo++] = keyInfo20->keyData[posInKeyInfo20++]; - keyWordsCopied++; - if(keyWordsCopied >= totalKeyLen) - break; - if (posInKeyInfo20 >= - (currKeyInfo20->getLength()-KeyInfo20::HeaderLength)){ - currKeyInfo20 = currKeyInfo20->next(); - keyInfo20 = CAST_CONSTPTR(KeyInfo20, currKeyInfo20->getDataPtr()); - posInKeyInfo20 = 0; - } - if (posInKeyInfo >= KeyInfo::DataLength){ - currKeyInfo = currKeyInfo->next(); - keyInfo = CAST_PTR(KeyInfo, currKeyInfo->getDataPtrSend()); - posInKeyInfo = 0; - } - } - } - - return newOp; -} - - - diff --git a/ndb/src/ndbapi/NdbRecAttr.cpp b/ndb/src/ndbapi/NdbRecAttr.cpp index 0f7baeac4f5..18ce59745d0 100644 --- a/ndb/src/ndbapi/NdbRecAttr.cpp +++ b/ndb/src/ndbapi/NdbRecAttr.cpp @@ -57,6 +57,8 @@ NdbRecAttr::setup(const NdbColumnImpl* anAttrInfo, char* aValue) theAttrSize = tAttrSize; theArraySize = tArraySize; theValue = aValue; + theNULLind = 0; + m_nullable = anAttrInfo->m_nullable; // check alignment to signal data // a future version could check alignment per data type as well @@ -124,3 +126,19 @@ NdbRecAttr::clone() const { memcpy(ret->theRef, theRef, n); return ret; } + +bool +NdbRecAttr::receive_data(const Uint32 * data, Uint32 sz){ + const Uint32 n = (theAttrSize * theArraySize + 3) >> 2; + if(n == sz){ + if(!copyoutRequired()) + memcpy(theRef, data, 4 * sz); + else + memcpy(theValue, data, theAttrSize * theArraySize); + return true; + } else if(sz == 0){ + setNULL(); + return true; + } + return false; +} diff --git a/ndb/src/ndbapi/NdbReceiver.cpp b/ndb/src/ndbapi/NdbReceiver.cpp index 4c461698a4a..7a538de3d7c 100644 --- a/ndb/src/ndbapi/NdbReceiver.cpp +++ b/ndb/src/ndbapi/NdbReceiver.cpp @@ -16,6 +16,10 @@ #include "NdbImpl.hpp" #include +#include "NdbDictionaryImpl.hpp" +#include +#include +#include NdbReceiver::NdbReceiver(Ndb *aNdb) : theMagicNumber(0), @@ -24,10 +28,11 @@ NdbReceiver::NdbReceiver(Ndb *aNdb) : m_type(NDB_UNINITIALIZED), m_owner(0) { + theCurrentRecAttr = theFirstRecAttr = 0; } void -NdbReceiver::init(ReceiverType type, void* owner) +NdbReceiver::init(ReceiverType type, void* owner, bool keyInfo) { theMagicNumber = 0x11223344; m_type = type; @@ -36,6 +41,24 @@ NdbReceiver::init(ReceiverType type, void* owner) if (m_ndb) m_id = m_ndb->theNdbObjectIdMap->map(this); } + + theFirstRecAttr = NULL; + theCurrentRecAttr = NULL; + m_key_info = (keyInfo ? 1 : 0); + m_defined_rows = 0; +} + +void +NdbReceiver::release(){ + NdbRecAttr* tRecAttr = theFirstRecAttr; + while (tRecAttr != NULL) + { + NdbRecAttr* tSaveRecAttr = tRecAttr; + tRecAttr = tRecAttr->next(); + m_ndb->releaseRecAttr(tSaveRecAttr); + } + theFirstRecAttr = NULL; + theCurrentRecAttr = NULL; } NdbReceiver::~NdbReceiver() @@ -44,3 +67,150 @@ NdbReceiver::~NdbReceiver() m_ndb->theNdbObjectIdMap->unmap(m_id, this); } } + +NdbRecAttr * +NdbReceiver::getValue(const NdbColumnImpl* tAttrInfo, char * user_dst_ptr){ + NdbRecAttr* tRecAttr = m_ndb->getRecAttr(); + if(tRecAttr && !tRecAttr->setup(tAttrInfo, user_dst_ptr)){ + if (theFirstRecAttr == NULL) + theFirstRecAttr = tRecAttr; + else + theCurrentRecAttr->next(tRecAttr); + theCurrentRecAttr = tRecAttr; + tRecAttr->next(NULL); + return tRecAttr; + } + if(tRecAttr){ + m_ndb->releaseRecAttr(tRecAttr); + } + return 0; +} + +#define KEY_ATTR_ID (~0) + +void +NdbReceiver::do_get_value(NdbReceiver * org, Uint32 rows, Uint32 key_size){ + m_defined_rows = rows; + m_rows = new NdbRecAttr*[rows + 1]; m_rows[rows] = 0; + + NdbColumnImpl key; + if(key_size){ + key.m_attrId = KEY_ATTR_ID; + key.m_arraySize = key_size+1; + key.m_attrSize = 4; + key.m_nullable = true; // So that receive works w.r.t KEYINFO20 + } + + for(Uint32 i = 0; itheFirstRecAttr; + while(tRecAttr != 0){ + if(getValue(&NdbColumnImpl::getImpl(*tRecAttr->m_column), (char*)0)) + tRecAttr = tRecAttr->next(); + else + break; + } + + if(tRecAttr){ + abort(); + return ;// -1; + } + + // Store first recAttr for each row in m_rows[i] + if(prev){ + m_rows[i] = prev->next(); + } else { + m_rows[i] = theFirstRecAttr; + } + } + + prepareSend(); + return ; //0; +} + +void +NdbReceiver::copyout(NdbReceiver & dstRec){ + NdbRecAttr* src = m_rows[m_current_row++]; + NdbRecAttr* dst = dstRec.theFirstRecAttr; + Uint32 tmp = m_key_info; + if(tmp > 0){ + src = src->next(); + } + + while(dst){ + Uint32 len = ((src->theAttrSize * src->theArraySize)+3)/4; + dst->receive_data((Uint32*)src->aRef(), len); + src = src->next(); + dst = dst->next(); + } +} + +int +NdbReceiver::execTRANSID_AI(const Uint32* aDataPtr, Uint32 aLength) +{ + bool ok = true; + NdbRecAttr* currRecAttr = theCurrentRecAttr; + NdbRecAttr* prevRecAttr = currRecAttr; + + for (Uint32 used = 0; used < aLength ; used++){ + AttributeHeader ah(* aDataPtr++); + const Uint32 tAttrId = ah.getAttributeId(); + const Uint32 tAttrSize = ah.getDataSize(); + + /** + * Set all results to NULL if not found... + */ + while(currRecAttr && currRecAttr->attrId() != tAttrId){ + ok &= currRecAttr->setNULL(); + prevRecAttr = currRecAttr; + currRecAttr = currRecAttr->next(); + } + + if(ok && currRecAttr && currRecAttr->receive_data(aDataPtr, tAttrSize)){ + used += tAttrSize; + aDataPtr += tAttrSize; + prevRecAttr = currRecAttr; + currRecAttr = currRecAttr->next(); + } else { + ndbout_c("%p: ok: %d tAttrId: %d currRecAttr: %p", + this,ok, tAttrId, currRecAttr); + abort(); + return -1; + } + } + + theCurrentRecAttr = currRecAttr; + + /** + * Update m_received_result_length + */ + Uint32 tmp = m_received_result_length + aLength; + m_received_result_length = tmp; + + return (tmp == m_expected_result_length ? 1 : 0); +} + +int +NdbReceiver::execKEYINFO20(Uint32 info, const Uint32* aDataPtr, Uint32 aLength) +{ + NdbRecAttr* currRecAttr = m_rows[m_current_row++]; + assert(currRecAttr->attrId() == KEY_ATTR_ID); + currRecAttr->receive_data(aDataPtr, aLength + 1); + + /** + * Save scanInfo in the end of keyinfo + */ + ((Uint32*)currRecAttr->aRef())[aLength] = info; + + Uint32 tmp = m_received_result_length + aLength; + m_received_result_length = tmp; + + return (tmp == m_expected_result_length ? 1 : 0); +} diff --git a/ndb/src/ndbapi/NdbResultSet.cpp b/ndb/src/ndbapi/NdbResultSet.cpp index 8397d5eef91..07c8972b4cb 100644 --- a/ndb/src/ndbapi/NdbResultSet.cpp +++ b/ndb/src/ndbapi/NdbResultSet.cpp @@ -30,7 +30,7 @@ #include #include -NdbResultSet::NdbResultSet(NdbCursorOperation *owner) +NdbResultSet::NdbResultSet(NdbScanOperation *owner) : m_operation(owner) { } @@ -55,46 +55,21 @@ void NdbResultSet::close() NdbOperation* NdbResultSet::updateTuple(){ - if(m_operation->cursorType() != NdbCursorOperation::ScanCursor){ - m_operation->setErrorCode(4003); - return 0; - } - - NdbScanOperation * op = (NdbScanOperation*)(m_operation); - return op->takeOverScanOp(UpdateRequest, op->m_transConnection); + return updateTuple(m_operation->m_transConnection); } NdbOperation* NdbResultSet::updateTuple(NdbConnection* takeOverTrans){ - if(m_operation->cursorType() != NdbCursorOperation::ScanCursor){ - m_operation->setErrorCode(4003); - return 0; - } - return m_operation->takeOverScanOp(UpdateRequest, takeOverTrans); } int NdbResultSet::deleteTuple(){ - if(m_operation->cursorType() != NdbCursorOperation::ScanCursor){ - m_operation->setErrorCode(4003); - return 0; - } - - NdbScanOperation * op = (NdbScanOperation*)(m_operation); - void * res = op->takeOverScanOp(DeleteRequest, op->m_transConnection); - if(res == 0) - return -1; - return 0; + return deleteTuple(m_operation->m_transConnection); } int NdbResultSet::deleteTuple(NdbConnection * takeOverTrans){ - if(m_operation->cursorType() != NdbCursorOperation::ScanCursor){ - m_operation->setErrorCode(4003); - return 0; - } - void * res = m_operation->takeOverScanOp(DeleteRequest, takeOverTrans); if(res == 0) return -1; diff --git a/ndb/src/ndbapi/NdbScanOperation.cpp b/ndb/src/ndbapi/NdbScanOperation.cpp index ca2c4590017..8a3d041b0d7 100644 --- a/ndb/src/ndbapi/NdbScanOperation.cpp +++ b/ndb/src/ndbapi/NdbScanOperation.cpp @@ -26,36 +26,57 @@ * Adjust: 2002-04-01 UABMASD First version. ****************************************************************************/ -#include #include #include +#include #include #include #include "NdbApiSignal.hpp" #include #include "NdbDictionaryImpl.hpp" +#include +#include + +#include +#include + +#include +#include +#include + NdbScanOperation::NdbScanOperation(Ndb* aNdb) : - NdbCursorOperation(aNdb), - m_transConnection(NULL), - m_autoExecute(false), - m_updateOp(false), - m_deleteOp(false), - m_setValueList(new SetValueRecList()) + NdbOperation(aNdb), + m_resultSet(0), + m_transConnection(NULL) { + theParallelism = 0; + m_allocated_receivers = 0; + m_prepared_receivers = 0; + m_api_receivers = 0; + m_conf_receivers = 0; + m_sent_receivers = 0; + m_receivers = 0; } NdbScanOperation::~NdbScanOperation() { - if (m_setValueList) delete m_setValueList; + fix_receivers(0, false); + if (m_resultSet) + delete m_resultSet; } -NdbCursorOperation::CursorType -NdbScanOperation::cursorType() +NdbResultSet* +NdbScanOperation::getResultSet() { - return NdbCursorOperation::ScanCursor; + if (!m_resultSet) + m_resultSet = new NdbResultSet(this); + + return m_resultSet; } + + void NdbScanOperation::setErrorCode(int aErrorCode){ NdbConnection* tmp = theNdbCon; @@ -88,267 +109,516 @@ NdbScanOperation::init(NdbTableImpl* tab, NdbConnection* myConnection) NdbConnection* aScanConnection = theNdb->hupp(myConnection); if (!aScanConnection) return -1; - aScanConnection->theFirstOpInList = this; - aScanConnection->theLastOpInList = this; - NdbCursorOperation::cursInit(); + // NOTE! The hupped trans becomes the owner of the operation - return NdbOperation::init(tab, aScanConnection); + if(NdbOperation::init(tab, aScanConnection) != 0){ + return -1; + } + + initInterpreter(); + + theStatus = GetValue; + theOperationType = OpenScanRequest; + + theTotalBoundAI_Len = 0; + theBoundATTRINFO = NULL; + + return 0; } -NdbResultSet* NdbScanOperation::readTuples(Uint32 parallell, - NdbCursorOperation::LockMode lm) +NdbResultSet* NdbScanOperation::readTuples(NdbScanOperation::LockMode lm, + Uint32 batch, + Uint32 parallell) { - int res = 0; + m_ordered = 0; + + Uint32 fragCount = m_currentTable->m_fragmentCount; + + if(batch + parallell == 0){ // Max speed + batch = 16; + parallell = fragCount; + } + + if(batch == 0 && parallell > 0){ // Backward + batch = (parallell >= 16 ? 16 : parallell & 15); + parallell = (parallell + 15) / 16; + + if(parallell == 0) + parallell = 1; + } + + if(parallell > fragCount) + parallell = fragCount; + else if(parallell == 0) + parallell = fragCount; + + assert(parallell > 0); + + // It is only possible to call openScan if + // 1. this transcation don't already contain another scan operation + // 2. this transaction don't already contain other operations + // 3. theScanOp contains a NdbScanOperation + if (theNdbCon->theScanningOp != NULL){ + setErrorCode(4605); + return 0; + } + + theNdbCon->theScanningOp = this; + + bool lockExcl, lockHoldMode, readCommitted; switch(lm){ - case NdbCursorOperation::LM_Read: - parallell = (parallell == 0 ? 240 : parallell); - res = openScan(parallell, false, true, false); + case NdbScanOperation::LM_Read: + lockExcl = false; + lockHoldMode = true; + readCommitted = false; break; - case NdbCursorOperation::LM_Exclusive: - parallell = (parallell == 0 ? 1 : parallell); - res = openScan(parallell, true, true, false); + case NdbScanOperation::LM_Exclusive: + lockExcl = true; + lockHoldMode = true; + readCommitted = false; break; - case NdbCursorOperation::LM_Dirty: - parallell = (parallell == 0 ? 240 : parallell); - res = openScan(parallell, false, false, true); + case NdbScanOperation::LM_Dirty: + lockExcl = false; + lockHoldMode = false; + readCommitted = true; break; default: - res = -1; setErrorCode(4003); + return 0; } - if(res == -1){ - return NULL; + + m_keyInfo = lockExcl; + + bool range = false; + if (m_currentTable->m_indexType == NdbDictionary::Index::OrderedIndex || + m_currentTable->m_indexType == NdbDictionary::Index::UniqueOrderedIndex){ + assert(m_currentTable == m_accessTable); + m_currentTable = theNdb->theDictionary-> + getTable(m_currentTable->m_primaryTable.c_str()); + assert(m_currentTable != NULL); + // Modify operation state + theStatus = SetBound; + theOperationType = OpenRangeScanRequest; + range = true; } - theNdbCon->theFirstOpInList = 0; - theNdbCon->theLastOpInList = 0; + + theParallelism = parallell; + theBatchSize = batch; + + if(fix_receivers(parallell, lockExcl) == -1){ + setErrorCodeAbort(4000); + return 0; + } + + theSCAN_TABREQ = theNdb->getSignal(); + if (theSCAN_TABREQ == NULL) { + setErrorCodeAbort(4000); + return 0; + }//if + + ScanTabReq * req = CAST_PTR(ScanTabReq, theSCAN_TABREQ->getDataPtrSend()); + req->apiConnectPtr = theNdbCon->theTCConPtr; + req->tableId = m_accessTable->m_tableId; + req->tableSchemaVersion = m_accessTable->m_version; + req->storedProcId = 0xFFFF; + req->buddyConPtr = theNdbCon->theBuddyConPtr; + + Uint32 reqInfo = 0; + ScanTabReq::setParallelism(reqInfo, parallell); + ScanTabReq::setScanBatch(reqInfo, batch); + ScanTabReq::setLockMode(reqInfo, lockExcl); + ScanTabReq::setHoldLockFlag(reqInfo, lockHoldMode); + ScanTabReq::setReadCommittedFlag(reqInfo, readCommitted); + ScanTabReq::setRangeScanFlag(reqInfo, range); + req->requestInfo = reqInfo; + + Uint64 transId = theNdbCon->getTransactionId(); + req->transId1 = (Uint32) transId; + req->transId2 = (Uint32) (transId >> 32); + + getFirstATTRINFOScan(); return getResultSet(); } -int NdbScanOperation::updateTuples(Uint32 parallelism) -{ - if (openScanExclusive(parallelism) == -1) { - return -1; - } - theNdbCon->theFirstOpInList = 0; - theNdbCon->theLastOpInList = 0; - - m_updateOp = true; - - return 0; -} - -int NdbScanOperation::deleteTuples(Uint32 parallelism) -{ - if (openScanExclusive(parallelism) == -1) { - return -1; - } - theNdbCon->theFirstOpInList = 0; - theNdbCon->theLastOpInList = 0; - - m_deleteOp = true; - - return 0; -} - -int NdbScanOperation::setValue(const char* anAttrName, const char* aValue, Uint32 len) -{ - // Check if attribute exist - if (m_currentTable->getColumn(anAttrName) == NULL) - return -1; - - m_setValueList->add(anAttrName, aValue, len); - return 0; -} - -int NdbScanOperation::setValue(const char* anAttrName, Int32 aValue) -{ - // Check if attribute exist - if (m_currentTable->getColumn(anAttrName) == NULL) - return -1; - - m_setValueList->add(anAttrName, aValue); - return 0; -} - -int NdbScanOperation::setValue(const char* anAttrName, Uint32 aValue) -{ - // Check if attribute exist - if (m_currentTable->getColumn(anAttrName) == NULL) - return -1; - - m_setValueList->add(anAttrName, aValue); - return 0; -} - -int NdbScanOperation::setValue(const char* anAttrName, Uint64 aValue) -{ - // Check if attribute exist - if (m_currentTable->getColumn(anAttrName) == NULL) - return -1; - - m_setValueList->add(anAttrName, aValue); - return 0; -} - -int NdbScanOperation::setValue(const char* anAttrName, Int64 aValue) -{ - // Check if attribute exist - if (m_currentTable->getColumn(anAttrName) == NULL) - return -1; - - m_setValueList->add(anAttrName, aValue); - return 0; -} - -int NdbScanOperation::setValue(const char* anAttrName, float aValue) -{ - // Check if attribute exist - if (m_currentTable->getColumn(anAttrName) == NULL) - return -1; - - m_setValueList->add(anAttrName, aValue); - return 0; -} - -int NdbScanOperation::setValue(const char* anAttrName, double aValue) -{ - // Check if attribute exist - if (m_currentTable->getColumn(anAttrName) == NULL) - return -1; - - m_setValueList->add(anAttrName, aValue); - return 0; -} - - -int NdbScanOperation::setValue(Uint32 anAttrId, const char* aValue, Uint32 len) -{ - // Check if attribute exist - if (m_currentTable->getColumn(anAttrId) == NULL) - return -1; - - m_setValueList->add(anAttrId, aValue, len); - return 0; -} - -int NdbScanOperation::setValue(Uint32 anAttrId, Int32 aValue) -{ - // Check if attribute exist - if (m_currentTable->getColumn(anAttrId) == NULL) - return -1; - - m_setValueList->add(anAttrId, aValue); - return 0; -} - -int NdbScanOperation::setValue(Uint32 anAttrId, Uint32 aValue) -{ - // Check if attribute exist - if (m_currentTable->getColumn(anAttrId) == NULL) - return -1; - - m_setValueList->add(anAttrId, aValue); - return 0; -} - -int NdbScanOperation::setValue(Uint32 anAttrId, Uint64 aValue) -{ - // Check if attribute exist - if (m_currentTable->getColumn(anAttrId) == NULL) - return -1; - - m_setValueList->add(anAttrId, aValue); - return 0; -} - -int NdbScanOperation::setValue(Uint32 anAttrId, Int64 aValue) -{ - // Check if attribute exist - if (m_currentTable->getColumn(anAttrId) == NULL) - return -1; - - m_setValueList->add(anAttrId, aValue); - return 0; -} - -int NdbScanOperation::setValue(Uint32 anAttrId, float aValue) -{ - // Check if attribute exist - if (m_currentTable->getColumn(anAttrId) == NULL) - return -1; - - m_setValueList->add(anAttrId, aValue); - return 0; -} - -int NdbScanOperation::setValue(Uint32 anAttrId, double aValue) -{ - // Check if attribute exist - if (m_currentTable->getColumn(anAttrId) == NULL) - return -1; - - m_setValueList->add(anAttrId, aValue); - return 0; -} - -// Private methods - -int NdbScanOperation::executeCursor(int ProcessorId) -{ - int result = theNdbCon->executeScan(); - // If the scan started ok and we are updating or deleting - // iterate over all tuples - if ((m_updateOp) || (m_deleteOp)) { - NdbOperation* newOp; - - while ((result != -1) && (nextResult() == 0)) { - if (m_updateOp) { - newOp = takeOverScanOp(UpdateRequest, m_transConnection); - // Pass setValues from scan operation to new operation - m_setValueList->iterate(SetValueRecList::callSetValueFn, *newOp); - // No need to call updateTuple since scan was taken over for update - // it should be the same with delete - MASV - // newOp->updateTuple(); - } - else if (m_deleteOp) { - newOp = takeOverScanOp(DeleteRequest, m_transConnection); - // newOp->deleteTuple(); - } -#if 0 - // takeOverScanOp will take over the lock that scan aquired - // the lock is released when nextScanResult is called - // That means that the "takeover" has to be sent to the kernel - // before nextScanresult is called - MASV - if (m_autoExecute){ - m_transConnection->execute(NoCommit); - } -#else - m_transConnection->execute(NoCommit); -#endif +int +NdbScanOperation::fix_receivers(Uint32 parallell, bool keyInfo){ + if(parallell == 0 || parallell > m_allocated_receivers){ + if(m_prepared_receivers) delete[] m_prepared_receivers; + if(m_receivers) delete[] m_receivers; + if(m_api_receivers) delete[] m_api_receivers; + if(m_conf_receivers) delete[] m_conf_receivers; + if(m_sent_receivers) delete[] m_sent_receivers; + + m_allocated_receivers = parallell; + if(parallell == 0){ + return 0; } - closeScan(); + + m_prepared_receivers = new Uint32[parallell]; + m_receivers = new NdbReceiver*[parallell]; + m_api_receivers = new NdbReceiver*[parallell]; + m_conf_receivers = new NdbReceiver*[parallell]; + m_sent_receivers = new NdbReceiver*[parallell]; + + NdbReceiver* tScanRec; + for (Uint32 i = 0; i < parallell; i ++) { + tScanRec = theNdb->getNdbScanRec(); + if (tScanRec == NULL) { + setErrorCodeAbort(4000); + return -1; + }//if + m_receivers[i] = tScanRec; + tScanRec->init(NdbReceiver::NDB_SCANRECEIVER, this, keyInfo); + } + } + + for(Uint32 i = 0; im_list_index = i; + m_prepared_receivers[i] = m_receivers[i]->getId(); + m_sent_receivers[i] = m_receivers[i]; + m_conf_receivers[i] = 0; + m_api_receivers[i] = 0; } - return result; + m_api_receivers_count = 0; + m_current_api_receiver = 0; + m_sent_receivers_count = parallell; + m_conf_receivers_count = 0; + return 0; +} + +/** + * Move receiver from send array to conf:ed array + */ +void +NdbScanOperation::receiver_delivered(NdbReceiver* tRec){ + Uint32 idx = tRec->m_list_index; + Uint32 last = m_sent_receivers_count - 1; + if(idx != last){ + NdbReceiver * move = m_sent_receivers[last]; + m_sent_receivers[idx] = move; + move->m_list_index = idx; + } + m_sent_receivers_count = last; + + last = m_conf_receivers_count; + m_conf_receivers[last] = tRec; + m_conf_receivers_count = last + 1; + tRec->m_list_index = last; + tRec->m_current_row = 0; +} + +/** + * Remove receiver as it's completed + */ +void +NdbScanOperation::receiver_completed(NdbReceiver* tRec){ + Uint32 idx = tRec->m_list_index; + Uint32 last = m_sent_receivers_count - 1; + if(idx != last){ + NdbReceiver * move = m_sent_receivers[last]; + m_sent_receivers[idx] = move; + move->m_list_index = idx; + } + m_sent_receivers_count = last; +} + +/***************************************************************************** + * int getFirstATTRINFOScan( U_int32 aData ) + * + * Return Value: Return 0: Successful + * Return -1: All other cases + * Parameters: None: Only allocate the first signal. + * Remark: When a scan is defined we need to use this method instead + * of insertATTRINFO for the first signal. + * This is because we need not to mess up the code in + * insertATTRINFO with if statements since we are not + * interested in the TCKEYREQ signal. + *****************************************************************************/ +int +NdbScanOperation::getFirstATTRINFOScan() +{ + NdbApiSignal* tSignal; + + tSignal = theNdb->getSignal(); + if (tSignal == NULL){ + setErrorCodeAbort(4000); + return -1; + } + tSignal->setSignal(m_attrInfoGSN); + theAI_LenInCurrAI = 8; + theATTRINFOptr = &tSignal->getDataPtrSend()[8]; + theFirstATTRINFO = tSignal; + theCurrentATTRINFO = tSignal; + theCurrentATTRINFO->next(NULL); + + return 0; +} + +/** + * Constats for theTupleKeyDefined[][0] + */ +#define SETBOUND_EQ 1 +#define FAKE_PTR 2 +#define API_PTR 3 + + +/* + * After setBound() are done, move the accumulated ATTRINFO signals to + * a separate list. Then continue with normal scan. + */ +int +NdbScanOperation::saveBoundATTRINFO() +{ + theCurrentATTRINFO->setLength(theAI_LenInCurrAI); + theBoundATTRINFO = theFirstATTRINFO; + theTotalBoundAI_Len = theTotalCurrAI_Len; + theTotalCurrAI_Len = 5; + theBoundATTRINFO->setData(theTotalBoundAI_Len, 4); + theBoundATTRINFO->setData(0, 5); + theBoundATTRINFO->setData(0, 6); + theBoundATTRINFO->setData(0, 7); + theBoundATTRINFO->setData(0, 8); + theStatus = GetValue; + + int res = getFirstATTRINFOScan(); + + /** + * Define each key with getValue (if ordered) + * unless the one's with EqBound + */ + if(!res && m_ordered){ + Uint32 idx = 0; + Uint32 cnt = m_currentTable->getNoOfPrimaryKeys(); + while(!theTupleKeyDefined[idx][0] && idx < cnt){ + NdbColumnImpl* col = m_currentTable->getColumn(idx); + NdbRecAttr* tmp = NdbScanOperation::getValue_impl(col, (char*)-1); + UintPtr newVal = UintPtr(tmp); + theTupleKeyDefined[idx][0] = FAKE_PTR; + theTupleKeyDefined[idx][1] = (newVal & 0xFFFFFFFF); +#if (SIZEOF_CHARP == 8) + theTupleKeyDefined[idx][2] = (newVal >> 32); +#endif + idx++; + } + } + return res; +} + +#define WAITFOR_SCAN_TIMEOUT 120000 + +int +NdbScanOperation::executeCursor(int nodeId){ + NdbConnection * tCon = theNdbCon; + TransporterFacade* tp = TransporterFacade::instance(); + Guard guard(tp->theMutexPtr); + Uint32 seq = tCon->theNodeSequence; + if (tp->get_node_alive(nodeId) && + (tp->getNodeSequence(nodeId) == seq)) { + + if(prepareSendScan(tCon->theTCConPtr, tCon->theTransactionId) == -1) + return -1; + + tCon->theMagicNumber = 0x37412619; + + if (doSendScan(nodeId) == -1) + return -1; + + return 0; + } else { + if (!(tp->get_node_stopping(nodeId) && + (tp->getNodeSequence(nodeId) == seq))){ + TRACE_DEBUG("The node is hard dead when attempting to start a scan"); + setErrorCode(4029); + tCon->theReleaseOnClose = true; + abort(); + } else { + TRACE_DEBUG("The node is stopping when attempting to start a scan"); + setErrorCode(4030); + }//if + tCon->theCommitStatus = Aborted; + }//if + return -1; } int NdbScanOperation::nextResult(bool fetchAllowed) { - int result = theNdbCon->nextScanResult(fetchAllowed); - if (result == -1){ - // Move the error code from hupped transaction - // to the real trans - const NdbError err = theNdbCon->getNdbError(); - m_transConnection->setOperationErrorCode(err.code); + if(m_ordered) + return ((NdbIndexScanOperation*)this)->next_result_ordered(fetchAllowed); + + /** + * Check current receiver + */ + int retVal = 2; + Uint32 idx = m_current_api_receiver; + Uint32 last = m_api_receivers_count; + + /** + * Check next buckets + */ + for(; idx < last; idx++){ + NdbReceiver* tRec = m_api_receivers[idx]; + if(tRec->nextResult()){ + tRec->copyout(theReceiver); + retVal = 0; + break; + } } - return result; + + /** + * We have advanced atleast one bucket + */ + if(!fetchAllowed){ + m_current_api_receiver = idx; + return retVal; + } + + Uint32 nodeId = theNdbCon->theDBnode; + TransporterFacade* tp = TransporterFacade::instance(); + Guard guard(tp->theMutexPtr); + Uint32 seq = theNdbCon->theNodeSequence; + if(seq == tp->getNodeSequence(nodeId) && send_next_scan(idx, false) == 0){ + + idx = m_current_api_receiver; + last = m_api_receivers_count; + + do { + Uint32 cnt = m_conf_receivers_count; + Uint32 sent = m_sent_receivers_count; + + if(cnt > 0){ + /** + * Just move completed receivers + */ + memcpy(m_api_receivers+last, m_conf_receivers, cnt * sizeof(char*)); + last += cnt; + m_conf_receivers_count = 0; + } else if(retVal == 2 && sent > 0){ + /** + * No completed... + */ + theNdb->theWaiter.m_node = nodeId; + theNdb->theWaiter.m_state = WAIT_SCAN; + int return_code = theNdb->receiveResponse(WAITFOR_SCAN_TIMEOUT); + if (return_code == 0 && seq == tp->getNodeSequence(nodeId)) { + continue; + } else { + idx = last; + retVal = -1; //return_code; + } + } else if(retVal == 2){ + /** + * No completed & no sent -> EndOfData + */ + if(send_next_scan(0, true) == 0){ // Close scan + theNdb->theWaiter.m_node = nodeId; + theNdb->theWaiter.m_state = WAIT_SCAN; + int return_code = theNdb->receiveResponse(WAITFOR_SCAN_TIMEOUT); + if (return_code == 0 && seq == tp->getNodeSequence(nodeId)) { + return 1; + } + retVal = -1; //return_code; + } else { + retVal = -3; + } + idx = last; + } + + if(retVal == 0) + break; + + for(; idx < last; idx++){ + NdbReceiver* tRec = m_api_receivers[idx]; + if(tRec->nextResult()){ + tRec->copyout(theReceiver); + retVal = 0; + break; + } + } + } while(retVal == 2); + } else { + retVal = -3; + } + + m_api_receivers_count = last; + m_current_api_receiver = idx; + + switch(retVal){ + case 0: + case 1: + case 2: + return retVal; + case -1: + setErrorCode(4008); // Timeout + break; + case -2: + setErrorCode(4028); // Node fail + break; + case -3: // send_next_scan -> return fail (set error-code self) + break; + } + + theNdbCon->theTransactionIsStarted = false; + theNdbCon->theReleaseOnClose = true; + return -1; +} + +int +NdbScanOperation::send_next_scan(Uint32 cnt, bool stopScanFlag){ + if(cnt > 0 || stopScanFlag){ + NdbApiSignal tSignal(theNdb->theMyRef); + tSignal.setSignal(GSN_SCAN_NEXTREQ); + + Uint32* theData = tSignal.getDataPtrSend(); + theData[0] = theNdbCon->theTCConPtr; + theData[1] = stopScanFlag == true ? 1 : 0; + Uint64 transId = theNdbCon->theTransactionId; + theData[2] = transId; + theData[3] = (Uint32) (transId >> 32); + + /** + * Prepare ops + */ + Uint32 last = m_sent_receivers_count; + Uint32 * prep_array = (cnt > 21 ? m_prepared_receivers : theData + 4); + for(Uint32 i = 0; im_list_index = last+i; + prep_array[i] = tRec->m_tcPtrI; + tRec->prepareSend(); + } + memcpy(&m_api_receivers[0], &m_api_receivers[cnt], cnt * sizeof(char*)); + + Uint32 nodeId = theNdbCon->theDBnode; + TransporterFacade * tp = TransporterFacade::instance(); + int ret; + if(cnt > 21){ + tSignal.setLength(4); + LinearSectionPtr ptr[3]; + ptr[0].p = prep_array; + ptr[0].sz = cnt; + ret = tp->sendFragmentedSignal(&tSignal, nodeId, ptr, 1); + } else { + tSignal.setLength(4+cnt); + ret = tp->sendSignal(&tSignal, nodeId); + } + + m_sent_receivers_count = last + cnt + stopScanFlag; + m_api_receivers_count -= cnt; + m_current_api_receiver = 0; + + return ret; + } + return 0; } int NdbScanOperation::prepareSend(Uint32 TC_ConnectPtr, Uint64 TransactionId) { printf("NdbScanOperation::prepareSend\n"); + abort(); return 0; } @@ -361,300 +631,689 @@ NdbScanOperation::doSend(int ProcessorId) void NdbScanOperation::closeScan() { - if(theNdbCon){ - if (theNdbCon->stopScan() == -1) - theError = theNdbCon->getNdbError(); - theNdb->closeTransaction(theNdbCon); - theNdbCon = 0; - } + do { + TransporterFacade* tp = TransporterFacade::instance(); + Guard guard(tp->theMutexPtr); + + Uint32 seq = theNdbCon->theNodeSequence; + Uint32 nodeId = theNdbCon->theDBnode; + + if(seq != tp->getNodeSequence(nodeId)){ + theNdbCon->theReleaseOnClose = true; + break; + } + + /** + * Wait for all running scans... + */ + while(m_sent_receivers_count){ + theNdb->theWaiter.m_node = nodeId; + theNdb->theWaiter.m_state = WAIT_SCAN; + int return_code = theNdb->receiveResponse(WAITFOR_SCAN_TIMEOUT); + switch(return_code){ + case 0: + break; + case -1: + setErrorCode(4008); + case -2: + m_sent_receivers_count = 0; + m_api_receivers_count = 0; + m_conf_receivers_count = 0; + } + } + + if(seq != tp->getNodeSequence(nodeId)){ + theNdbCon->theReleaseOnClose = true; + break; + } + + if(m_api_receivers_count+m_conf_receivers_count){ + // Send close scan + send_next_scan(0, true); // Close scan + + /** + * wait for close scan conf + */ + do { + theNdb->theWaiter.m_node = nodeId; + theNdb->theWaiter.m_state = WAIT_SCAN; + int return_code = theNdb->receiveResponse(WAITFOR_SCAN_TIMEOUT); + switch(return_code){ + case 0: + break; + case -1: + setErrorCode(4008); + case -2: + m_api_receivers_count = 0; + m_conf_receivers_count = 0; + } + } while(m_api_receivers_count+m_conf_receivers_count); + } + } while(0); + + theNdbCon->theScanningOp = 0; + theNdb->closeTransaction(theNdbCon); + + theNdbCon = 0; m_transConnection = NULL; } -void NdbScanOperation::release(){ - closeScan(); - NdbCursorOperation::release(); +void +NdbScanOperation::execCLOSE_SCAN_REP(Uint32 errCode){ + /** + * We will receive no further signals from this scan + */ + if(!errCode){ + /** + * Normal termination + */ + theNdbCon->theCommitStatus = Committed; + theNdbCon->theCompletionStatus = CompletedSuccess; + } else { + /** + * Something is fishy + */ + abort(); + } + m_api_receivers_count = 0; + m_conf_receivers_count = 0; + m_sent_receivers_count = 0; } -void SetValueRecList::add(const char* anAttrName, const char* aValue, Uint32 len) +void NdbScanOperation::release() { - SetValueRec* newSetValueRec = new SetValueRec(); - - newSetValueRec->stype = SetValueRec::SET_STRING_ATTR1; - newSetValueRec->anAttrName = strdup(anAttrName); - newSetValueRec->stringStruct.aStringValue = (char *) malloc(len); - strlcpy(newSetValueRec->stringStruct.aStringValue, aValue, len); - if (!last) - first = last = newSetValueRec; - else { - last->next = newSetValueRec; - last = newSetValueRec; + if(theNdbCon != 0 || m_transConnection != 0){ + closeScan(); + } + for(Uint32 i = 0; irelease(); } } -void SetValueRecList::add(const char* anAttrName, Int32 aValue) -{ - SetValueRec* newSetValueRec = new SetValueRec(); +/*************************************************************************** +int prepareSendScan(Uint32 aTC_ConnectPtr, + Uint64 aTransactionId) - newSetValueRec->stype = SetValueRec::SET_INT32_ATTR1; - newSetValueRec->anAttrName = strdup(anAttrName); - newSetValueRec->anInt32Value = aValue; - if (!last) - first = last = newSetValueRec; - else { - last->next = newSetValueRec; - last = newSetValueRec; +Return Value: Return 0 : preparation of send was succesful. + Return -1: In all other case. +Parameters: aTC_ConnectPtr: the Connect pointer to TC. + aTransactionId: the Transaction identity of the transaction. +Remark: Puts the the final data into ATTRINFO signal(s) after this + we know the how many signal to send and their sizes +***************************************************************************/ +int NdbScanOperation::prepareSendScan(Uint32 aTC_ConnectPtr, + Uint64 aTransactionId){ + + if (theInterpretIndicator != 1 || + (theOperationType != OpenScanRequest && + theOperationType != OpenRangeScanRequest)) { + setErrorCodeAbort(4005); + return -1; } -} -void SetValueRecList::add(const char* anAttrName, Uint32 aValue) -{ - SetValueRec* newSetValueRec = new SetValueRec(); - - newSetValueRec->stype = SetValueRec::SET_UINT32_ATTR1; - newSetValueRec->anAttrName = strdup(anAttrName); - newSetValueRec->anUint32Value = aValue; - if (!last) - first = last = newSetValueRec; - else { - last->next = newSetValueRec; - last = newSetValueRec; + if (theStatus == SetBound) { + saveBoundATTRINFO(); + theStatus = GetValue; } -} -void SetValueRecList::add(const char* anAttrName, Int64 aValue) -{ - SetValueRec* newSetValueRec = new SetValueRec(); + theErrorLine = 0; - newSetValueRec->stype = SetValueRec::SET_INT64_ATTR1; - newSetValueRec->anAttrName = strdup(anAttrName); - newSetValueRec->anInt64Value = aValue; - if (!last) - first = last = newSetValueRec; - else { - last->next = newSetValueRec; - last = newSetValueRec; + // In preapareSendInterpreted we set the sizes (word 4-8) in the + // first ATTRINFO signal. + if (prepareSendInterpreted() == -1) + return -1; + + if(m_ordered){ + ((NdbIndexScanOperation*)this)->fix_get_values(); } -} - -void SetValueRecList::add(const char* anAttrName, Uint64 aValue) -{ - SetValueRec* newSetValueRec = new SetValueRec(); - - newSetValueRec->stype = SetValueRec::SET_UINT64_ATTR1; - newSetValueRec->anAttrName = strdup(anAttrName); - newSetValueRec->anUint64Value = aValue; - if (!last) - first = last = newSetValueRec; - else { - last->next = newSetValueRec; - last = newSetValueRec; + + const Uint32 transId1 = (Uint32) (aTransactionId & 0xFFFFFFFF); + const Uint32 transId2 = (Uint32) (aTransactionId >> 32); + + if (theOperationType == OpenRangeScanRequest) { + NdbApiSignal* tSignal = theBoundATTRINFO; + do{ + tSignal->setData(aTC_ConnectPtr, 1); + tSignal->setData(transId1, 2); + tSignal->setData(transId2, 3); + tSignal = tSignal->next(); + } while (tSignal != NULL); } -} + theCurrentATTRINFO->setLength(theAI_LenInCurrAI); + NdbApiSignal* tSignal = theFirstATTRINFO; + do{ + tSignal->setData(aTC_ConnectPtr, 1); + tSignal->setData(transId1, 2); + tSignal->setData(transId2, 3); + tSignal = tSignal->next(); + } while (tSignal != NULL); -void SetValueRecList::add(const char* anAttrName, float aValue) -{ - SetValueRec* newSetValueRec = new SetValueRec(); - - newSetValueRec->stype = SetValueRec::SET_FLOAT_ATTR1; - newSetValueRec->anAttrName = strdup(anAttrName); - newSetValueRec->aFloatValue = aValue; - if (!last) - first = last = newSetValueRec; - else { - last->next = newSetValueRec; - last = newSetValueRec; + /** + * Prepare all receivers + */ + theReceiver.prepareSend(); + bool keyInfo = m_keyInfo; + Uint32 key_size = keyInfo ? m_currentTable->m_keyLenInWords : 0; + for(Uint32 i = 0; ido_get_value(&theReceiver, theBatchSize, key_size); } + return 0; } -void SetValueRecList::add(const char* anAttrName, double aValue) -{ - SetValueRec* newSetValueRec = new SetValueRec(); +/****************************************************************************** +int doSend() - newSetValueRec->stype = SetValueRec::SET_DOUBLE_ATTR1; - newSetValueRec->anAttrName = strdup(anAttrName); - newSetValueRec->aDoubleValue = aValue; - if (!last) - first = last = newSetValueRec; - else { - last->next = newSetValueRec; - last = newSetValueRec; +Return Value: Return >0 : send was succesful, returns number of signals sent + Return -1: In all other case. +Parameters: aProcessorId: Receiving processor node +Remark: Sends the ATTRINFO signal(s) +******************************************************************************/ +int +NdbScanOperation::doSendScan(int aProcessorId) +{ + Uint32 tSignalCount = 0; + NdbApiSignal* tSignal; + + if (theInterpretIndicator != 1 || + (theOperationType != OpenScanRequest && + theOperationType != OpenRangeScanRequest)) { + setErrorCodeAbort(4005); + return -1; } -} - -void SetValueRecList::add(Uint32 anAttrId, const char* aValue, Uint32 len) -{ - SetValueRec* newSetValueRec = new SetValueRec(); - - newSetValueRec->stype = SetValueRec::SET_STRING_ATTR2; - newSetValueRec->anAttrId = anAttrId; - newSetValueRec->stringStruct.aStringValue = (char *) malloc(len); - strlcpy(newSetValueRec->stringStruct.aStringValue, aValue, len); - if (!last) - first = last = newSetValueRec; - else { - last->next = newSetValueRec; - last = newSetValueRec; + + assert(theSCAN_TABREQ != NULL); + tSignal = theSCAN_TABREQ; + if (tSignal->setSignal(GSN_SCAN_TABREQ) == -1) { + setErrorCode(4001); + return -1; } -} - -void SetValueRecList::add(Uint32 anAttrId, Int32 aValue) -{ - SetValueRec* newSetValueRec = new SetValueRec(); - - newSetValueRec->stype = SetValueRec::SET_INT32_ATTR2; - newSetValueRec->anAttrId = anAttrId; - newSetValueRec->anInt32Value = aValue; - last->next = newSetValueRec; - last = newSetValueRec; -} - -void SetValueRecList::add(Uint32 anAttrId, Uint32 aValue) -{ - SetValueRec* newSetValueRec = new SetValueRec(); - - newSetValueRec->stype = SetValueRec::SET_UINT32_ATTR2; - newSetValueRec->anAttrId = anAttrId; - newSetValueRec->anUint32Value = aValue; - if (!last) - first = last = newSetValueRec; - else { - last->next = newSetValueRec; - last = newSetValueRec; + // Update the "attribute info length in words" in SCAN_TABREQ before + // sending it. This could not be done in openScan because + // we created the ATTRINFO signals after the SCAN_TABREQ signal. + ScanTabReq * const req = CAST_PTR(ScanTabReq, tSignal->getDataPtrSend()); + req->attrLen = theTotalCurrAI_Len; + if (theOperationType == OpenRangeScanRequest) + req->attrLen += theTotalBoundAI_Len; + TransporterFacade *tp = TransporterFacade::instance(); + if(theParallelism > 16){ + LinearSectionPtr ptr[3]; + ptr[0].p = m_prepared_receivers; + ptr[0].sz = theParallelism; + if (tp->sendFragmentedSignal(tSignal, aProcessorId, ptr, 1) == -1) { + setErrorCode(4002); + return -1; + } + } else { + tSignal->setLength(9+theParallelism); + memcpy(tSignal->getDataPtrSend()+9, m_prepared_receivers, 4*theParallelism); + if (tp->sendSignal(tSignal, aProcessorId) == -1) { + setErrorCode(4002); + return -1; + } } -} -void SetValueRecList::add(Uint32 anAttrId, Int64 aValue) -{ - SetValueRec* newSetValueRec = new SetValueRec(); - - newSetValueRec->stype = SetValueRec::SET_INT64_ATTR2; - newSetValueRec->anAttrId = anAttrId; - newSetValueRec->anInt64Value = aValue; - if (!last) - first = last = newSetValueRec; - else { - last->next = newSetValueRec; - last = newSetValueRec; + if (theOperationType == OpenRangeScanRequest) { + // must have at least one signal since it contains attrLen for bounds + assert(theBoundATTRINFO != NULL); + tSignal = theBoundATTRINFO; + while (tSignal != NULL) { + if (tp->sendSignal(tSignal,aProcessorId) == -1){ + setErrorCode(4002); + return -1; + } + tSignalCount++; + tSignal = tSignal->next(); + } } -} + + tSignal = theFirstATTRINFO; + while (tSignal != NULL) { + if (tp->sendSignal(tSignal,aProcessorId) == -1){ + setErrorCode(4002); + return -1; + } + tSignalCount++; + tSignal = tSignal->next(); + } + theStatus = WaitResponse; + return tSignalCount; +}//NdbOperation::doSendScan() -void SetValueRecList::add(Uint32 anAttrId, Uint64 aValue) -{ - SetValueRec* newSetValueRec = new SetValueRec(); +/****************************************************************************** + * NdbOperation* takeOverScanOp(NdbConnection* updateTrans); + * + * Parameters: The update transactions NdbConnection pointer. + * Return Value: A reference to the transferred operation object + * or NULL if no success. + * Remark: Take over the scanning transactions NdbOperation + * object for a tuple to an update transaction, + * which is the last operation read in nextScanResult() + * (theNdbCon->thePreviousScanRec) + * + * FUTURE IMPLEMENTATION: (This note was moved from header file.) + * In the future, it will even be possible to transfer + * to a NdbConnection on another Ndb-object. + * In this case the receiving NdbConnection-object must call + * a method receiveOpFromScan to actually receive the information. + * This means that the updating transactions can be placed + * in separate threads and thus increasing the parallelism during + * the scan process. + *****************************************************************************/ +NdbOperation* +NdbScanOperation::takeOverScanOp(OperationType opType, NdbConnection* pTrans){ + + Uint32 idx = m_current_api_receiver; + Uint32 last = m_api_receivers_count; - newSetValueRec->stype = SetValueRec::SET_UINT64_ATTR2; - newSetValueRec->anAttrId = anAttrId; - newSetValueRec->anUint64Value = aValue; - if (!last) - first = last = newSetValueRec; - else { - last->next = newSetValueRec; - last = newSetValueRec; + Uint32 row; + NdbReceiver * tRec; + NdbRecAttr * tRecAttr; + if(idx < last && (tRec = m_api_receivers[idx]) + && ((row = tRec->m_current_row) <= tRec->m_defined_rows) + && (tRecAttr = tRec->m_rows[row-1])){ + + NdbOperation * newOp = pTrans->getNdbOperation(m_currentTable); + if (newOp == NULL){ + return NULL; + } + + const Uint32 len = (tRecAttr->attrSize() * tRecAttr->arraySize() + 3)/4-1; + + newOp->theTupKeyLen = len; + newOp->theOperationType = opType; + if (opType == DeleteRequest) { + newOp->theStatus = GetValue; + } else { + newOp->theStatus = SetValue; + } + + const Uint32 * src = (Uint32*)tRecAttr->aRef(); + const Uint32 tScanInfo = src[len] & 0xFFFF; + const Uint32 tTakeOverNode = src[len] >> 16; + { + UintR scanInfo = 0; + TcKeyReq::setTakeOverScanFlag(scanInfo, 1); + TcKeyReq::setTakeOverScanNode(scanInfo, tTakeOverNode); + TcKeyReq::setTakeOverScanInfo(scanInfo, tScanInfo); + newOp->theScanInfo = scanInfo; + } + + // Copy the first 8 words of key info from KEYINF20 into TCKEYREQ + TcKeyReq * tcKeyReq = CAST_PTR(TcKeyReq,newOp->theTCREQ->getDataPtrSend()); + Uint32 i = 0; + for (i = 0; i < TcKeyReq::MaxKeyInfo && i < len; i++) { + tcKeyReq->keyInfo[i] = * src++; + } + + if(i < len){ + NdbApiSignal* tSignal = theNdb->getSignal(); + newOp->theFirstKEYINFO = tSignal; + + Uint32 left = len - i; + while(tSignal && left > KeyInfo::DataLength){ + tSignal->setSignal(GSN_KEYINFO); + KeyInfo * keyInfo = CAST_PTR(KeyInfo, tSignal->getDataPtrSend()); + memcpy(keyInfo->keyData, src, 4 * KeyInfo::DataLength); + src += KeyInfo::DataLength; + left -= KeyInfo::DataLength; + + tSignal->next(theNdb->getSignal()); + tSignal = tSignal->next(); + } + + if(tSignal && left > 0){ + tSignal->setSignal(GSN_KEYINFO); + KeyInfo * keyInfo = CAST_PTR(KeyInfo, tSignal->getDataPtrSend()); + memcpy(keyInfo->keyData, src, 4 * left); + } + } + return newOp; } + return 0; } -void SetValueRecList::add(Uint32 anAttrId, float aValue) +NdbIndexScanOperation::NdbIndexScanOperation(Ndb* aNdb) + : NdbScanOperation(aNdb) { - SetValueRec* newSetValueRec = new SetValueRec(); - - newSetValueRec->stype = SetValueRec::SET_FLOAT_ATTR2; - newSetValueRec->anAttrId = anAttrId; - newSetValueRec->aFloatValue = aValue; - if (!last) - first = last = newSetValueRec; - else { - last->next = newSetValueRec; - last = newSetValueRec; - } } -void SetValueRecList::add(Uint32 anAttrId, double aValue) -{ - SetValueRec* newSetValueRec = new SetValueRec(); - - newSetValueRec->stype = SetValueRec::SET_DOUBLE_ATTR2; - newSetValueRec->anAttrId = anAttrId; - newSetValueRec->aDoubleValue = aValue; - if (!last) - first = last = newSetValueRec; - else { - last->next = newSetValueRec; - last = newSetValueRec; - } -} - -void -SetValueRecList::callSetValueFn(SetValueRec& aSetValueRec, NdbOperation& oper) -{ - switch(aSetValueRec.stype) { - case(SetValueRec::SET_STRING_ATTR1): - oper.setValue(aSetValueRec.anAttrName, aSetValueRec.stringStruct.aStringValue, aSetValueRec.stringStruct.len); - break; - case(SetValueRec::SET_INT32_ATTR1): - oper.setValue(aSetValueRec.anAttrName, aSetValueRec.anInt32Value); - break; - case(SetValueRec::SET_UINT32_ATTR1): - oper.setValue(aSetValueRec.anAttrName, aSetValueRec.anUint32Value); - break; - case(SetValueRec::SET_INT64_ATTR1): - oper.setValue(aSetValueRec.anAttrName, aSetValueRec.anInt64Value); - break; - case(SetValueRec::SET_UINT64_ATTR1): - oper.setValue(aSetValueRec.anAttrName, aSetValueRec.anUint64Value); - break; - case(SetValueRec::SET_FLOAT_ATTR1): - oper.setValue(aSetValueRec.anAttrName, aSetValueRec.aFloatValue); - break; - case(SetValueRec::SET_DOUBLE_ATTR1): - oper.setValue(aSetValueRec.anAttrName, aSetValueRec.aDoubleValue); - break; - case(SetValueRec::SET_STRING_ATTR2): - oper.setValue(aSetValueRec.anAttrId, aSetValueRec.stringStruct.aStringValue, aSetValueRec.stringStruct.len); - break; - case(SetValueRec::SET_INT32_ATTR2): - oper.setValue(aSetValueRec.anAttrId, aSetValueRec.anInt32Value); - break; - case(SetValueRec::SET_UINT32_ATTR2): - oper.setValue(aSetValueRec.anAttrId, aSetValueRec.anUint32Value); - break; - case(SetValueRec::SET_INT64_ATTR2): - oper.setValue(aSetValueRec.anAttrId, aSetValueRec.anInt64Value); - break; - case(SetValueRec::SET_UINT64_ATTR2): - oper.setValue(aSetValueRec.anAttrId, aSetValueRec.anUint64Value); - break; - case(SetValueRec::SET_FLOAT_ATTR2): - oper.setValue(aSetValueRec.anAttrId, aSetValueRec.aFloatValue); - break; - case(SetValueRec::SET_DOUBLE_ATTR2): - oper.setValue(aSetValueRec.anAttrId, aSetValueRec.aDoubleValue); - break; - } -} - -SetValueRec::~SetValueRec() -{ - if ((stype == SET_STRING_ATTR1) || - (stype == SET_INT32_ATTR1) || - (stype == SET_UINT32_ATTR1) || - (stype == SET_INT64_ATTR1) || - (stype == SET_UINT64_ATTR1) || - (stype == SET_FLOAT_ATTR1) || - (stype == SET_DOUBLE_ATTR1)) - free(anAttrName); - - if ((stype == SET_STRING_ATTR1) || - (stype == SET_STRING_ATTR2)) - free(stringStruct.aStringValue); - if (next) delete next; - next = 0; +NdbIndexScanOperation::~NdbIndexScanOperation(){ } int -NdbScanOperation::equal_impl(const NdbColumnImpl* anAttrObject, - const char* aValue, - Uint32 len){ +NdbIndexScanOperation::setBound(const char* anAttrName, int type, const void* aValue, Uint32 len) +{ + return setBound(m_accessTable->getColumn(anAttrName), type, aValue, len); +} + +int +NdbIndexScanOperation::setBound(Uint32 anAttrId, int type, const void* aValue, Uint32 len) +{ + return setBound(m_accessTable->getColumn(anAttrId), type, aValue, len); +} + +int +NdbIndexScanOperation::equal_impl(const NdbColumnImpl* anAttrObject, + const char* aValue, + Uint32 len){ return setBound(anAttrObject, BoundEQ, aValue, len); } +NdbRecAttr* +NdbIndexScanOperation::getValue_impl(const NdbColumnImpl* attrInfo, + char* aValue){ + if(!attrInfo->getPrimaryKey() || !m_ordered){ + return NdbScanOperation::getValue_impl(attrInfo, aValue); + } + + Uint32 id = attrInfo->m_attrId; + Uint32 marker = theTupleKeyDefined[id][0]; + if(marker == SETBOUND_EQ){ + return NdbScanOperation::getValue_impl(attrInfo, aValue); + } else if(marker == API_PTR){ + return NdbScanOperation::getValue_impl(attrInfo, aValue); + } + + UintPtr oldVal; + oldVal = theTupleKeyDefined[id][1]; +#if (SIZEOF_CHARP == 8) + oldVal = oldVal | (((UintPtr)theTupleKeyDefined[id][2]) << 32); +#endif + theTupleKeyDefined[id][0] = API_PTR; + + NdbRecAttr* tmp = (NdbRecAttr*)oldVal; + tmp->setup(attrInfo, aValue); + return tmp; +} + +#include +/* + * Define bound on index column in range scan. + */ +int +NdbIndexScanOperation::setBound(const NdbColumnImpl* tAttrInfo, + int type, const void* aValue, Uint32 len) +{ + if (theOperationType == OpenRangeScanRequest && + theStatus == SetBound && + (0 <= type && type <= 4) && + aValue != NULL && + len <= 8000) { + // bound type + + insertATTRINFO(type); + // attribute header + Uint32 sizeInBytes = tAttrInfo->m_attrSize * tAttrInfo->m_arraySize; + if (len != sizeInBytes && (len != 0)) { + setErrorCodeAbort(4209); + return -1; + } + len = sizeInBytes; + Uint32 tIndexAttrId = tAttrInfo->m_attrId; + Uint32 sizeInWords = (len + 3) / 4; + AttributeHeader ah(tIndexAttrId, sizeInWords); + insertATTRINFO(ah.m_value); + // attribute data + if ((UintPtr(aValue) & 0x3) == 0 && (len & 0x3) == 0) + insertATTRINFOloop((const Uint32*)aValue, sizeInWords); + else { + Uint32 temp[2000]; + memcpy(temp, aValue, len); + while ((len & 0x3) != 0) + ((char*)temp)[len++] = 0; + insertATTRINFOloop(temp, sizeInWords); + } + + /** + * Do sorted stuff + */ + + /** + * The primary keys for an ordered index is defined in the beginning + * so it's safe to use [tIndexAttrId] + * (instead of looping as is NdbOperation::equal_impl) + */ + if(!theTupleKeyDefined[tIndexAttrId][0]){ + theNoOfTupKeyDefined++; + theTupleKeyDefined[tIndexAttrId][0] = SETBOUND_EQ; + m_sort_columns -= m_ordered; + } + + return 0; + } else { + setErrorCodeAbort(4228); // XXX wrong code + return -1; + } +} + +NdbResultSet* +NdbIndexScanOperation::readTuples(LockMode lm, + Uint32 batch, + Uint32 parallel, + bool order_by){ + NdbResultSet * rs = NdbScanOperation::readTuples(lm, batch, 0); + if(rs && order_by){ + m_ordered = 1; + m_sort_columns = m_accessTable->getNoOfPrimaryKeys(); + m_current_api_receiver = m_sent_receivers_count; + } + return rs; +} + +void +NdbIndexScanOperation::fix_get_values(){ + /** + * Loop through all getValues and set buffer pointer to "API" pointer + */ + NdbRecAttr * curr = theReceiver.theFirstRecAttr; + + Uint32 cnt = m_sort_columns; + assert(cnt < MAXNROFTUPLEKEY); + + Uint32 idx = 0; + NdbTableImpl * tab = m_currentTable; + while(cnt > 0){ // To MAXNROFTUPLEKEY loops + NdbColumnImpl * col = tab->getColumn(idx); + if(col->getPrimaryKey()){ + Uint32 val = theTupleKeyDefined[idx][0]; + switch(val){ + case FAKE_PTR: + curr->setup(col, 0); + // Fall-through + case API_PTR: + cnt--; + break; + case SETBOUND_EQ: + (void)1; +#ifdef VM_TRACE + break; + default: + abort(); +#endif + } + } + idx++; + } +} + +int +NdbIndexScanOperation::compare(Uint32 skip, Uint32 cols, + const NdbReceiver* t1, + const NdbReceiver* t2){ + + NdbRecAttr * r1 = t1->m_rows[t1->m_current_row]; + NdbRecAttr * r2 = t2->m_rows[t2->m_current_row]; + + r1 = (skip ? r1->next() : r1); + r2 = (skip ? r2->next() : r2); + + while(cols > 0){ + Uint32 * d1 = (Uint32*)r1->aRef(); + Uint32 * d2 = (Uint32*)r2->aRef(); + unsigned r1_null = r1->isNULL(); + if((r1_null ^ (unsigned)r2->isNULL())){ + return (r1_null ? 1 : -1); + } + Uint32 type = NdbColumnImpl::getImpl(* r1->m_column).m_extType; + Uint32 size = (r1->theAttrSize * r1->theArraySize + 3) / 4; + if(!r1_null){ + char r = NdbSqlUtil::cmp(type, d1, d2, size, size); + if(r){ + assert(r != NdbSqlUtil::CmpUnknown); + assert(r != NdbSqlUtil::CmpError); + return r; + } + } + cols--; + r1 = r1->next(); + r2 = r2->next(); + } + return 0; +} + +#define DEBUG_NEXT_RESULT 0 + +int +NdbIndexScanOperation::next_result_ordered(bool fetchAllowed){ + + Uint32 u_idx = m_current_api_receiver; // start of unsorted + Uint32 u_last = u_idx + 1; // last unsorted + Uint32 s_idx = u_last; // start of sorted + Uint32 s_last = theParallelism; // last sorted + + NdbReceiver** arr = m_api_receivers; + NdbReceiver* tRec = arr[u_idx]; + + if(DEBUG_NEXT_RESULT) ndbout_c("nextOrderedResult(%d) nextResult: %d", + fetchAllowed, + (u_idx < s_last ? tRec->nextResult() : 0)); + + if(DEBUG_NEXT_RESULT) ndbout_c("u=[%d %d] s=[%d %d]", + u_idx, u_last, + s_idx, s_last); + + bool fetchNeeded = (u_idx == s_last) || !tRec->nextResult(); + + if(fetchNeeded){ + if(fetchAllowed){ + if(DEBUG_NEXT_RESULT) ndbout_c("performing fetch..."); + TransporterFacade* tp = TransporterFacade::instance(); + Guard guard(tp->theMutexPtr); + Uint32 seq = theNdbCon->theNodeSequence; + Uint32 nodeId = theNdbCon->theDBnode; + if(seq == tp->getNodeSequence(nodeId) && !send_next_scan_ordered(u_idx)){ + Uint32 tmp = m_sent_receivers_count; + while(m_sent_receivers_count > 0){ + theNdb->theWaiter.m_node = nodeId; + theNdb->theWaiter.m_state = WAIT_SCAN; + int return_code = theNdb->receiveResponse(WAITFOR_SCAN_TIMEOUT); + if (return_code == 0 && seq == tp->getNodeSequence(nodeId)) { + continue; + } + return -1; + } + + u_idx = 0; + u_last = m_conf_receivers_count; + s_idx = (u_last > 1 ? s_last : s_idx); + m_conf_receivers_count = 0; + memcpy(arr, m_conf_receivers, u_last * sizeof(char*)); + + if(DEBUG_NEXT_RESULT) ndbout_c("sent: %d recv: %d", tmp, u_last); + } + } else { + return 2; + } + } + + if(DEBUG_NEXT_RESULT) ndbout_c("u=[%d %d] s=[%d %d]", + u_idx, u_last, + s_idx, s_last); + + + Uint32 cols = m_sort_columns; + Uint32 skip = m_keyInfo; + while(u_idx < u_last){ + u_last--; + tRec = arr[u_last]; + + // Do binary search instead to find place + Uint32 place = s_idx; + for(; place < s_last; place++){ + if(compare(skip, cols, tRec, arr[place]) <= 0){ + break; + } + } + + if(place != s_idx){ + if(DEBUG_NEXT_RESULT) + ndbout_c("memmove(%d, %d, %d)", s_idx-1, s_idx, (place - s_idx)); + memmove(arr+s_idx-1, arr+s_idx, sizeof(char*)*(place - s_idx)); + } + + if(DEBUG_NEXT_RESULT) ndbout_c("putting %d @ %d", u_last, place - 1); + m_api_receivers[place-1] = tRec; + s_idx--; + } + + if(DEBUG_NEXT_RESULT) ndbout_c("u=[%d %d] s=[%d %d]", + u_idx, u_last, + s_idx, s_last); + + m_current_api_receiver = s_idx; + + if(DEBUG_NEXT_RESULT) + for(Uint32 i = s_idx; inextResult()){ + tRec->copyout(theReceiver); + return 0; + } + + TransporterFacade* tp = TransporterFacade::instance(); + Guard guard(tp->theMutexPtr); + Uint32 seq = theNdbCon->theNodeSequence; + Uint32 nodeId = theNdbCon->theDBnode; + if(seq == tp->getNodeSequence(nodeId) && send_next_scan(0, true) == 0){ + return 1; + } + return -1; +} + +int +NdbIndexScanOperation::send_next_scan_ordered(Uint32 idx){ + if(idx == theParallelism) + return 0; + + NdbApiSignal tSignal(theNdb->theMyRef); + tSignal.setSignal(GSN_SCAN_NEXTREQ); + + Uint32* theData = tSignal.getDataPtrSend(); + theData[0] = theNdbCon->theTCConPtr; + theData[1] = 0; + Uint64 transId = theNdbCon->theTransactionId; + theData[2] = transId; + theData[3] = (Uint32) (transId >> 32); + + /** + * Prepare ops + */ + Uint32 last = m_sent_receivers_count; + Uint32 * prep_array = theData + 4; + + NdbReceiver * tRec = m_api_receivers[idx]; + m_sent_receivers[last] = tRec; + tRec->m_list_index = last; + prep_array[0] = tRec->m_tcPtrI; + tRec->prepareSend(); + + m_sent_receivers_count = last + 1; + + Uint32 nodeId = theNdbCon->theDBnode; + TransporterFacade * tp = TransporterFacade::instance(); + tSignal.setLength(4+1); + return tp->sendSignal(&tSignal, nodeId); +} diff --git a/ndb/src/ndbapi/Ndbif.cpp b/ndb/src/ndbapi/Ndbif.cpp index b3e5b300e8d..60eda978397 100644 --- a/ndb/src/ndbapi/Ndbif.cpp +++ b/ndb/src/ndbapi/Ndbif.cpp @@ -18,11 +18,9 @@ #include "NdbApiSignal.hpp" #include "AttrType.hpp" #include "NdbImpl.hpp" -#include "NdbSchemaOp.hpp" -#include "NdbSchemaCon.hpp" #include "NdbOperation.hpp" #include "NdbIndexOperation.hpp" -#include "NdbScanReceiver.hpp" +#include "NdbScanOperation.hpp" #include "NdbConnection.hpp" #include "NdbRecAttr.hpp" #include "NdbReceiver.hpp" @@ -35,6 +33,9 @@ #include #include #include +#include +#include +#include #include #include @@ -301,26 +302,28 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3]) NdbOperation* tOp; NdbIndexOperation* tIndexOp; NdbConnection* tCon; - int tReturnCode; + int tReturnCode = -1; const Uint32* tDataPtr = aSignal->getDataPtr(); const Uint32 tWaitState = theWaiter.m_state; const Uint32 tSignalNumber = aSignal->readSignalNumber(); const Uint32 tFirstData = *tDataPtr; + const Uint32 tLen = aSignal->getLength(); + void * tFirstDataPtr; /* - In order to support 64 bit processes in the application we need to use - id's rather than a direct pointer to the object used. It is also a good - idea that one cannot corrupt the application code by sending a corrupt - memory pointer. - - All signals received by the API requires the first data word to be such - an id to the receiving object. + In order to support 64 bit processes in the application we need to use + id's rather than a direct pointer to the object used. It is also a good + idea that one cannot corrupt the application code by sending a corrupt + memory pointer. + + All signals received by the API requires the first data word to be such + an id to the receiving object. */ - + switch (tSignalNumber){ case GSN_TCKEYCONF: { - void* tFirstDataPtr = int2void(tFirstData); + tFirstDataPtr = int2void(tFirstData); if (tFirstDataPtr == 0) goto InvalidSignal; const TcKeyConf * const keyConf = (TcKeyConf *)tDataPtr; @@ -329,7 +332,7 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3]) tCon = void2con(tFirstDataPtr); if ((tCon->checkMagicNumber() == 0) && (tCon->theSendStatus == sendTC_OP)) { - tReturnCode = tCon->receiveTCKEYCONF(keyConf, aSignal->getLength()); + tReturnCode = tCon->receiveTCKEYCONF(keyConf, tLen); if (tReturnCode != -1) { completedTransaction(tCon); }//if @@ -345,93 +348,50 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3]) }//if goto InvalidSignal; - return; - } - case GSN_READCONF: - { - void* tFirstDataPtr = int2void(tFirstData); - if (tFirstDataPtr == 0) goto InvalidSignal; - - tOp = void2rec_op(tFirstDataPtr); - if (tOp->checkMagicNumber() == 0) { - tCon = tOp->theNdbCon; - if (tCon != NULL) { - if (tCon->theSendStatus == sendTC_OP) { - tReturnCode = tOp->receiveREAD_CONF(tDataPtr, - aSignal->getLength()); - if (tReturnCode != -1) { - completedTransaction(tCon); - }//if - }//if - }//if - }//if return; } case GSN_TRANSID_AI: { - void* tFirstDataPtr = int2void(tFirstData); + tFirstDataPtr = int2void(tFirstData); + assert(tFirstDataPtr); if (tFirstDataPtr == 0) goto InvalidSignal; - - // ndbout << "*** GSN_TRANSID_AI ***" << endl; NdbReceiver* tRec = void2rec(tFirstDataPtr); - if (tRec->getType() == NdbReceiver::NDB_OPERATION){ - // tOp = (NdbOperation*)tRec->getOwner(); - tOp = void2rec_op(tFirstDataPtr); - // ndbout << "NDB_OPERATION" << endl; - if (tOp->checkMagicNumber() == 0) { - tCon = tOp->theNdbCon; - if (tCon != NULL) { - if (tCon->theSendStatus == sendTC_OP) { - tReturnCode = tOp->receiveTRANSID_AI(tDataPtr, - aSignal->getLength()); - if (tReturnCode != -1) { - completedTransaction(tCon); - break; - } - } - } + assert(tRec->checkMagicNumber()); + assert(tRec->getTransaction()); + assert(tRec->getTransaction()->checkState_TransId(((const TransIdAI*)tDataPtr)->transId)); + if(tRec->checkMagicNumber() && (tCon = tRec->getTransaction()) && + tCon->checkState_TransId(((const TransIdAI*)tDataPtr)->transId)){ + Uint32 com; + if(aSignal->m_noOfSections > 0){ + com = tRec->execTRANSID_AI(ptr[0].p, ptr[0].sz); + } else { + com = tRec->execTRANSID_AI(tDataPtr + TransIdAI::HeaderLength, + tLen - TransIdAI::HeaderLength); } - } else if (tRec->getType() == NdbReceiver::NDB_INDEX_OPERATION){ - // tOp = (NdbIndexOperation*)tRec->getOwner(); - tOp = void2rec_iop(tFirstDataPtr); - // ndbout << "NDB_INDEX_OPERATION" << endl; - if (tOp->checkMagicNumber() == 0) { - tCon = tOp->theNdbCon; - if (tCon != NULL) { - if (tCon->theSendStatus == sendTC_OP) { - tReturnCode = tOp->receiveTRANSID_AI(tDataPtr, - aSignal->getLength()); - if (tReturnCode != -1) { - completedTransaction(tCon); - break; - } - } - } - } - } else if (tRec->getType() == NdbReceiver::NDB_SCANRECEIVER) { - // NdbScanReceiver* tScanRec = (NdbScanReceiver*)tRec->getOwner(); - // NdbScanReceiver* tScanRec = - // (NdbScanReceiver*)(void2rec(tFirstDataPtr)->getOwner()); - NdbScanReceiver* tScanRec = void2rec_srec(tFirstDataPtr); - // ndbout << "NDB_SCANRECEIVER" << endl; - if(tScanRec->checkMagicNumber() == 0){ - tReturnCode = tScanRec->receiveTRANSID_AI_SCAN(aSignal); - if (tReturnCode != -1) { + + if(com == 1){ + switch(tRec->getType()){ + case NdbReceiver::NDB_OPERATION: + case NdbReceiver::NDB_INDEX_OPERATION: + if(tCon->OpCompleteSuccess() != -1) + completedTransaction(tCon); + break; + case NdbReceiver::NDB_SCANRECEIVER: + tCon->theScanningOp->receiver_delivered(tRec); theWaiter.m_state = NO_WAIT; break; + default: + goto InvalidSignal; } } + break; } else { -#ifdef NDB_NO_DROPPED_SIGNAL - abort(); -#endif goto InvalidSignal; } - return; } case GSN_TCKEY_FAILCONF: { - void* tFirstDataPtr = int2void(tFirstData); + tFirstDataPtr = int2void(tFirstData); if (tFirstDataPtr == 0) goto InvalidSignal; const TcKeyFailConf * const failConf = (TcKeyFailConf *)tDataPtr; @@ -462,7 +422,7 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3]) } case GSN_TCKEY_FAILREF: { - void* tFirstDataPtr = int2void(tFirstData); + tFirstDataPtr = int2void(tFirstData); if (tFirstDataPtr == 0) goto InvalidSignal; tOp = void2rec_op(tFirstDataPtr); @@ -483,7 +443,7 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3]) } case GSN_TCKEYREF: { - void* tFirstDataPtr = int2void(tFirstData); + tFirstDataPtr = int2void(tFirstData); if (tFirstDataPtr == 0) goto InvalidSignal; tOp = void2rec_op(tFirstDataPtr); @@ -504,7 +464,7 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3]) } case GSN_TC_COMMITCONF: { - void* tFirstDataPtr = int2void(tFirstData); + tFirstDataPtr = int2void(tFirstData); if (tFirstDataPtr == 0) goto InvalidSignal; const TcCommitConf * const commitConf = (TcCommitConf *)tDataPtr; @@ -532,7 +492,7 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3]) case GSN_TC_COMMITREF: { - void* tFirstDataPtr = int2void(tFirstData); + tFirstDataPtr = int2void(tFirstData); if (tFirstDataPtr == 0) goto InvalidSignal; tCon = void2con(tFirstDataPtr); @@ -548,7 +508,7 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3]) } case GSN_TCROLLBACKCONF: { - void* tFirstDataPtr = int2void(tFirstData); + tFirstDataPtr = int2void(tFirstData); if (tFirstDataPtr == 0) goto InvalidSignal; tCon = void2con(tFirstDataPtr); @@ -563,7 +523,7 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3]) } case GSN_TCROLLBACKREF: { - void* tFirstDataPtr = int2void(tFirstData); + tFirstDataPtr = int2void(tFirstData); if (tFirstDataPtr == 0) goto InvalidSignal; tCon = void2con(tFirstDataPtr); @@ -579,7 +539,7 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3]) } case GSN_TCROLLBACKREP: { - void* tFirstDataPtr = int2void(tFirstData); + tFirstDataPtr = int2void(tFirstData); if (tFirstDataPtr == 0) goto InvalidSignal; tCon = void2con(tFirstDataPtr); @@ -593,7 +553,7 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3]) } case GSN_TCSEIZECONF: { - void* tFirstDataPtr = int2void(tFirstData); + tFirstDataPtr = int2void(tFirstData); if (tFirstDataPtr == 0) goto InvalidSignal; if (tWaitState != WAIT_TC_SEIZE) { @@ -613,7 +573,7 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3]) } case GSN_TCSEIZEREF: { - void* tFirstDataPtr = int2void(tFirstData); + tFirstDataPtr = int2void(tFirstData); if (tFirstDataPtr == 0) goto InvalidSignal; if (tWaitState != WAIT_TC_SEIZE) { @@ -633,7 +593,7 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3]) } case GSN_TCRELEASECONF: { - void* tFirstDataPtr = int2void(tFirstData); + tFirstDataPtr = int2void(tFirstData); if (tFirstDataPtr == 0) goto InvalidSignal; if (tWaitState != WAIT_TC_RELEASE) { @@ -651,7 +611,7 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3]) } case GSN_TCRELEASEREF: { - void* tFirstDataPtr = int2void(tFirstData); + tFirstDataPtr = int2void(tFirstData); if (tFirstDataPtr == 0) goto InvalidSignal; if (tWaitState != WAIT_TC_RELEASE) { @@ -705,7 +665,7 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3]) case GSN_DIHNDBTAMPER: { - void* tFirstDataPtr = int2void(tFirstData); + tFirstDataPtr = int2void(tFirstData); if (tFirstDataPtr == 0) goto InvalidSignal; if (tWaitState != WAIT_NDB_TAMPER) @@ -719,27 +679,34 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3]) break; } case GSN_SCAN_TABCONF: - { - void* tFirstDataPtr = int2void(tFirstData); - if (tFirstDataPtr == 0) goto InvalidSignal; - - //ndbout << "*** GSN_SCAN_TABCONF *** " << endl; - if (tWaitState != WAIT_SCAN){ - return; - } - tCon = void2con(tFirstDataPtr); - if (tCon->checkMagicNumber() != 0) - return; - tReturnCode = tCon->receiveSCAN_TABCONF(aSignal); - if (tReturnCode != -1) - theWaiter.m_state = NO_WAIT; - break; + { + tFirstDataPtr = int2void(tFirstData); + assert(tFirstDataPtr); + assert(void2con(tFirstDataPtr)); + assert(void2con(tFirstDataPtr)->checkMagicNumber() == 0); + if(tFirstDataPtr && + (tCon = void2con(tFirstDataPtr)) && (tCon->checkMagicNumber() == 0)){ + + if(aSignal->m_noOfSections > 0){ + tReturnCode = tCon->receiveSCAN_TABCONF(aSignal, ptr[0].p, ptr[0].sz); + } else { + tReturnCode = + tCon->receiveSCAN_TABCONF(aSignal, + tDataPtr + ScanTabConf::SignalLength, + tLen - ScanTabConf::SignalLength); + } + if (tReturnCode != -1) + theWaiter.m_state = NO_WAIT; + break; + } else { + goto InvalidSignal; } + } case GSN_SCAN_TABREF: - { - void* tFirstDataPtr = int2void(tFirstData); + { + tFirstDataPtr = int2void(tFirstData); if (tFirstDataPtr == 0) goto InvalidSignal; - + if (tWaitState == WAIT_SCAN){ tCon = void2con(tFirstDataPtr); if (tCon->checkMagicNumber() == 0){ @@ -754,35 +721,41 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3]) } case GSN_SCAN_TABINFO: { - void* tFirstDataPtr = int2void(tFirstData); - if (tFirstDataPtr == 0) goto InvalidSignal; - - //ndbout << "*** GSN_SCAN_TABINFO ***" << endl; - if (tWaitState != WAIT_SCAN) - return; - tCon = void2con(tFirstDataPtr); - if (tCon->checkMagicNumber() != 0) - return; - tReturnCode = tCon->receiveSCAN_TABINFO(aSignal); - if (tReturnCode != -1) - theWaiter.m_state = NO_WAIT; - break; + goto InvalidSignal; } case GSN_KEYINFO20: { - void* tFirstDataPtr = int2void(tFirstData); + tFirstDataPtr = int2void(tFirstData); if (tFirstDataPtr == 0) goto InvalidSignal; + NdbReceiver* tRec = void2rec(tFirstDataPtr); + + if(tRec->checkMagicNumber() && (tCon = tRec->getTransaction()) && + tCon->checkState_TransId(&((const KeyInfo20*)tDataPtr)->transId1)){ - //ndbout << "*** GSN_KEYINFO20 ***" << endl; - NdbScanReceiver* tScanRec = void2rec_srec(tFirstDataPtr); - if (tScanRec->checkMagicNumber() != 0) - return; - tReturnCode = tScanRec->receiveKEYINFO20(aSignal); - if (tReturnCode != -1) - theWaiter.m_state = NO_WAIT; - break; + Uint32 len = ((const KeyInfo20*)tDataPtr)->keyLen; + Uint32 info = ((const KeyInfo20*)tDataPtr)->scanInfo_Node; + int com = -1; + if(aSignal->m_noOfSections > 0 && len == ptr[0].sz){ + com = tRec->execKEYINFO20(info, ptr[0].p, len); + } else if(len == tLen - KeyInfo20::HeaderLength){ + com = tRec->execKEYINFO20(info, tDataPtr+KeyInfo20::HeaderLength, len); + } + + switch(com){ + case 1: + tCon->theScanningOp->receiver_delivered(tRec); + theWaiter.m_state = NO_WAIT; + break; + case 0: + break; + case -1: + goto InvalidSignal; + } + break; + } + goto InvalidSignal; } case GSN_TCINDXCONF:{ - void* tFirstDataPtr = int2void(tFirstData); + tFirstDataPtr = int2void(tFirstData); if (tFirstDataPtr == 0) goto InvalidSignal; const TcIndxConf * const indxConf = (TcIndxConf *)tDataPtr; @@ -790,7 +763,7 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3]) tCon = void2con(tFirstDataPtr); if ((tCon->checkMagicNumber() == 0) && (tCon->theSendStatus == sendTC_OP)) { - tReturnCode = tCon->receiveTCINDXCONF(indxConf, aSignal->getLength()); + tReturnCode = tCon->receiveTCINDXCONF(indxConf, tLen); if (tReturnCode != -1) { completedTransaction(tCon); }//if @@ -805,7 +778,7 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3]) break; } case GSN_TCINDXREF:{ - void* tFirstDataPtr = int2void(tFirstData); + tFirstDataPtr = int2void(tFirstData); if (tFirstDataPtr == 0) goto InvalidSignal; tIndexOp = void2rec_iop(tFirstDataPtr); @@ -895,8 +868,8 @@ Ndb::completedTransaction(NdbConnection* aCon) ndbout << endl << flush; #ifdef VM_TRACE printState("completedTransaction abort"); -#endif abort(); +#endif }//if }//Ndb::completedTransaction() @@ -1255,8 +1228,7 @@ Return: 0 - Response received ******************************************************************************/ int -Ndb::receiveResponse(int waitTime) -{ +Ndb::receiveResponse(int waitTime){ int tResultCode; TransporterFacade::instance()->checkForceSend(theNdbBlockNumber); @@ -1310,10 +1282,10 @@ Ndb::sendRecSignal(Uint16 node_id, if (return_code != -1) { theWaiter.m_node = node_id; theWaiter.m_state = aWaitState; - return receiveResponse(); - // End of protected area - }//if - return_code = -3; + return_code = receiveResponse(); + } else { + return_code = -3; + } } else { return_code = -4; }//if diff --git a/ndb/src/ndbapi/Ndblist.cpp b/ndb/src/ndbapi/Ndblist.cpp index 3839cc3291b..26333596408 100644 --- a/ndb/src/ndbapi/Ndblist.cpp +++ b/ndb/src/ndbapi/Ndblist.cpp @@ -15,16 +15,13 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include -#include "Ndb.hpp" -#include "NdbSchemaOp.hpp" -#include "NdbSchemaCon.hpp" -#include "NdbOperation.hpp" -#include "NdbScanOperation.hpp" -#include "NdbIndexOperation.hpp" -#include "NdbConnection.hpp" +#include +#include +#include +#include +#include #include "NdbApiSignal.hpp" -#include "NdbRecAttr.hpp" -#include "NdbScanReceiver.hpp" +#include #include "NdbUtil.hpp" #include "API.hpp" @@ -263,13 +260,13 @@ Ndb::getNdbLabel() * Remark: Get a NdbScanReceiver from theScanRecList and return the * object . ****************************************************************************/ -NdbScanReceiver* +NdbReceiver* Ndb::getNdbScanRec() { - NdbScanReceiver* tNdbScanRec; + NdbReceiver* tNdbScanRec; if ( theScanList == NULL ) { - tNdbScanRec = new NdbScanReceiver(this); + tNdbScanRec = new NdbReceiver(this); if (tNdbScanRec == NULL) { return NULL; @@ -344,17 +341,17 @@ Return Value: Return theOpList : if the getScanOperation was succesful. Return NULL : In all other case. Remark: Get an operation from theScanOpIdleList and return the object . ***************************************************************************/ -NdbScanOperation* +NdbIndexScanOperation* Ndb::getScanOperation() { - NdbScanOperation* tOp = theScanOpIdleList; + NdbIndexScanOperation* tOp = theScanOpIdleList; if (tOp != NULL ) { - NdbScanOperation* tOpNext = (NdbScanOperation*) tOp->next(); + NdbIndexScanOperation* tOpNext = (NdbIndexScanOperation*)tOp->next(); tOp->next(NULL); theScanOpIdleList = tOpNext; return tOp; } else { - tOp = new NdbScanOperation(this); + tOp = new NdbIndexScanOperation(this); if (tOp != NULL) tOp->next(NULL); } @@ -495,7 +492,7 @@ Parameters: aNdbScanRec: The NdbScanReceiver object. Remark: Add a NdbScanReceiver object into the Scan idlelist. ***************************************************************************/ void -Ndb::releaseNdbScanRec(NdbScanReceiver* aNdbScanRec) +Ndb::releaseNdbScanRec(NdbReceiver* aNdbScanRec) { aNdbScanRec->next(theScanList); theScanList = aNdbScanRec; @@ -544,12 +541,12 @@ Parameters: aScanOperation : The released NdbScanOperation object. Remark: Add a NdbScanOperation object into the signal idlelist. ***************************************************************************/ void -Ndb::releaseScanOperation(NdbScanOperation* aScanOperation) +Ndb::releaseScanOperation(NdbIndexScanOperation* aScanOperation) { aScanOperation->next(theScanOpIdleList); aScanOperation->theNdbCon = NULL; aScanOperation->theMagicNumber = 0xFE11D2; - theScanOpIdleList = (NdbScanOperation*)aScanOperation; + theScanOpIdleList = aScanOperation; } /*************************************************************************** @@ -623,7 +620,7 @@ void Ndb::freeScanOperation() { NdbScanOperation* tOp = theScanOpIdleList; - theScanOpIdleList = (NdbScanOperation *) theScanOpIdleList->next(); + theScanOpIdleList = (NdbIndexScanOperation *) theScanOpIdleList->next(); delete tOp; } @@ -674,7 +671,7 @@ Remark: Always release the first item in the free list void Ndb::freeNdbScanRec() { - NdbScanReceiver* tNdbScanRec = theScanList; + NdbReceiver* tNdbScanRec = theScanList; theScanList = theScanList->next(); delete tNdbScanRec; } diff --git a/ndb/src/ndbapi/ObjectMap.hpp b/ndb/src/ndbapi/ObjectMap.hpp index 4abb54b5081..f67774bb413 100644 --- a/ndb/src/ndbapi/ObjectMap.hpp +++ b/ndb/src/ndbapi/ObjectMap.hpp @@ -93,26 +93,28 @@ inline void * NdbObjectIdMap::unmap(Uint32 id, void *object){ - int i = id>>2; + Uint32 i = id>>2; // lock(); - - void * obj = m_map[i].m_obj; - if (object == obj) { - m_map[i].m_next = m_firstFree; - m_firstFree = i; - } else { - ndbout_c("Error: NdbObjectIdMap::::unmap(%u, 0x%x) obj=0x%x", id, object, obj); - return 0; - } - - // unlock(); - + if(i < m_size){ + void * obj = m_map[i].m_obj; + if (object == obj) { + m_map[i].m_next = m_firstFree; + m_firstFree = i; + } else { + ndbout_c("Error: NdbObjectIdMap::::unmap(%u, 0x%x) obj=0x%x", id, object, obj); + return 0; + } + + // unlock(); + #ifdef DEBUG_OBJECTMAP - ndbout_c("NdbObjectIdMap::unmap(%u) obj=0x%x", id, obj); + ndbout_c("NdbObjectIdMap::unmap(%u) obj=0x%x", id, obj); #endif - - return obj; + + return obj; + } + return 0; } inline void * @@ -120,7 +122,11 @@ NdbObjectIdMap::getObject(Uint32 id){ #ifdef DEBUG_OBJECTMAP ndbout_c("NdbObjectIdMap::getObject(%u) obj=0x%x", id, m_map[id>>2].m_obj); #endif - return m_map[id>>2].m_obj; + id >>= 2; + if(id < m_size){ + return m_map[id].m_obj; + } + return 0; } inline void @@ -129,7 +135,6 @@ NdbObjectIdMap::expand(Uint32 incSize){ MapEntry * tmp = (MapEntry*)malloc(newSize * sizeof(MapEntry)); memcpy(tmp, m_map, m_size * sizeof(MapEntry)); - free(m_map); m_map = tmp; for(Uint32 i = m_size; i z z) NdbConnection (scan) theScanningOp -> y theFirstOpInList -> y (until after openScan) + +# SU + +ScanOpLen: includes KeyInfo +New protocol + +# -- Impl. + +1) Scan uses one NdbReceiver per "parallelism" +2) Each NdbReceiver can handle up to "batch size" rows +3) API send one "pointer" per parallelism (prev. was one per row) +4) API handles each receiver independently. + It can "nextResult"-one, receive one and close-one +5) When a recevier has been "nextResult"-ed, the API can fetch from it again +6) After doing "openScan"-req, no wait is performed + (only possible to block on nextResult(true) or closeScan) + +7) Instead of "ack"-ing each row with length, +* Each row is sent in one lonw signal (unless to short) +* Each NdbReceiver is ack-ed with #rows and sum(#length) +* KeyInfo20 is one signal and included in sum(#length) + +8) The API receive(s) the data into NdbRecAttr-objects + (prev. it copied signals using new/delete) +9) KeyInfo20 is also received into a NdbRecAttr-object +10) + +# -- Close of scan + +1) Each NdbReciver gets a signal when it's complete + (0 rows is ack-ed) +2) The API then "closes" this receiver +3) The API can at any time close then scan for other reason(s) + (example dying) +4) This is signal:ed via a NEXT_SCANREQ (close = 1) +5) TC responds with a SCAN_TABCONF (close = 1) + + +# -- Sorted + +1) The sorted scan is transparent to TC + It's a API only impl. +2) The API makes the following adjustements: +* Scan all fragments simultaniously (max parallelism) +* Never return a row to the API if a NdbReciver is "outstanding" +* Sort Receivers (only top row as they already are sorted within) diff --git a/ndb/test/include/HugoTransactions.hpp b/ndb/test/include/HugoTransactions.hpp index 5ff1fef16bc..d859c463acf 100644 --- a/ndb/test/include/HugoTransactions.hpp +++ b/ndb/test/include/HugoTransactions.hpp @@ -38,12 +38,12 @@ public: int scanReadRecords(Ndb*, int records, int abort = 0, - int parallelism = 1, + int parallelism = 0, bool committed = false); int scanReadCommittedRecords(Ndb*, int records, int abort = 0, - int parallelism = 1); + int parallelism = 0); int pkReadRecords(Ndb*, int records, int batchsize = 1, @@ -52,20 +52,20 @@ public: int scanUpdateRecords(Ndb*, int records, int abort = 0, - int parallelism = 1); + int parallelism = 0); int scanUpdateRecords1(Ndb*, int records, int abort = 0, - int parallelism = 1); + int parallelism = 0); int scanUpdateRecords2(Ndb*, int records, int abort = 0, - int parallelism = 1); + int parallelism = 0); int scanUpdateRecords3(Ndb*, int records, int abort = 0, - int parallelism = 1); + int parallelism = 0); int pkUpdateRecords(Ndb*, int records, @@ -100,24 +100,6 @@ public: int batchsize = 1); protected: - int takeOverAndUpdateRecord(Ndb*, - NdbOperation*); -#if 0 - int setValueForAttr(NdbOperation*, - int attrId, - int rowId, - int updateId); -public: - int equalForAttr(NdbOperation*, - int attrId, - int rowId); -#endif - - int addRowToUpdate(Ndb* pNdb, - NdbConnection* pUpdTrans, - NdbOperation* pOrgOp); - - NDBT_ResultRow row; int m_defaultScanUpdateMethod; }; diff --git a/ndb/test/include/UtilTransactions.hpp b/ndb/test/include/UtilTransactions.hpp index b16ab74455e..1298028d591 100644 --- a/ndb/test/include/UtilTransactions.hpp +++ b/ndb/test/include/UtilTransactions.hpp @@ -34,24 +34,24 @@ public: int clearTable(Ndb*, int records = 0, - int parallelism = 240); + int parallelism = 0); // Delete all records from the table using a scan int clearTable1(Ndb*, int records = 0, - int parallelism = 16); + int parallelism = 0); // Delete all records from the table using a scan // Using batching int clearTable2(Ndb*, int records = 0, - int parallelism = 240); + int parallelism = 0); int clearTable3(Ndb*, int records = 0, - int parallelism = 240); + int parallelism = 0); int selectCount(Ndb*, - int parallelism = 16, + int parallelism = 0, int* count_rows = NULL, ScanLock lock = SL_Read, NdbConnection* pTrans = NULL); @@ -64,7 +64,7 @@ public: ReadCallBackFn* fn = NULL); int verifyIndex(Ndb*, const char* indexName, - int parallelism = 240, + int parallelism = 0, bool transactional = false); int copyTableData(Ndb*, @@ -88,7 +88,7 @@ private: int verifyUniqueIndex(Ndb*, const char* indexName, - int parallelism = 240, + int parallelism = 0, bool transactional = false); int scanAndCompareUniqueIndex(Ndb* pNdb, diff --git a/ndb/test/ndbapi/Makefile b/ndb/test/ndbapi/Makefile index 91f0c84c18e..2e20f05ecc9 100644 --- a/ndb/test/ndbapi/Makefile +++ b/ndb/test/ndbapi/Makefile @@ -4,12 +4,11 @@ include .defs.mk ifeq ($(NDB_OS), OSE) DIRS = basic flexBench flexAsynch else -DIRS = lmc-bench bank ronja +DIRS = lmc-bench ronja BIN_DIRS = \ flexAsynch \ flexBench \ flexHammer \ - flexScan \ flexTT \ create_tab \ create_all_tabs \ @@ -32,7 +31,6 @@ BIN_DIRS = \ testDataBuffers \ testDict \ acid \ - interpreterInTup \ telco \ indexTest \ test_event \ diff --git a/ndb/test/ndbapi/testBackup/Makefile b/ndb/test/ndbapi/testBackup/Makefile index ce0e404803c..abf47dcfb2d 100644 --- a/ndb/test/ndbapi/testBackup/Makefile +++ b/ndb/test/ndbapi/testBackup/Makefile @@ -3,7 +3,6 @@ include .defs.mk TYPE = ndbapitest BIN_TARGET = testBackup -BIN_TARGET_LIBS += bank SOURCES = testBackup.cpp include $(NDB_TOP)/Epilogue.mk diff --git a/ndb/test/ndbapi/testBackup/testBackup.cpp b/ndb/test/ndbapi/testBackup/testBackup.cpp index f9ae7ffcbbc..3d085e6a2d9 100644 --- a/ndb/test/ndbapi/testBackup/testBackup.cpp +++ b/ndb/test/ndbapi/testBackup/testBackup.cpp @@ -205,6 +205,7 @@ int runClearTable(NDBT_Context* ctx, NDBT_Step* step){ return NDBT_OK; } +#if 0 #include "../bank/Bank.hpp" @@ -394,6 +395,7 @@ int runRestoreBankAndVerify(NDBT_Context* ctx, NDBT_Step* step){ return result; } +#endif NDBT_TESTSUITE(testBackup); TESTCASE("BackupOne", @@ -411,6 +413,7 @@ TESTCASE("BackupOne", FINALIZER(runClearTable); } +#if 0 TESTCASE("BackupBank", "Test that backup and restore works during transaction load\n" " by backing up the bank" @@ -429,8 +432,8 @@ TESTCASE("BackupBank", STEP(runBackupBank); VERIFIER(runRestoreBankAndVerify); // FINALIZER(runDropBank); - } +#endif TESTCASE("NFMaster", "Test that backup behaves during node failiure\n"){ INITIALIZER(setMaster); diff --git a/ndb/test/ndbapi/testDataBuffers/testDataBuffers.cpp b/ndb/test/ndbapi/testDataBuffers/testDataBuffers.cpp index b8e0fef6cef..e9e60f34b59 100644 --- a/ndb/test/ndbapi/testDataBuffers/testDataBuffers.cpp +++ b/ndb/test/ndbapi/testDataBuffers/testDataBuffers.cpp @@ -84,6 +84,8 @@ static NdbSchemaCon* tcon = 0; static NdbSchemaOp* top = 0; static NdbConnection* con = 0; static NdbOperation* op = 0; +static NdbScanOperation* sop = 0; +static NdbResultSet* rs = 0; static int ndberror(char const* fmt, ...) @@ -438,9 +440,9 @@ testcase(int flag) int newkey = 0; if ((con = ndb->startTransaction()) == 0) return ndberror("startTransaction key=%d", key); - if ((op = con->getNdbOperation(tab)) == 0) + if ((sop = con->getNdbScanOperation(tab)) == 0) return ndberror("getNdbOperation key=%d", key); - if (op->openScanRead(1) < 0) + if ((rs = sop->readTuples(1)) == 0) return ndberror("openScanRead key=%d", key); { col& c = ccol[0]; @@ -481,10 +483,10 @@ testcase(int flag) } } } - if (con->executeScan() < 0) + if (con->execute(NoCommit) < 0) return ndberror("executeScan key=%d", key); int ret, cnt = 0; - while ((ret = con->nextScanResult()) == 0) { + while ((ret = rs->nextResult()) == 0) { if (key != newkey) return ndberror("unexpected key=%d newkey=%d", key, newkey); for (int i = 1; i < attrcnt; i++) { diff --git a/ndb/test/ndbapi/testGrep/Makefile b/ndb/test/ndbapi/testGrep/Makefile index 34fdd7113d0..6bad3d56a00 100644 --- a/ndb/test/ndbapi/testGrep/Makefile +++ b/ndb/test/ndbapi/testGrep/Makefile @@ -3,7 +3,6 @@ include .defs.mk TYPE = ndbapitest DIRS = verify BIN_TARGET = testGrep -BIN_TARGET_LIBS += bank SOURCES = testGrep.cpp include $(NDB_TOP)/Epilogue.mk diff --git a/ndb/test/ndbapi/testGrep/testGrep.cpp b/ndb/test/ndbapi/testGrep/testGrep.cpp index 4b870f6f9a9..b8966d15c5e 100644 --- a/ndb/test/ndbapi/testGrep/testGrep.cpp +++ b/ndb/test/ndbapi/testGrep/testGrep.cpp @@ -254,6 +254,7 @@ int runClearTable(NDBT_Context* ctx, NDBT_Step* step){ return NDBT_OK; } +#if 0 #include "../bank/Bank.hpp" @@ -444,6 +445,8 @@ int runRestoreBankAndVerify(NDBT_Context* ctx, NDBT_Step* step){ return result; } */ +#endif + NDBT_TESTSUITE(testGrep); TESTCASE("GrepBasic", "Test that Global Replication works on one table \n" @@ -473,7 +476,7 @@ TESTCASE("GrepNodeRestart", } - +#if 0 TESTCASE("GrepBank", "Test that grep and restore works during transaction load\n" @@ -495,6 +498,8 @@ TESTCASE("GrepBank", // FINALIZER(runDropBank); } +#endif + TESTCASE("NFMaster", "Test that grep behaves during node failiure\n"){ INITIALIZER(setMaster); diff --git a/ndb/test/ndbapi/testGrep/verify/Makefile b/ndb/test/ndbapi/testGrep/verify/Makefile index 4e6182de6b2..256e3c98f36 100644 --- a/ndb/test/ndbapi/testGrep/verify/Makefile +++ b/ndb/test/ndbapi/testGrep/verify/Makefile @@ -3,7 +3,6 @@ include .defs.mk TYPE = ndbapitest BIN_TARGET = testGrepVerify -BIN_TARGET_LIBS += bank SOURCES = testGrepVerify.cpp CFLAGS_testGrepVerify.cpp += -I$(call fixpath,$(NDB_TOP)/include/kernel) -I$(call fixpath,$(NDB_TOP)/include/mgmcommon) diff --git a/ndb/test/ndbapi/testIndex/testIndex.cpp b/ndb/test/ndbapi/testIndex/testIndex.cpp index 47db0b3cff7..d93c7f6a8a0 100644 --- a/ndb/test/ndbapi/testIndex/testIndex.cpp +++ b/ndb/test/ndbapi/testIndex/testIndex.cpp @@ -1130,7 +1130,7 @@ runUniqueNullTransactions(NDBT_Context* ctx, NDBT_Step* step){ if(!pTrans) goto done; sOp = pTrans->getNdbScanOperation(pTab->getName()); if(!sOp) goto done; - rs = sOp->readTuples(240, NdbScanOperation::LM_Exclusive); + rs = sOp->readTuples(NdbScanOperation::LM_Exclusive); if(!rs) goto done; if(pTrans->execute(NoCommit) == -1) goto done; while((eof = rs->nextResult(true)) == 0){ diff --git a/ndb/test/ndbapi/testOIBasic/testOIBasic.cpp b/ndb/test/ndbapi/testOIBasic/testOIBasic.cpp index a47d9d2099e..4b82cadffa5 100644 --- a/ndb/test/ndbapi/testOIBasic/testOIBasic.cpp +++ b/ndb/test/ndbapi/testOIBasic/testOIBasic.cpp @@ -551,7 +551,8 @@ struct Con { NdbConnection* m_tx; NdbOperation* m_op; NdbConnection* m_scantx; - NdbOperation* m_scanop; + NdbIndexScanOperation* m_scanop; + NdbResultSet* m_resultSet; enum ScanMode { ScanNo = 0, Committed, Latest, Exclusive }; ScanMode m_scanmode; enum ErrType { ErrNone = 0, ErrDeadlock, ErrOther }; @@ -632,7 +633,7 @@ Con::getNdbOperation(const Tab& tab) int Con::getNdbOperation(const ITab& itab, const Tab& tab) { - CHKCON((m_op = m_tx->getNdbOperation(itab.m_name, tab.m_name)) != 0, *this); + CHKCON((m_scanop = m_tx->getNdbIndexScanOperation(itab.m_name, tab.m_name)) != 0, *this); return 0; } @@ -664,7 +665,7 @@ int Con::setBound(int num, int type, const void* value) { assert(m_tx != 0 && m_op != 0); - CHKCON(m_op->setBound(num, type, value) == 0, *this); + CHKCON(m_scanop->setBound(num, type, value) == 0, *this); return 0; } @@ -680,7 +681,7 @@ int Con::openScanRead(unsigned parallelism) { assert(m_tx != 0 && m_op != 0); - CHKCON(m_op->openScanRead(parallelism) == 0, *this); + CHKCON((m_resultSet = m_scanop->readTuples(parallelism)) != 0, *this); return 0; } @@ -688,14 +689,14 @@ int Con::openScanExclusive(unsigned parallelism) { assert(m_tx != 0 && m_op != 0); - CHKCON(m_op->openScanExclusive(parallelism) == 0, *this); + CHKCON((m_resultSet = m_scanop->readTuplesExclusive(parallelism)) != 0, *this); return 0; } int Con::executeScan() { - CHKCON(m_tx->executeScan() == 0, *this); + CHKCON(m_tx->execute(NoCommit) == 0, *this); return 0; } @@ -703,7 +704,8 @@ int Con::nextScanResult() { int ret; - CHKCON((ret = m_tx->nextScanResult()) != -1, *this); + assert(m_resultSet != 0); + CHKCON((ret = m_resultSet->nextResult()) != -1, *this); assert(ret == 0 || ret == 1); return ret; } @@ -712,7 +714,7 @@ int Con::takeOverForUpdate(Con& scan) { assert(m_tx != 0 && scan.m_op != 0); - CHKCON((m_op = scan.m_op->takeOverForUpdate(m_tx)) != 0, scan); + CHKCON((m_op = scan.m_resultSet->updateTuple(m_tx)) != 0, scan); return 0; } @@ -720,7 +722,7 @@ int Con::takeOverForDelete(Con& scan) { assert(m_tx != 0 && scan.m_op != 0); - CHKCON((m_op = scan.m_op->takeOverForUpdate(m_tx)) != 0, scan); + CHKCON(scan.m_resultSet->deleteTuple(m_tx) == 0, scan); return 0; } diff --git a/ndb/test/ndbapi/testScan/ScanFunctions.hpp b/ndb/test/ndbapi/testScan/ScanFunctions.hpp index 36d01909861..e0a88ab9e94 100644 --- a/ndb/test/ndbapi/testScan/ScanFunctions.hpp +++ b/ndb/test/ndbapi/testScan/ScanFunctions.hpp @@ -80,7 +80,8 @@ ScanFunctions::scanReadFunctions(Ndb* pNdb, int sleepTime = 10; int check; NdbConnection *pTrans; - NdbOperation *pOp; + NdbScanOperation *pOp; + NdbResultSet *rs; while (true){ if (retryAttempt >= retryMax){ @@ -104,69 +105,36 @@ ScanFunctions::scanReadFunctions(Ndb* pNdb, // Execute the scan without defining a scan operation if(action != ExecuteScanWithOutOpenScan){ - - if (action == OnlyOneOpBeforeOpenScan){ - // There can only be one operation defined when calling openScan - NdbOperation* pOp3; - pOp3 = pTrans->getNdbOperation(tab.getName()); - if (pOp3 == NULL) { - ERR(pTrans->getNdbError()); - pNdb->closeTransaction(pTrans); - return NDBT_FAILED; - } - } - pOp = pTrans->getNdbOperation(tab.getName()); + pOp = pTrans->getNdbScanOperation(tab.getName()); if (pOp == NULL) { ERR(pTrans->getNdbError()); pNdb->closeTransaction(pTrans); return NDBT_FAILED; } - if (exclusive == true) - check = pOp->openScanExclusive(parallelism); - else - check = pOp->openScanRead(parallelism); - if( check == -1 ) { + + rs = pOp->readTuples(exclusive ? + NdbScanOperation::LM_Exclusive : + NdbScanOperation::LM_Read); + + if( rs == 0 ) { ERR(pTrans->getNdbError()); pNdb->closeTransaction(pTrans); return NDBT_FAILED; } - - if (action == OnlyOneScanPerTrans){ - // There can only be one operation in a scan transaction - NdbOperation* pOp4; - pOp4 = pTrans->getNdbOperation(tab.getName()); - if (pOp4 == NULL) { - ERR(pTrans->getNdbError()); - pNdb->closeTransaction(pTrans); - return NDBT_FAILED; - } - } - + if (action == OnlyOpenScanOnce){ // Call openScan one more time when it's already defined - check = pOp->openScanRead(parallelism); - if( check == -1 ) { + NdbResultSet* rs2 = pOp->readTuples(NdbScanOperation::LM_Read); + if( rs2 == 0 ) { ERR(pTrans->getNdbError()); pNdb->closeTransaction(pTrans); return NDBT_FAILED; } } - - if (action == OnlyOneOpInScanTrans){ - // Try to add another op to this scanTransaction - NdbOperation* pOp2; - pOp2 = pTrans->getNdbOperation(tab.getName()); - if (pOp2 == NULL) { - ERR(pTrans->getNdbError()); - pNdb->closeTransaction(pTrans); - return NDBT_FAILED; - } - } - - + if (action==EqualAfterOpenScan){ check = pOp->equal(tab.getColumn(0)->getName(), 10); if( check == -1 ) { @@ -191,7 +159,7 @@ ScanFunctions::scanReadFunctions(Ndb* pNdb, } } } - check = pTrans->executeScan(); + check = pTrans->execute(NoCommit); if( check == -1 ) { ERR(pTrans->getNdbError()); pNdb->closeTransaction(pTrans); @@ -203,7 +171,7 @@ ScanFunctions::scanReadFunctions(Ndb* pNdb, bool abortTrans = (action==CloseWithoutStop); int eof; int rows = 0; - eof = pTrans->nextScanResult(); + eof = rs->nextResult(); while(eof == 0){ rows++; @@ -213,7 +181,7 @@ ScanFunctions::scanReadFunctions(Ndb* pNdb, if (action != CloseWithoutStop){ // Test that we can closeTrans without stopScan - check = pTrans->stopScan(); + rs->close(); if( check == -1 ) { ERR(pTrans->getNdbError()); pNdb->closeTransaction(pTrans); @@ -236,7 +204,7 @@ ScanFunctions::scanReadFunctions(Ndb* pNdb, } } - eof = pTrans->nextScanResult(); + eof = rs->nextResult(); } if (eof == -1) { const NdbError err = pTrans->getNdbError(); @@ -246,7 +214,7 @@ ScanFunctions::scanReadFunctions(Ndb* pNdb, // Be cruel, call nextScanResult after error for(int i=0; i<10; i++){ - eof =pTrans->nextScanResult(); + eof = rs->nextResult(); if(eof == 0){ g_err << "nextScanResult returned eof = " << eof << endl << " That is an error when there are no more records" << endl; @@ -276,7 +244,7 @@ ScanFunctions::scanReadFunctions(Ndb* pNdb, if (action == NextScanWhenNoMore){ g_info << "Calling nextScanresult when there are no more records" << endl; for(int i=0; i<10; i++){ - eof =pTrans->nextScanResult(); + eof = rs->nextResult(); if(eof == 0){ g_err << "nextScanResult returned eof = " << eof << endl << " That is an error when there are no more records" << endl; @@ -285,7 +253,7 @@ ScanFunctions::scanReadFunctions(Ndb* pNdb, } } - if(action ==CheckInactivityBeforeClose){ + if(action == CheckInactivityBeforeClose){ // Sleep for a long time before calling close g_info << "NdbSleep_SecSleep(5) before close transaction" << endl; NdbSleep_SecSleep(5); diff --git a/ndb/test/ndbapi/testScanInterpreter/ScanInterpretTest.hpp b/ndb/test/ndbapi/testScanInterpreter/ScanInterpretTest.hpp index 3862de34111..e8a0d4b6dca 100644 --- a/ndb/test/ndbapi/testScanInterpreter/ScanInterpretTest.hpp +++ b/ndb/test/ndbapi/testScanInterpreter/ScanInterpretTest.hpp @@ -197,7 +197,7 @@ ScanInterpretTest::scanRead(Ndb* pNdb, int retryMax = 100; int check; NdbConnection *pTrans; - NdbOperation *pOp; + NdbScanOperation *pOp; while (true){ @@ -220,16 +220,17 @@ ScanInterpretTest::scanRead(Ndb* pNdb, return NDBT_FAILED; } - pOp = pTrans->getNdbOperation(tab.getName()); + pOp = pTrans->getNdbScanOperation(tab.getName()); if (pOp == NULL) { ERR(pTrans->getNdbError()); pNdb->closeTransaction(pTrans); return NDBT_FAILED; } - - check = pOp->openScanRead(parallelism); - //check = pOp->openScanExclusive(parallelism); - if( check == -1 ) { + + NdbResultSet * rs = pOp->readTuples(NdbScanOperation::LM_Read, + 0, parallelism); + + if( rs == 0 ) { ERR(pTrans->getNdbError()); pNdb->closeTransaction(pTrans); return NDBT_FAILED; @@ -250,7 +251,7 @@ ScanInterpretTest::scanRead(Ndb* pNdb, return NDBT_FAILED; } } - check = pTrans->executeScan(); + check = pTrans->execute(NoCommit); if( check == -1 ) { ERR(pTrans->getNdbError()); pNdb->closeTransaction(pTrans); @@ -261,32 +262,22 @@ ScanInterpretTest::scanRead(Ndb* pNdb, int rows = 0; NdbConnection* pInsTrans; - while((eof = pTrans->nextScanResult(true)) == 0){ - pInsTrans = pNdb->startTransaction(); - if (pInsTrans == NULL) { - const NdbError err = pNdb->getNdbError(); - ERR(err); - return NDBT_FAILED; - } + while((eof = rs->nextResult(true)) == 0){ do { rows++; - if (addRowToInsert(pNdb, pInsTrans) != 0){ + if (addRowToInsert(pNdb, pTrans) != 0){ pNdb->closeTransaction(pTrans); - pNdb->closeTransaction(pInsTrans); return NDBT_FAILED; } - } while((eof = pTrans->nextScanResult(false)) == 0); + } while((eof = rs->nextResult(false)) == 0); - check = pInsTrans->execute(Commit); + check = pTrans->execute(Commit); if( check == -1 ) { - const NdbError err = pInsTrans->getNdbError(); + const NdbError err = pTrans->getNdbError(); ERR(err); - pNdb->closeTransaction(pInsTrans); pNdb->closeTransaction(pTrans); return NDBT_FAILED; } - pNdb->closeTransaction(pInsTrans); - } if (eof == -1) { const NdbError err = pTrans->getNdbError(); @@ -322,7 +313,7 @@ ScanInterpretTest::scanReadVerify(Ndb* pNdb, const int retryMax = 100; int check; NdbConnection *pTrans; - NdbOperation *pOp; + NdbScanOperation *pOp; while (true){ @@ -346,7 +337,7 @@ ScanInterpretTest::scanReadVerify(Ndb* pNdb, } - pOp = pTrans->getNdbOperation(tab.getName()); + pOp = pTrans->getNdbScanOperation(tab.getName()); if (pOp == NULL) { if (pOp->getValue("KOL2") == 0){ ERR(pNdb->getNdbError()); return NDBT_FAILED; @@ -357,9 +348,10 @@ ScanInterpretTest::scanReadVerify(Ndb* pNdb, pNdb->closeTransaction(pTrans); return NDBT_FAILED; } - - check = pOp->openScanRead(parallelism); - if( check == -1 ) { + + NdbResultSet * rs = pOp->readTuples(NdbScanOperation::LM_Read, + 0, parallelism); + if( rs == 0 ) { ERR(pTrans->getNdbError()); pNdb->closeTransaction(pTrans); return NDBT_FAILED; @@ -382,7 +374,7 @@ ScanInterpretTest::scanReadVerify(Ndb* pNdb, return NDBT_FAILED; } } - check = pTrans->executeScan(); + check = pTrans->execute(NoCommit); if( check == -1 ) { ERR(pTrans->getNdbError()); pNdb->closeTransaction(pTrans); @@ -400,7 +392,7 @@ ScanInterpretTest::scanReadVerify(Ndb* pNdb, NdbConnection* pExistTrans; NdbConnection* pNoExistTrans; - while((eof = pTrans->nextScanResult(true)) == 0){ + while((eof = rs->nextResult(true)) == 0){ pExistTrans = pNdb->startTransaction(); if (pExistTrans == NULL) { const NdbError err = pNdb->getNdbError(); @@ -432,7 +424,7 @@ ScanInterpretTest::scanReadVerify(Ndb* pNdb, return NDBT_FAILED; } } - } while((eof = pTrans->nextScanResult(false)) == 0); + } while((eof = rs->nextResult(false)) == 0); // Execute the transaction containing reads of diff --git a/ndb/test/src/HugoOperations.cpp b/ndb/test/src/HugoOperations.cpp index 91263aa29b4..f4b814adee2 100644 --- a/ndb/test/src/HugoOperations.cpp +++ b/ndb/test/src/HugoOperations.cpp @@ -295,6 +295,7 @@ int HugoOperations::pkDeleteRecord(Ndb* pNdb, int HugoOperations::scanReadRecords(Ndb* pNdb, Uint32 parallelism, ScanLock lock){ +#ifdef JONAS_NOT_DONE NdbConnection * pCon = pNdb->hupp(pTrans); NDBT_ResultRow * m_tmpRow = new NDBT_ResultRow(tab); ScanTmp tmp(pCon, m_tmpRow); @@ -350,6 +351,7 @@ int HugoOperations::scanReadRecords(Ndb* pNdb, m_scans.push_back(tmp); return 0; +#endif } int HugoOperations::executeScanRead(Ndb* pNdb){ @@ -414,6 +416,7 @@ int HugoOperations::execute_Commit(Ndb* pNdb, int HugoOperations::run(ScanTmp & tmp){ +#if JONAS_NOT_DONE int count = 0; if(tmp.m_op == ScanTmp::DONE) abort(); @@ -443,6 +446,7 @@ HugoOperations::run(ScanTmp & tmp){ if(count == 0) return 626; +#endif return 0; } diff --git a/ndb/test/src/HugoTransactions.cpp b/ndb/test/src/HugoTransactions.cpp index 7f12484ddc8..7c26baa3ec2 100644 --- a/ndb/test/src/HugoTransactions.cpp +++ b/ndb/test/src/HugoTransactions.cpp @@ -48,7 +48,7 @@ HugoTransactions::scanReadRecords(Ndb* pNdb, const int retryMax = 100; int check; NdbConnection *pTrans; - NdbOperation *pOp; + NdbScanOperation *pOp; while (true){ @@ -72,19 +72,18 @@ HugoTransactions::scanReadRecords(Ndb* pNdb, return NDBT_FAILED; } - pOp = pTrans->getNdbOperation(tab.getName()); + pOp = pTrans->getNdbScanOperation(tab.getName()); if (pOp == NULL) { ERR(pTrans->getNdbError()); pNdb->closeTransaction(pTrans); return NDBT_FAILED; } - if (committed == true) - check = pOp->openScanReadCommitted(parallelism); - else - check = pOp->openScanRead(parallelism); + NdbResultSet * rs; + rs = pOp ->readTuples(committed ? NdbScanOperation::LM_CommittedRead : + NdbScanOperation::LM_Read); - if( check == -1 ) { + if( rs == 0 ) { ERR(pTrans->getNdbError()); pNdb->closeTransaction(pTrans); return NDBT_FAILED; @@ -106,7 +105,7 @@ HugoTransactions::scanReadRecords(Ndb* pNdb, } } - check = pTrans->executeScan(); + check = pTrans->execute(NoCommit); if( check == -1 ) { const NdbError err = pTrans->getNdbError(); if (err.status == NdbError::TemporaryError){ @@ -130,12 +129,10 @@ HugoTransactions::scanReadRecords(Ndb* pNdb, if (abortCount < abortPercent) abortTrans = true; } - + int eof; int rows = 0; - eof = pTrans->nextScanResult(); - - while(eof == 0){ + while((eof = rs->nextResult(true)) == 0){ rows++; if (calc.verifyRowValues(&row) != 0){ pNdb->closeTransaction(pTrans); @@ -145,22 +142,20 @@ HugoTransactions::scanReadRecords(Ndb* pNdb, if (abortCount == rows && abortTrans == true){ ndbout << "Scan is aborted" << endl; g_info << "Scan is aborted" << endl; - check = pTrans->stopScan(); + rs->close(); if( check == -1 ) { ERR(pTrans->getNdbError()); pNdb->closeTransaction(pTrans); return NDBT_FAILED; } - + pNdb->closeTransaction(pTrans); return NDBT_OK; } - - eof = pTrans->nextScanResult(); } if (eof == -1) { const NdbError err = pTrans->getNdbError(); - + if (err.status == NdbError::TemporaryError){ ERR_INFO(err); pNdb->closeTransaction(pTrans); @@ -199,106 +194,6 @@ HugoTransactions::scanReadRecords(Ndb* pNdb, #define RESTART_SCAN 99 -// Take over one record from pOrgOp and update it -int -HugoTransactions::takeOverAndUpdateRecord(Ndb* pNdb, - NdbOperation* pOrgOp){ - int retryAttempt = 0; - const int retryMax = 10; - int check; - NdbConnection *pUpdTrans; - NdbOperation *pUpdOp; - - while (true){ - - if (retryAttempt >= retryMax){ - g_info << "ERROR: has retried this operation " << retryAttempt - << " times, failing!" << endl; - return NDBT_FAILED; - } - - pUpdTrans = pNdb->startTransaction(); - if (pUpdTrans == NULL) { - const NdbError err = pNdb->getNdbError(); - - if (err.status == NdbError::TemporaryError){ - ERR(err); - NdbSleep_MilliSleep(50); - retryAttempt++; - continue; - } - ERR(err); - return NDBT_FAILED; - } - - if ((pUpdOp = pOrgOp->takeOverForUpdate(pUpdTrans)) == NULL){ - ERR(pNdb->getNdbError()); - return NDBT_FAILED; - } - - int updates = calc.getUpdatesValue(&row) + 1; - int id = calc.getIdValue(&row); - - // Set a calculated value for each non-PK attribute in this table - for (int a = 0; agetPrimaryKey() == false){ - if(setValueForAttr(pUpdOp, a, id, updates ) != 0){ - ERR(pUpdTrans->getNdbError()); - pNdb->closeTransaction(pUpdTrans); - return NDBT_FAILED; - } - } - } - check = pUpdTrans->execute( Commit ); - if(check == -1 ) { - const NdbError err = pUpdTrans->getNdbError(); - pNdb->closeTransaction(pUpdTrans); - - ERR(err); - if(err.code == 499 || err.code == 250){ - return RESTART_SCAN; - } - - switch(err.status){ - case NdbError::Success: - g_info << "ERROR: NdbError reports success when transcaction failed" - << endl; - return NDBT_FAILED; - break; - - case NdbError::TemporaryError: - NdbSleep_MilliSleep(50+50*retryAttempt); - retryAttempt++; - continue; - break; - - case NdbError::UnknownResult: - return NDBT_FAILED; - break; - - default: - case NdbError::PermanentError: - switch (err.code){ - case 499: - case 250: - return NDBT_TEMPORARY; - - default: - return NDBT_FAILED; - break; - } - break; - } - } - else{ - pNdb->closeTransaction(pUpdTrans); - } - - return NDBT_OK; - } - return NDBT_FAILED; -} - int HugoTransactions::scanUpdateRecords(Ndb* pNdb, int records, @@ -320,6 +215,9 @@ HugoTransactions::scanUpdateRecords1(Ndb* pNdb, int records, int abortPercent, int parallelism){ +#if 1 + return scanUpdateRecords3(pNdb, records, abortPercent, 1); +#else int retryAttempt = 0; const int retryMax = 100; int check; @@ -472,9 +370,9 @@ HugoTransactions::scanUpdateRecords1(Ndb* pNdb, return NDBT_OK; } return NDBT_FAILED; +#endif } - // Scan all records exclusive and update // them batched by asking nextScanResult to // give us all cached records before fetching new @@ -484,6 +382,9 @@ HugoTransactions::scanUpdateRecords2(Ndb* pNdb, int records, int abortPercent, int parallelism){ +#if 1 + return scanUpdateRecords3(pNdb, records, abortPercent, parallelism); +#else int retryAttempt = 0; const int retryMax = 100; int check; @@ -642,35 +543,9 @@ HugoTransactions::scanUpdateRecords2(Ndb* pNdb, return NDBT_OK; } return NDBT_FAILED; +#endif } -int -HugoTransactions::addRowToUpdate(Ndb* pNdb, - NdbConnection* pUpdTrans, - NdbOperation* pOrgOp){ - - int updates = calc.getUpdatesValue(&row) + 1; - int r = calc.getIdValue(&row); - - NdbOperation* pUpdOp = pOrgOp->takeOverForUpdate(pUpdTrans); - if (pUpdOp == NULL){ - ERR(pNdb->getNdbError()); - return NDBT_FAILED; - } - - for(int a = 0; agetPrimaryKey() == false){ - if(setValueForAttr(pUpdOp, a, r, updates ) != 0){ - ERR(pUpdTrans->getNdbError()); - pNdb->closeTransaction(pUpdTrans); - return NDBT_FAILED; - } - } - } - return NDBT_OK; -} - - int HugoTransactions::scanUpdateRecords3(Ndb* pNdb, int records, @@ -759,7 +634,6 @@ HugoTransactions::scanUpdateRecords3(Ndb* pNdb, } const int updates = calc.getUpdatesValue(&row) + 1; const int r = calc.getIdValue(&row); - for(int a = 0; agetPrimaryKey() == false){ if(setValueForAttr(pUp, a, r, updates ) != 0){ @@ -794,7 +668,7 @@ HugoTransactions::scanUpdateRecords3(Ndb* pNdb, return NDBT_FAILED; } } - + const NdbError err = pTrans->getNdbError(); if( check == -1 ) { pNdb->closeTransaction(pTrans); @@ -2083,7 +1957,7 @@ HugoTransactions::indexReadRecords(Ndb* pNdb, int check; NdbConnection *pTrans; NdbOperation *pOp; - NdbScanOperation *sOp; + NdbIndexScanOperation *sOp; NdbResultSet * rs; const NdbDictionary::Index* pIndex @@ -2134,7 +2008,7 @@ HugoTransactions::indexReadRecords(Ndb* pNdb, } check = pOp->readTuple(); } else { - pOp = sOp = pTrans->getNdbScanOperation(idxName, tab.getName()); + pOp = sOp = pTrans->getNdbIndexScanOperation(idxName, tab.getName()); if (sOp == NULL) { ERR(pTrans->getNdbError()); pNdb->closeTransaction(pTrans); @@ -2284,7 +2158,7 @@ HugoTransactions::indexUpdateRecords(Ndb* pNdb, return NDBT_FAILED; } } else { - pOp = sOp = pTrans->getNdbScanOperation(idxName, tab.getName()); + pOp = sOp = pTrans->getNdbIndexScanOperation(idxName, tab.getName()); if (pOp == NULL) { ERR(pTrans->getNdbError()); pNdb->closeTransaction(pTrans); diff --git a/ndb/test/src/NDBT_Tables.cpp b/ndb/test/src/NDBT_Tables.cpp index 548e755a3fb..8fd2d4042fd 100644 --- a/ndb/test/src/NDBT_Tables.cpp +++ b/ndb/test/src/NDBT_Tables.cpp @@ -835,7 +835,7 @@ NDBT_Tables::printAll(){ if (tab == NULL){ abort(); } - ndbout << (* tab) << endl; + ndbout << (* (NDBT_Table*)tab) << endl; } return NDBT_OK; diff --git a/ndb/test/src/UtilTransactions.cpp b/ndb/test/src/UtilTransactions.cpp index 2e6ff360123..060368322c4 100644 --- a/ndb/test/src/UtilTransactions.cpp +++ b/ndb/test/src/UtilTransactions.cpp @@ -47,10 +47,14 @@ UtilTransactions::clearTable(Ndb* pNdb, } } + int UtilTransactions::clearTable1(Ndb* pNdb, int records, int parallelism){ +#if 1 + return clearTable3(pNdb, records, 1); +#else // Scan all records exclusive and delete // them one by one int retryAttempt = 0; @@ -191,12 +195,16 @@ UtilTransactions::clearTable1(Ndb* pNdb, return NDBT_OK; } return NDBT_FAILED; +#endif } int UtilTransactions::clearTable2(Ndb* pNdb, int records, int parallelism){ +#if 1 + return clearTable3(pNdb, records, parallelism); +#else // Scan all records exclusive and delete // them one by one int retryAttempt = 0; @@ -336,6 +344,7 @@ UtilTransactions::clearTable2(Ndb* pNdb, return NDBT_OK; } return NDBT_FAILED; +#endif } int @@ -451,7 +460,7 @@ UtilTransactions::copyTableData(Ndb* pNdb, int parallelism = 240; int check; NdbConnection *pTrans; - NdbOperation *pOp; + NdbScanOperation *pOp; NDBT_ResultRow row(tab); while (true){ @@ -477,14 +486,15 @@ UtilTransactions::copyTableData(Ndb* pNdb, return NDBT_FAILED; } - pOp = pTrans->getNdbOperation(tab.getName()); + pOp = pTrans->getNdbScanOperation(tab.getName()); if (pOp == NULL) { ERR(pTrans->getNdbError()); pNdb->closeTransaction(pTrans); return NDBT_FAILED; } - check = pOp->openScanRead(parallelism); + NdbResultSet* rs = pOp->readTuples(NdbScanOperation::LM_Read, + parallelism); if( check == -1 ) { ERR(pTrans->getNdbError()); pNdb->closeTransaction(pTrans); @@ -508,7 +518,7 @@ UtilTransactions::copyTableData(Ndb* pNdb, } } - check = pTrans->executeScan(); + check = pTrans->execute(NoCommit); if( check == -1 ) { ERR(pTrans->getNdbError()); pNdb->closeTransaction(pTrans); @@ -516,39 +526,27 @@ UtilTransactions::copyTableData(Ndb* pNdb, } int eof; - NdbConnection* pInsTrans; - - while((eof = pTrans->nextScanResult(true)) == 0){ - pInsTrans = pNdb->startTransaction(); - if (pInsTrans == NULL) { - const NdbError err = pNdb->getNdbError(); - ERR(err); - pNdb->closeTransaction(pInsTrans); - return NDBT_FAILED; - } + while((eof = rs->nextResult(true)) == 0){ do { insertedRows++; - if (addRowToInsert(pNdb, pInsTrans, row, destName) != 0){ - pNdb->closeTransaction(pInsTrans); + if (addRowToInsert(pNdb, pTrans, row, destName) != 0){ pNdb->closeTransaction(pTrans); return NDBT_FAILED; } - } while((eof = pTrans->nextScanResult(false)) == 0); - - check = pInsTrans->execute(Commit); + } while((eof = rs->nextResult(false)) == 0); + + check = pTrans->execute(Commit); + pTrans->releaseCompletedOperations(); if( check == -1 ) { - const NdbError err = pInsTrans->getNdbError(); + const NdbError err = pTrans->getNdbError(); ERR(err); - pNdb->closeTransaction(pInsTrans); pNdb->closeTransaction(pTrans); return NDBT_FAILED; } - pNdb->closeTransaction(pInsTrans); - } if (eof == -1) { const NdbError err = pTrans->getNdbError(); - + if (err.status == NdbError::TemporaryError){ ERR(err); pNdb->closeTransaction(pTrans); @@ -562,29 +560,16 @@ UtilTransactions::copyTableData(Ndb* pNdb, pNdb->closeTransaction(pTrans); return NDBT_FAILED; } - + pNdb->closeTransaction(pTrans); - + g_info << insertedRows << " rows copied" << endl; - + return NDBT_OK; } return NDBT_FAILED; } -int -UtilTransactions::addRowToDelete(Ndb* pNdb, - NdbConnection* pDelTrans, - NdbOperation* pOrgOp){ - - NdbOperation* pDelOp = pOrgOp->takeOverForDelete(pDelTrans); - if (pDelOp == NULL){ - ERR(pNdb->getNdbError()); - return NDBT_FAILED; - } - return NDBT_OK; -} - int UtilTransactions::addRowToInsert(Ndb* pNdb, NdbConnection* pInsTrans, @@ -621,101 +606,6 @@ UtilTransactions::addRowToInsert(Ndb* pNdb, return NDBT_OK; } -// Take over one record from pOrgOp and delete it -int -UtilTransactions::takeOverAndDeleteRecord(Ndb* pNdb, - NdbOperation* pOrgOp){ - - int retryAttempt = 0; - const int retryMax = 10; - int check; - NdbConnection *pDelTrans; - NdbOperation *pDelOp; - - while (true){ - - if (retryAttempt >= retryMax){ - g_info << "ERROR: has retried this operation " << retryAttempt - << " times, failing!" << endl; - return NDBT_FAILED; - } - - pDelTrans = pNdb->startTransaction(); - if (pDelTrans == NULL) { - const NdbError err = pNdb->getNdbError(); - - if (err.status == NdbError::TemporaryError){ - ERR(err); - NdbSleep_MilliSleep(50); - retryAttempt++; - continue; - } - ERR(err); - return NDBT_FAILED; - } - - if ((pDelOp = pOrgOp->takeOverForDelete(pDelTrans)) == NULL){ - ERR(pNdb->getNdbError()); - return NDBT_FAILED; - } - -#if 0 - // It should not be necessary to call deleteTuple HERE!!! - check = pDelOp->deleteTuple(); - if( check == -1 ) { - ERR(pDelTrans->getNdbError()); - pNdb->closeTransaction(pDelTrans); - return NDBT_FAILED; - } -#endif - - check = pDelTrans->execute( Commit ); - if(check == -1 ) { - const NdbError err = pDelTrans->getNdbError(); - pNdb->closeTransaction(pDelTrans); - - ERR(err); - if(err.code == 250 || err.code == 499) - return RESTART_SCAN; - - switch(err.status){ - case NdbError::Success: - g_info << "ERROR: NdbError reports success when transcaction failed" - << endl; - RETURN_FAIL(err); - break; - - case NdbError::TemporaryError: - NdbSleep_MilliSleep(50+50*retryAttempt); - retryAttempt++; - continue; - break; - - case NdbError::UnknownResult: - RETURN_FAIL(err); - break; - - default: - case NdbError::PermanentError: - switch (err.classification){ - default: - RETURN_FAIL(err); - break; - } - break; - } - } - else{ - pNdb->closeTransaction(pDelTrans); - } - - return NDBT_OK; - } - return NDBT_FAILED; -} - - - int UtilTransactions::scanReadRecords(Ndb* pNdb, @@ -730,7 +620,7 @@ UtilTransactions::scanReadRecords(Ndb* pNdb, const int retryMax = 100; int check; NdbConnection *pTrans; - NdbOperation *pOp; + NdbScanOperation *pOp; NDBT_ResultRow row(tab); while (true){ @@ -755,18 +645,18 @@ UtilTransactions::scanReadRecords(Ndb* pNdb, return NDBT_FAILED; } - pOp = pTrans->getNdbOperation(tab.getName()); + pOp = pTrans->getNdbScanOperation(tab.getName()); if (pOp == NULL) { ERR(pTrans->getNdbError()); pNdb->closeTransaction(pTrans); return NDBT_FAILED; } - if (exclusive == true) - check = pOp->openScanExclusive(parallelism); - else - check = pOp->openScanRead(parallelism); - if( check == -1 ) { + NdbResultSet * rs = pOp->readTuples(exclusive ? + NdbScanOperation::LM_Exclusive : + NdbScanOperation::LM_Read, + 0, parallelism); + if( rs == 0 ) { ERR(pTrans->getNdbError()); pNdb->closeTransaction(pTrans); return NDBT_FAILED; @@ -778,7 +668,7 @@ UtilTransactions::scanReadRecords(Ndb* pNdb, pNdb->closeTransaction(pTrans); return NDBT_FAILED; } - + // Call getValue for all the attributes supplied in attrib_list // ************************************************ for (int a = 0; a < noAttribs; a++){ @@ -793,8 +683,8 @@ UtilTransactions::scanReadRecords(Ndb* pNdb, } } // ************************************************* - - check = pTrans->executeScan(); + + check = pTrans->execute(NoCommit); if( check == -1 ) { const NdbError err = pTrans->getNdbError(); @@ -812,15 +702,14 @@ UtilTransactions::scanReadRecords(Ndb* pNdb, int eof; int rows = 0; - eof = pTrans->nextScanResult(); - while(eof == 0){ + + while((eof = rs->nextResult()) == 0){ rows++; // Call callback for each record returned if(fn != NULL) fn(&row); - eof = pTrans->nextScanResult(); } if (eof == -1) { const NdbError err = pTrans->getNdbError(); @@ -856,14 +745,15 @@ UtilTransactions::selectCount(Ndb* pNdb, int parallelism, int* count_rows, ScanLock lock, - NdbConnection* pBuddyTrans){ + NdbConnection* pTrans){ int retryAttempt = 0; const int retryMax = 100; int check; - NdbConnection *pTrans; - NdbOperation *pOp; + NdbScanOperation *pOp; + if(!pTrans) + pTrans = pNdb->startTransaction(); while (true){ if (retryAttempt >= retryMax){ @@ -871,39 +761,27 @@ UtilTransactions::selectCount(Ndb* pNdb, << " times, failing!" << endl; return NDBT_FAILED; } - - pTrans = pNdb->hupp(pBuddyTrans); - if (pTrans == NULL) { - const NdbError err = pNdb->getNdbError(); - - if (err.status == NdbError::TemporaryError){ - NdbSleep_MilliSleep(50); - retryAttempt++; - continue; - } - ERR(err); - return NDBT_FAILED; - } - pOp = pTrans->getNdbOperation(tab.getName()); + pOp = pTrans->getNdbScanOperation(tab.getName()); if (pOp == NULL) { ERR(pTrans->getNdbError()); pNdb->closeTransaction(pTrans); return NDBT_FAILED; } + NdbResultSet * rs; switch(lock){ case SL_ReadHold: - check = pOp->openScanReadHoldLock(parallelism); + rs = pOp->readTuples(NdbScanOperation::LM_Read); break; case SL_Exclusive: - check = pOp->openScanExclusive(parallelism); + rs = pOp->readTuples(NdbScanOperation::LM_Exclusive); break; case SL_Read: default: - check = pOp->openScanRead(parallelism); + rs = pOp->readTuples(NdbScanOperation::LM_CommittedRead); } - if( check == -1 ) { + if( rs == 0) { ERR(pTrans->getNdbError()); pNdb->closeTransaction(pTrans); return NDBT_FAILED; @@ -922,9 +800,9 @@ UtilTransactions::selectCount(Ndb* pNdb, return NDBT_FAILED; } } - - - check = pTrans->executeScan(); + + + check = pTrans->execute(NoCommit); if( check == -1 ) { ERR(pTrans->getNdbError()); pNdb->closeTransaction(pTrans); @@ -933,15 +811,14 @@ UtilTransactions::selectCount(Ndb* pNdb, int eof; int rows = 0; - eof = pTrans->nextScanResult(); + - while(eof == 0){ + while((eof = rs->nextResult()) == 0){ rows++; - eof = pTrans->nextScanResult(); } if (eof == -1) { const NdbError err = pTrans->getNdbError(); - + if (err.status == NdbError::TemporaryError){ pNdb->closeTransaction(pTrans); NdbSleep_MilliSleep(50); @@ -952,7 +829,7 @@ UtilTransactions::selectCount(Ndb* pNdb, pNdb->closeTransaction(pTrans); return NDBT_FAILED; } - + pNdb->closeTransaction(pTrans); if (count_rows != NULL){ @@ -963,7 +840,6 @@ UtilTransactions::selectCount(Ndb* pNdb, } return NDBT_FAILED; } - int UtilTransactions::verifyIndex(Ndb* pNdb, @@ -1028,7 +904,7 @@ UtilTransactions::scanAndCompareUniqueIndex(Ndb* pNdb, const int retryMax = 100; int check; NdbConnection *pTrans; - NdbOperation *pOp; + NdbScanOperation *pOp; NDBT_ResultRow row(tab); parallelism = 1; @@ -1055,20 +931,21 @@ UtilTransactions::scanAndCompareUniqueIndex(Ndb* pNdb, return NDBT_FAILED; } - pOp = pTrans->getNdbOperation(tab.getName()); + pOp = pTrans->getNdbScanOperation(tab.getName()); if (pOp == NULL) { ERR(pTrans->getNdbError()); pNdb->closeTransaction(pTrans); return NDBT_FAILED; } + NdbResultSet* rs; if(transactional){ - check = pOp->openScanReadHoldLock(parallelism); + rs = pOp->readTuples(NdbScanOperation::LM_Read, 0, parallelism); } else { - check = pOp->openScanRead(parallelism); + rs = pOp->readTuples(NdbScanOperation::LM_CommittedRead, 0, parallelism); } - - if( check == -1 ) { + + if( rs == 0 ) { ERR(pTrans->getNdbError()); pNdb->closeTransaction(pTrans); return NDBT_FAILED; @@ -1091,10 +968,10 @@ UtilTransactions::scanAndCompareUniqueIndex(Ndb* pNdb, } } - check = pTrans->executeScan(); + check = pTrans->execute(NoCommit); if( check == -1 ) { const NdbError err = pTrans->getNdbError(); - + if (err.status == NdbError::TemporaryError){ ERR(err); pNdb->closeTransaction(pTrans); @@ -1109,14 +986,14 @@ UtilTransactions::scanAndCompareUniqueIndex(Ndb* pNdb, int eof; int rows = 0; - eof = pTrans->nextScanResult(); - while(eof == 0){ + + while((eof = rs->nextResult()) == 0){ rows++; - + // ndbout << row.c_str().c_str() << endl; - - + + if (readRowFromTableAndIndex(pNdb, pTrans, indexName, @@ -1124,11 +1001,6 @@ UtilTransactions::scanAndCompareUniqueIndex(Ndb* pNdb, pNdb->closeTransaction(pTrans); return NDBT_FAILED; } - - - - - eof = pTrans->nextScanResult(); } if (eof == -1) { const NdbError err = pTrans->getNdbError(); @@ -1265,13 +1137,13 @@ UtilTransactions::readRowFromTableAndIndex(Ndb* pNdb, * Read the record from INDEX_TABLE */ NdbIndexOperation* pIndexOp= NULL; - NdbScanOperation *pScanOp= NULL; + NdbIndexScanOperation *pScanOp= NULL; { void* pOpCheck= NULL; if (indexType == NdbDictionary::Index::UniqueHashIndex) { pOpCheck= pIndexOp= pTrans1->getNdbIndexOperation(indexName, tab.getName()); } else { - pOpCheck= pScanOp= pTrans1->getNdbScanOperation(indexName, tab.getName()); + pOpCheck= pScanOp= pTrans1->getNdbIndexScanOperation(indexName, tab.getName()); } if (pOpCheck == NULL) { @@ -1308,7 +1180,7 @@ UtilTransactions::readRowFromTableAndIndex(Ndb* pNdb, // setBound not possible for null attributes if ( !row.attributeStore(col->getName())->isNULL() ) { r = pScanOp->setBound(col->getName(), - NdbOperation::BoundEQ, + NdbIndexScanOperation::BoundEQ, row.attributeStore(col->getName())->aRef()); } } diff --git a/ndb/tools/create_index/create_index.cpp b/ndb/tools/create_index/create_index.cpp index dc9e6c606d6..f883755ea24 100644 --- a/ndb/tools/create_index/create_index.cpp +++ b/ndb/tools/create_index/create_index.cpp @@ -29,10 +29,13 @@ main(int argc, const char** argv){ const char* _dbname = "TEST_DB"; int _help = 0; + int _ordered, _pk; struct getargs args[] = { { "database", 'd', arg_string, &_dbname, "dbname", "Name of database table is in"}, + { "ordered", 'o', arg_flag, &_ordered, "Create ordered index", "" }, + { "pk", 'p', arg_flag, &_pk, "Create index on primary key", "" }, { "usage", '?', arg_flag, &_help, "Print help", "" } }; @@ -73,14 +76,21 @@ main(int argc, const char** argv){ } NdbDictionary::Index ind; + if(_ordered){ + ind.setType(NdbDictionary::Index::OrderedIndex); + ind.setLogging(false); + } else { + ind.setType(NdbDictionary::Index::UniqueHashIndex); + } char buf[512]; - sprintf(buf, "IND_%s", argv[i]); + sprintf(buf, "IND_%s_%s_%c", + argv[i], (_pk ? "PK" : "FULL"), (_ordered ? 'O' : 'U')); ind.setName(buf); ind.setTable(argv[i]); - ind.setType(NdbDictionary::Index::UniqueHashIndex); - for(int c = 0; cgetNoOfColumns(); c++) - ind.addIndexColumn(tab->getColumn(c)->getName()); - + for(int c = 0; cgetNoOfColumns(); c++){ + if(!_pk || tab->getColumn(c)->getPrimaryKey()) + ind.addIndexColumn(tab->getColumn(c)->getName()); + } ndbout << "creating index " << buf << " on table " << argv[i] << "..."; const int res = dict->createIndex(ind); if(res != 0) diff --git a/ndb/tools/select_all/select_all.cpp b/ndb/tools/select_all/select_all.cpp index 34f63a095bb..329ed87bc48 100644 --- a/ndb/tools/select_all/select_all.cpp +++ b/ndb/tools/select_all/select_all.cpp @@ -29,11 +29,13 @@ int scanReadRecords(Ndb*, const NdbDictionary::Table*, + const NdbDictionary::Index*, int parallel, int lockType, bool headers, bool useHexFormat, - char delim); + char delim, + bool orderby); int main(int argc, const char** argv){ int _parallelism = 240; @@ -44,6 +46,7 @@ int main(int argc, const char** argv){ const char* _dbname = "TEST_DB"; int _help = 0; int _lock = 0; + int _order = 0; struct getargs args[] = { { "database", 'd', arg_string, &_dbname, "dbname", @@ -57,7 +60,8 @@ int main(int argc, const char** argv){ "delimiter" }, { "usage", '?', arg_flag, &_help, "Print help", "" }, { "lock", 'l', arg_integer, &_lock, - "Read(0), Read-hold(1), Exclusive(2)", "lock"} + "Read(0), Read-hold(1), Exclusive(2)", "lock"}, + { "order", 'o', arg_flag, &_order, "Sort resultset according to index", ""} }; int num_args = sizeof(args) / sizeof(args[0]); int optind = 0; @@ -90,6 +94,11 @@ int main(int argc, const char** argv){ // Check if table exists in db const NdbDictionary::Table* pTab = NDBT_Table::discoverTableFromDb(&MyNdb, _tabname); + const NdbDictionary::Index * pIdx = 0; + if(optind+1 < argc){ + pIdx = MyNdb.getDictionary()->getIndex(argv[optind+1], _tabname); + } + if(pTab == NULL){ ndbout << " Table " << _tabname << " does not exist!" << endl; return NDBT_ProgramExit(NDBT_WRONGARGS); @@ -97,11 +106,12 @@ int main(int argc, const char** argv){ if (scanReadRecords(&MyNdb, pTab, + pIdx, _parallelism, _lock, _header, _useHexFormat, - (char)*_delimiter) != 0){ + (char)*_delimiter, _order) != 0){ return NDBT_ProgramExit(NDBT_FAILED); } @@ -111,17 +121,19 @@ int main(int argc, const char** argv){ int scanReadRecords(Ndb* pNdb, const NdbDictionary::Table* pTab, + const NdbDictionary::Index* pIdx, int parallel, int _lock, bool headers, bool useHexFormat, - char delimiter){ + char delimiter, bool order){ int retryAttempt = 0; const int retryMax = 100; int check; NdbConnection *pTrans; - NdbOperation *pOp; + NdbScanOperation *pOp; + NdbIndexScanOperation * pIOp; NDBT_ResultRow * row = new NDBT_ResultRow(*pTab, delimiter); @@ -146,29 +158,45 @@ int scanReadRecords(Ndb* pNdb, return -1; } - pOp = pTrans->getNdbOperation(pTab->getName()); + + pOp = (!pIdx) ? pTrans->getNdbScanOperation(pTab->getName()) : + pIOp=pTrans->getNdbIndexScanOperation(pIdx->getName(), pTab->getName()); + if (pOp == NULL) { ERR(pTrans->getNdbError()); pNdb->closeTransaction(pTrans); return -1; } - switch(_lock){ + NdbResultSet * rs; + switch(_lock + (3 * order)){ case 1: - check = pOp->openScanReadHoldLock(parallel); + rs = pOp->readTuples(NdbScanOperation::LM_Read, 0, parallel); break; case 2: - check = pOp->openScanExclusive(parallel); + rs = pOp->readTuples(NdbScanOperation::LM_Exclusive, 0, parallel); break; + case 3: + rs = pIOp->readTuples(NdbScanOperation::LM_CommittedRead, 0, parallel, + true); + break; + case 4: + rs = pIOp->readTuples(NdbScanOperation::LM_Read, 0, parallel, true); + break; + case 5: + rs = pIOp->readTuples(NdbScanOperation::LM_Exclusive, 0, parallel, true); + break; + case 0: default: - check = pOp->openScanRead(parallel); + rs = pOp->readTuples(NdbScanOperation::LM_CommittedRead, 0, parallel); + break; } - if( check == -1 ) { + if( rs == 0 ){ ERR(pTrans->getNdbError()); pNdb->closeTransaction(pTrans); return -1; } - + if(0){ NdbScanFilter sf(pOp); #if 0 @@ -229,10 +257,10 @@ int scanReadRecords(Ndb* pNdb, } } - check = pTrans->executeScan(); + check = pTrans->execute(NoCommit); if( check == -1 ) { const NdbError err = pTrans->getNdbError(); - + if (err.status == NdbError::TemporaryError){ pNdb->closeTransaction(pTrans); NdbSleep_MilliSleep(50); @@ -246,11 +274,11 @@ int scanReadRecords(Ndb* pNdb, if (headers) row->header(ndbout) << endl; - + int eof; int rows = 0; - eof = pTrans->nextScanResult(); - + eof = rs->nextResult(); + while(eof == 0){ rows++; @@ -260,7 +288,7 @@ int scanReadRecords(Ndb* pNdb, ndbout << (*row) << endl; } - eof = pTrans->nextScanResult(); + eof = rs->nextResult(); } if (eof == -1) { const NdbError err = pTrans->getNdbError();