diff options
Diffstat (limited to 'ndb')
277 files changed, 14573 insertions, 11784 deletions
diff --git a/ndb/include/Makefile.am b/ndb/include/Makefile.am index 2565a78238b..b1b7951f216 100644 --- a/ndb/include/Makefile.am +++ b/ndb/include/Makefile.am @@ -23,6 +23,7 @@ ndbapi/NdbReceiver.hpp \ ndbapi/NdbResultSet.hpp \ ndbapi/NdbScanFilter.hpp \ ndbapi/NdbScanOperation.hpp \ +ndbapi/NdbIndexScanOperation.hpp \ ndbapi/ndberror.h mgmapiinclude_HEADERS = \ diff --git a/ndb/include/debugger/EventLogger.hpp b/ndb/include/debugger/EventLogger.hpp index c49bd176ee8..6cd6a83e68d 100644 --- a/ndb/include/debugger/EventLogger.hpp +++ b/ndb/include/debugger/EventLogger.hpp @@ -73,13 +73,6 @@ public: ~EventLogger(); /** - * Open/create the eventlog, the default name is 'cluster.log'. - * - * @return true if successful. - */ - bool open(); - - /** * Opens/creates the eventlog with the specified filename. * * @param aFileName the eventlog filename. diff --git a/ndb/include/kernel/GlobalSignalNumbers.h b/ndb/include/kernel/GlobalSignalNumbers.h index 7b70f4c3ac0..8941fa6b381 100644 --- a/ndb/include/kernel/GlobalSignalNumbers.h +++ b/ndb/include/kernel/GlobalSignalNumbers.h @@ -84,7 +84,7 @@ extern const GlobalSignalNumber NO_OF_SIGNAL_NAMES; #define GSN_SCAN_NEXTREQ 28 #define GSN_SCAN_TABCONF 29 -#define GSN_SCAN_TABINFO 30 +// 30 unused #define GSN_SCAN_TABREF 31 #define GSN_SCAN_TABREQ 32 #define GSN_KEYINFO20 33 @@ -897,12 +897,9 @@ extern const GlobalSignalNumber NO_OF_SIGNAL_NAMES; #define GSN_TUX_MAINT_CONF 678 #define GSN_TUX_MAINT_REF 679 -/* - * TUP access - */ -#define GSN_TUP_READ_ATTRS 680 -#define GSN_TUP_QUERY_TH 712 -#define GSN_TUP_STORE_TH 681 +// not used 680 +// not used 712 +// not used 681 /** * from mgmtsrvr to NDBCNTR diff --git a/ndb/include/kernel/Interpreter.hpp b/ndb/include/kernel/Interpreter.hpp index 2c282be361c..74399f5732e 100644 --- a/ndb/include/kernel/Interpreter.hpp +++ b/ndb/include/kernel/Interpreter.hpp @@ -83,7 +83,7 @@ public: static Uint32 LoadConst64(Uint32 Register); // Value in next 2 words static Uint32 Add(Uint32 DstReg, Uint32 SrcReg1, Uint32 SrcReg2); static Uint32 Sub(Uint32 DstReg, Uint32 SrcReg1, Uint32 SrcReg2); - static Uint32 Branch(Uint32 Inst, Uint32 R1, Uint32 R2); + static Uint32 Branch(Uint32 Inst, Uint32 Reg1, Uint32 Reg2); static Uint32 ExitOK(); /** @@ -184,8 +184,8 @@ Interpreter::Sub(Uint32 Dcoleg, Uint32 SrcReg1, Uint32 SrcReg2){ inline Uint32 -Interpreter::Branch(Uint32 Inst, Uint32 R1, Uint32 R2){ - return (R1 << 9) + (R2 << 6) + Inst; +Interpreter::Branch(Uint32 Inst, Uint32 Reg1, Uint32 Reg2){ + return (Reg1 << 9) + (Reg2 << 6) + Inst; } inline diff --git a/ndb/include/kernel/NodeInfo.hpp b/ndb/include/kernel/NodeInfo.hpp index 86aca7d6883..5377f001949 100644 --- a/ndb/include/kernel/NodeInfo.hpp +++ b/ndb/include/kernel/NodeInfo.hpp @@ -18,6 +18,7 @@ #define NODE_INFO_HPP #include <NdbOut.hpp> +#include <mgmapi_config_parameters.h> class NodeInfo { public: @@ -27,10 +28,10 @@ public: * NodeType */ enum NodeType { - DB = 0, ///< Database node - API = 1, ///< NDB API node - MGM = 2, ///< Management node (incl. NDB API) - REP = 3, ///< Replication node (incl. NDB API) + DB = NODE_TYPE_DB, ///< Database node + API = NODE_TYPE_API, ///< NDB API node + MGM = NODE_TYPE_MGM, ///< Management node (incl. NDB API) + REP = NODE_TYPE_REP, ///< Replication node (incl. NDB API) INVALID = 255 ///< Invalid type }; NodeType getType() const; diff --git a/ndb/include/kernel/NodeState.hpp b/ndb/include/kernel/NodeState.hpp index 1bc7806876d..185e3ea8ea4 100644 --- a/ndb/include/kernel/NodeState.hpp +++ b/ndb/include/kernel/NodeState.hpp @@ -18,6 +18,7 @@ #define NODE_STATE_HPP #include <NdbOut.hpp> +#include <NodeBitmask.hpp> class NodeState { public: @@ -99,7 +100,7 @@ public: /** * Length in 32-bit words */ - static const Uint32 DataLength = 8; + static const Uint32 DataLength = 8 + NdbNodeBitmask::Size; /** * Constructor(s) @@ -108,7 +109,8 @@ public: NodeState(StartLevel); NodeState(StartLevel, bool systemShutdown); NodeState(StartLevel, Uint32 startPhase, StartType); - + void init(); + /** * Current start level */ @@ -146,6 +148,8 @@ public: Uint32 singleUserMode; Uint32 singleUserApi; //the single user node + BitmaskPOD<NdbNodeBitmask::Size> m_connected_nodes; + void setDynamicId(Uint32 dynamic); void setNodeGroup(Uint32 group); void setSingleUser(Uint32 s); @@ -177,16 +181,23 @@ public: inline NodeState::NodeState(){ + init(); +} + +inline +void +NodeState::init(){ startLevel = SL_CMVMI; nodeGroup = 0xFFFFFFFF; dynamicId = 0xFFFFFFFF; singleUserMode = 0; singleUserApi = 0xFFFFFFFF; + m_connected_nodes.clear(); } inline NodeState::NodeState(StartLevel sl){ - NodeState::NodeState(); + init(); startLevel = sl; singleUserMode = 0; singleUserApi = 0xFFFFFFFF; @@ -194,7 +205,7 @@ NodeState::NodeState(StartLevel sl){ inline NodeState::NodeState(StartLevel sl, Uint32 sp, StartType typeOfStart){ - NodeState::NodeState(); + init(); startLevel = sl; starting.startPhase = sp; starting.restartType = typeOfStart; @@ -204,7 +215,7 @@ NodeState::NodeState(StartLevel sl, Uint32 sp, StartType typeOfStart){ inline NodeState::NodeState(StartLevel sl, bool sys){ - NodeState::NodeState(); + init(); startLevel = sl; stopping.systemShutdown = sys; singleUserMode = 0; diff --git a/ndb/include/kernel/kernel_config_parameters.h b/ndb/include/kernel/kernel_config_parameters.h index 2f63efa4b6c..bb7c6ebd42c 100644 --- a/ndb/include/kernel/kernel_config_parameters.h +++ b/ndb/include/kernel/kernel_config_parameters.h @@ -14,10 +14,7 @@ #define CFG_ACC_SCAN (PRIVATE_BASE + 9) #define CFG_DICT_ATTRIBUTE (PRIVATE_BASE + 10) -#define CFG_DICT_CONNECT (PRIVATE_BASE + 11) -#define CFG_DICT_FRAG_CONNECT (PRIVATE_BASE + 12) #define CFG_DICT_TABLE (PRIVATE_BASE + 13) -#define CFG_DICT_TC_CONNECT (PRIVATE_BASE + 14) #define CFG_DIH_API_CONNECT (PRIVATE_BASE + 15) #define CFG_DIH_CONNECT (PRIVATE_BASE + 16) @@ -27,10 +24,8 @@ #define CFG_DIH_TABLE (PRIVATE_BASE + 20) #define CFG_LQH_FRAG (PRIVATE_BASE + 21) -#define CFG_LQH_CONNECT (PRIVATE_BASE + 22) #define CFG_LQH_TABLE (PRIVATE_BASE + 23) #define CFG_LQH_TC_CONNECT (PRIVATE_BASE + 24) -#define CFG_LQH_REPLICAS (PRIVATE_BASE + 25) #define CFG_LQH_LOG_FILES (PRIVATE_BASE + 26) #define CFG_LQH_SCAN (PRIVATE_BASE + 27) diff --git a/ndb/include/kernel/ndb_limits.h b/ndb/include/kernel/ndb_limits.h index 68ffe310328..f35cc617e86 100644 --- a/ndb/include/kernel/ndb_limits.h +++ b/ndb/include/kernel/ndb_limits.h @@ -88,7 +88,7 @@ * Ordered index constants. Make configurable per index later. */ #define MAX_TTREE_NODE_SIZE 64 // total words in node -#define MAX_TTREE_PREF_SIZE 4 // words in min/max prefix each +#define MAX_TTREE_PREF_SIZE 4 // words in min prefix #define MAX_TTREE_NODE_SLACK 3 // diff between max and min occupancy /* 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 67610f9d2be..dec7145c897 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(); }; @@ -309,7 +311,7 @@ public: ExtDatetime = NdbSqlUtil::Type::Datetime, ExtTimespec = NdbSqlUtil::Type::Timespec, ExtBlob = NdbSqlUtil::Type::Blob, - ExtClob = NdbSqlUtil::Type::Clob + ExtText = NdbSqlUtil::Type::Text }; // Attribute data interpretation @@ -433,7 +435,7 @@ public: AttributeArraySize = 12 * AttributeExtLength; return true; case DictTabInfo::ExtBlob: - case DictTabInfo::ExtClob: + case DictTabInfo::ExtText: AttributeType = DictTabInfo::StringType; AttributeSize = DictTabInfo::an8Bit; // head + inline part [ attr precision ] 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/DumpStateOrd.hpp b/ndb/include/kernel/signaldata/DumpStateOrd.hpp index 6403a52926f..1e349fad55a 100644 --- a/ndb/include/kernel/signaldata/DumpStateOrd.hpp +++ b/ndb/include/kernel/signaldata/DumpStateOrd.hpp @@ -94,6 +94,7 @@ public: TcDumpOneApiConnectRec = 2505, TcDumpAllApiConnectRec = 2506, TcSetTransactionTimeout = 2507, + TcSetApplTransactionTimeout = 2508, CmvmiDumpConnections = 2600, CmvmiDumpLongSignalMemory = 2601, CmvmiSetRestartOnErrorInsert = 2602, 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..ab2978e48da 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){ @@ -146,6 +151,12 @@ ScanTabReq::getRangeScanFlag(const UintR & requestInfo){ } inline +Uint8 +ScanTabReq::getScanBatch(const Uint32 & requestInfo){ + return (Uint8)((requestInfo >> SCAN_BATCH_SHIFT) & SCAN_BATCH_MASK); +} + +inline void ScanTabReq::clearRequestInfo(UintR & requestInfo){ requestInfo = 0; @@ -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,103 +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 - * RECIVER: API, Dbtc - */ -class ScanTabInfo { - /** - * Reciver(s) and Sender(s) - */ - friend class NdbConnection; - friend class Dbtc; - - /** - * For printing - */ - friend bool printSCANTABINFO(FILE * output, const Uint32 * theData, Uint32 len, Uint16 receiverBlockNo); - -public: - /** - * Length of signal - */ - STATIC_CONST( SignalLength = 17 ); - -private: - - // Type definitions - - /** - * DATA VARIABLES - */ - UintR apiConnectPtr; // DATA 0 - UintR operLenAndIdx[16]; // DATA 1-16 - - /** - * Get:ers for operLenAndIdx - */ - static Uint32 getLen(const UintR & operLenAndIdx); - static Uint8 getIdx(const UintR & operLenAndIdx); - -}; - - -/** - * Operation length and index - * - l = Length of operation - 24 Bits -> Max 16777215 (Bit 0-24) - i = Index of operation - 7 Bits -> Max 255 (Bit 25-32) - - 1111111111222222222233 - 01234567890123456789012345678901 - llllllllllllllllllllllllliiiiiii -*/ - -#define LENGTH_SHIFT (0) -#define LENGTH_MASK (0xFFFFFF) - -#define INDEX_SHIFT (24) -#define INDEX_MASK (0xFF) - -inline -Uint32 -ScanTabInfo::getLen(const UintR & operLenAndIdx){ - return (Uint32)((operLenAndIdx >> LENGTH_SHIFT) & LENGTH_MASK); -} - -inline -Uint8 -ScanTabInfo::getIdx(const UintR & operLenAndIdx){ - return (Uint8)((operLenAndIdx >> INDEX_SHIFT) & INDEX_MASK); -} /** * @@ -390,7 +297,7 @@ public: /** * Length of signal */ - STATIC_CONST( SignalLength = 4 ); + STATIC_CONST( SignalLength = 5 ); private: @@ -403,7 +310,7 @@ private: UintR transId1; // DATA 1 UintR transId2; // DATA 2 UintR errorCode; // DATA 3 - // UintR sendScanNextReqWithClose; // DATA 4 + UintR closeNeeded; // DATA 4 }; diff --git a/ndb/include/kernel/signaldata/SignalData.hpp b/ndb/include/kernel/signaldata/SignalData.hpp index 511e7d30c21..6e5748217b2 100644 --- a/ndb/include/kernel/signaldata/SignalData.hpp +++ b/ndb/include/kernel/signaldata/SignalData.hpp @@ -21,20 +21,10 @@ #include <ndb_limits.h> #include <kernel_types.h> -#ifndef NDB_ASSERT -#ifdef VM_TRACE -#define NDB_ASSERT(test, message) { if(!(test)) { printf(message); exit(-1); }} -#else -#define NDB_ASSERT(test, message) -#endif -#endif - -// Useful ASSERT macros... -#define ASSERT_BOOL(flag, message) NDB_ASSERT( (flag<=1), (message) ) +#define ASSERT_BOOL(flag, message) assert(flag<=1) #define ASSERT_RANGE(value, min, max, message) \ - NDB_ASSERT((value) >= (min) && (value) <= (max), (message)) -#define ASSERT_MAX(value, max, message) \ - NDB_ASSERT((value) <= (max), (message)) + assert((value) >= (min) && (value) <= (max)) +#define ASSERT_MAX(value, max, message) assert((value) <= (max)) #define SECTION(x) STATIC_CONST(x) diff --git a/ndb/include/kernel/signaldata/StartInfo.hpp b/ndb/include/kernel/signaldata/StartInfo.hpp index da032adba8a..d0850b13ef4 100644 --- a/ndb/include/kernel/signaldata/StartInfo.hpp +++ b/ndb/include/kernel/signaldata/StartInfo.hpp @@ -78,7 +78,7 @@ class StartInfoRef { Uint32 errorCode; public: - STATIC_CONST( SignalLength = 2 ); + STATIC_CONST( SignalLength = 3 ); }; #endif 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/kernel/signaldata/TupAccess.hpp b/ndb/include/kernel/signaldata/TupAccess.hpp deleted file mode 100644 index ab56a73322c..00000000000 --- a/ndb/include/kernel/signaldata/TupAccess.hpp +++ /dev/null @@ -1,174 +0,0 @@ -/* 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 TUP_ACCESS_HPP -#define TUP_ACCESS_HPP - -#include "SignalData.hpp" - -/* - * Direct signals used by ACC and TUX to access the TUP block in the - * same thread. - * - * NOTE: Caller must set errorCode to RNIL. Signal printer uses this to - * distinguish between input and output (no better way exists). - */ - -/* - * Read attributes from any table. - */ -class TupReadAttrs { - friend class Dbtup; - friend class Dbacc; - friend class Dbtux; - friend bool printTUP_READ_ATTRS(FILE*, const Uint32*, Uint32, Uint16); -public: - enum Flag { - /* - * Read primary key attributes. No input attribute ids are - * specified. Instead TUP fills in both input and output sections. - * Tuple version is not used. - */ - ReadKeys = (1 << 0) - }; - STATIC_CONST( SignalLength = 10 ); -private: - /* - * Error code set by TUP. Zero means no error. - */ - Uint32 errorCode; - /* - * Request info contains flags (see Flags above). - */ - Uint32 requestInfo; - /* - * Table i-value. - */ - Uint32 tableId; - /* - * Fragment is given by logical id within the table or by direct - * i-value (faster). Unknown values are given as RNIL. On return TUP - * fills in both values. - */ - Uint32 fragId; - Uint32 fragPtrI; - /* - * Logical address ("local key") of "original" tuple (the latest - * version) consisting of logical fragment page id and tuple index - * within the page (shifted left by 1). - */ - Uint32 tupAddr; - /* - * Version of the tuple to read. Not used if ReadKeys. - */ - Uint32 tupVersion; - /* - * Real page id and offset of the "original" tuple. Unknown page is - * given as RNIL. On return TUP fills in these. - */ - Uint32 pageId; - Uint32 pageOffset; - /* - * Shared buffer id. Currently must be 0 which means to use rest of - * signal data. - */ - Uint32 bufferId; - /* - * Shared buffer 0 starts after signal class. Input is number of - * attributes and list of attribute ids in AttributeHeader format. - * Output is placed after the input and consists of a list of entries - * where each entry has an AttributeHeader followed by words of data. - */ -}; - -/* - * Query status of tuple version. Used by TUX to decide if a tuple - * version found in index tree is visible to the transaction. - */ -class TupQueryTh { - friend class Dbtup; - friend class Dbtux; - friend bool printTUP_QUERY_TH(FILE*, const Uint32*, Uint32, Uint16); -public: - enum Flag { - }; - STATIC_CONST( SignalLength = 7 ); -private: - /* - TUX wants to check if tuple is visible to the scan query. - Input data is tuple address (tableId, fragId, tupAddr, tupVersion), - and transaction data so that TUP knows how to deduct if tuple is - visible (transId1, transId2, savePointId). - returnCode is set in return signal to indicate whether tuple is visible. - */ - union { - Uint32 returnCode; // 1 if tuple visible - Uint32 tableId; - }; - Uint32 fragId; - Uint32 tupAddr; - Uint32 tupVersion; - Uint32 transId1; - Uint32 transId2; - Uint32 savePointId; -}; - -/* - * Operate on entire tuple. Used by TUX where the table has a single - * Uint32 array attribute representing an index tree node. - * - * XXX this signal is no longer used by TUX and can be removed - */ -class TupStoreTh { - friend class Dbtup; - friend class Dbtux; - friend bool printTUP_STORE_TH(FILE*, const Uint32*, Uint32, Uint16); -public: - enum OpCode { - OpUndefined = 0, - OpRead = 1, - OpInsert = 2, - OpUpdate = 3, - OpDelete = 4 - }; - STATIC_CONST( SignalLength = 12 ); -private: - /* - * These are as in TupReadAttrs (except opCode). Version must be - * zero. Ordered index tuple (tree node) has only current version. - */ - Uint32 errorCode; - Uint32 opCode; - Uint32 tableId; - Uint32 fragId; - Uint32 fragPtrI; - Uint32 tupAddr; - Uint32 tupVersion; - Uint32 pageId; - Uint32 pageOffset; - Uint32 bufferId; - /* - * Data offset and size in words. Applies to both the buffer and the - * tuple. Used e.g. to read only node header. - */ - Uint32 dataOffset; - Uint32 dataSize; - /* - * Shared buffer 0 starts after signal class. - */ -}; - -#endif diff --git a/ndb/include/mgmapi/mgmapi.h b/ndb/include/mgmapi/mgmapi.h index 7b2f728bda8..123297b0d71 100644 --- a/ndb/include/mgmapi/mgmapi.h +++ b/ndb/include/mgmapi/mgmapi.h @@ -49,6 +49,8 @@ * @{ */ +#include "mgmapi_config_parameters.h" + #ifdef __cplusplus extern "C" { #endif @@ -81,10 +83,10 @@ extern "C" { */ enum ndb_mgm_node_type { NDB_MGM_NODE_TYPE_UNKNOWN = -1, /*/< Node type not known*/ - NDB_MGM_NODE_TYPE_API = 0, /*/< An application node (API)*/ - NDB_MGM_NODE_TYPE_NDB = 1, /*/< A database node (DB)*/ - NDB_MGM_NODE_TYPE_MGM = 2, /*/< A management server node (MGM)*/ - NDB_MGM_NODE_TYPE_REP = 3, ///< A replication node + NDB_MGM_NODE_TYPE_API = NODE_TYPE_API, /*/< An application node (API)*/ + NDB_MGM_NODE_TYPE_NDB = NODE_TYPE_DB, /*/< A database node (DB)*/ + NDB_MGM_NODE_TYPE_MGM = NODE_TYPE_MGM, /*/< A management server node (MGM)*/ + NDB_MGM_NODE_TYPE_REP = NODE_TYPE_REP, ///< A replication node NDB_MGM_NODE_TYPE_MIN = 0, /*/< Min valid value*/ NDB_MGM_NODE_TYPE_MAX = 3 /*/< Max valid value*/ @@ -666,6 +668,11 @@ extern "C" { */ struct ndb_mgm_configuration * ndb_mgm_get_configuration(NdbMgmHandle handle, unsigned version); + + int ndb_mgm_alloc_nodeid(NdbMgmHandle handle, + unsigned version, + unsigned *pnodeid, + int nodetype); /** * Config iterator */ diff --git a/ndb/include/mgmapi/mgmapi_config_parameters.h b/ndb/include/mgmapi/mgmapi_config_parameters.h index d3bb44c1523..3eca49055fe 100644 --- a/ndb/include/mgmapi/mgmapi_config_parameters.h +++ b/ndb/include/mgmapi/mgmapi_config_parameters.h @@ -6,6 +6,7 @@ #define CFG_SYS_PRIMARY_MGM_NODE 1 #define CFG_SYS_CONFIG_GENERATION 2 #define CFG_SYS_REPLICATION_ROLE 7 +#define CFG_SYS_PORT_BASE 8 #define CFG_NODE_ID 3 #define CFG_NODE_BYTE_ORDER 4 @@ -87,11 +88,11 @@ #define CFG_CONNECTION_CHECKSUM 403 #define CFG_CONNECTION_NODE_1_SYSTEM 404 #define CFG_CONNECTION_NODE_2_SYSTEM 405 +#define CFG_CONNECTION_SERVER_PORT 406 #define CFG_TCP_HOSTNAME_1 450 #define CFG_TCP_HOSTNAME_2 451 #define CFG_TCP_SERVER 452 -#define CFG_TCP_SERVER_PORT 453 #define CFG_TCP_SEND_BUFFER_SIZE 454 #define CFG_TCP_RECEIVE_BUFFER_SIZE 455 #define CFG_TCP_PROXY 456 diff --git a/ndb/include/mgmapi/mgmapi_debug.h b/ndb/include/mgmapi/mgmapi_debug.h index 2723263e7a7..1c562cd164f 100644 --- a/ndb/include/mgmapi/mgmapi_debug.h +++ b/ndb/include/mgmapi/mgmapi_debug.h @@ -106,6 +106,31 @@ extern "C" { struct ndb_mgm_reply* reply); + /** + * + * @param handle the NDB management handle. + * @param nodeId the node id. 0 = all db nodes + * @param errrorCode the errorCode. + * @param reply the reply message. + * @return 0 if successful or an error code. + */ + int ndb_mgm_set_int_parameter(NdbMgmHandle handle, + int node, + int param, + unsigned value, + struct ndb_mgm_reply* reply); + + int ndb_mgm_set_int64_parameter(NdbMgmHandle handle, + int node, + int param, + unsigned long long value, + struct ndb_mgm_reply* reply); + + int ndb_mgm_set_string_parameter(NdbMgmHandle handle, + int node, + int param, + const char * value, + struct ndb_mgm_reply* reply); #ifdef __cplusplus } #endif diff --git a/ndb/include/mgmcommon/ConfigRetriever.hpp b/ndb/include/mgmcommon/ConfigRetriever.hpp index 50d333b54dd..396ce24308c 100644 --- a/ndb/include/mgmcommon/ConfigRetriever.hpp +++ b/ndb/include/mgmcommon/ConfigRetriever.hpp @@ -19,6 +19,8 @@ #include <ndb_types.h> #include <mgmapi.h> +#include <BaseString.hpp> +#include <LocalConfig.hpp> /** * @class ConfigRetriever @@ -26,15 +28,16 @@ */ class ConfigRetriever { public: - ConfigRetriever(); - ConfigRetriever(const int id, const char* remoteHost, const int port); + ConfigRetriever(Uint32 version, Uint32 nodeType); ~ConfigRetriever(); /** * Read local config * @return Own node id, -1 means fail */ - int init(bool onlyNodeId = false); + int init(); + + int do_connect(); /** * Get configuration for current (nodeId given in local config file) node. @@ -47,7 +50,7 @@ public: * @return ndb_mgm_configuration object if succeeded, * NULL if erroneous local config file or configuration error. */ - struct ndb_mgm_configuration * getConfig(int versionId, int nodeType); + struct ndb_mgm_configuration * getConfig(); const char * getErrorString(); @@ -62,28 +65,21 @@ public: void setLocalConfigFileName(const char * connectString); /** - * Sets connectstring which can be used instead of local config file - * environment variables and Ndb.cfg has precidence over this - */ - void setDefaultConnectString(const char * defaultConnectString); - - /** * @return Node id of this node (as stated in local config or connectString) */ - inline Uint32 getOwnNodeId() { return _ownNodeId; } - + Uint32 allocNodeId(); /** * Get config using socket */ - struct ndb_mgm_configuration * getConfig(const char * mgmhost, short port, - int versionId); + struct ndb_mgm_configuration * getConfig(NdbMgmHandle handle); + /** * Get config from file */ - struct ndb_mgm_configuration * getConfig(const char * file, int versionId); + struct ndb_mgm_configuration * getConfig(const char * file); private: - char * errorString; + BaseString errorString; enum ErrorType { CR_ERROR = 0, CR_RETRY = 1 @@ -91,18 +87,21 @@ private: ErrorType latestErrorType; void setError(ErrorType, const char * errorMsg); - - char * _localConfigFileName; - struct LocalConfig * _localConfig; + + BaseString _localConfigFileName; + struct LocalConfig _localConfig; int _ownNodeId; - - char * m_connectString; - char * m_defaultConnectString; + BaseString m_connectString; + + Uint32 m_version; + Uint32 m_node_type; + NdbMgmHandle m_handle; + /** * Verify config */ - bool verifyConfig(const struct ndb_mgm_configuration *, int type); + bool verifyConfig(const struct ndb_mgm_configuration *); }; #endif diff --git a/ndb/src/common/mgmcommon/LocalConfig.hpp b/ndb/include/mgmcommon/LocalConfig.hpp index eb676bf9bed..c741b35f482 100644 --- a/ndb/src/common/mgmcommon/LocalConfig.hpp +++ b/ndb/include/mgmcommon/LocalConfig.hpp @@ -32,49 +32,35 @@ enum MgmtSrvrId_Type { struct MgmtSrvrId { MgmtSrvrId_Type type; - union { - struct { - char * remoteHost; - unsigned int port; - } tcp; - struct { - char * filename; - } file; - } data; + BaseString name; + unsigned int port; }; struct LocalConfig { int _ownNodeId; - - int size; - int items; - MgmtSrvrId ** ids; - + Vector<MgmtSrvrId> ids; + int error_line; char error_msg[256]; LocalConfig(); ~LocalConfig(); - bool init(bool onlyNodeId = false, - const char *connectString = 0, - const char *fileName = 0, - const char *defaultConnectString = 0); - - void add(MgmtSrvrId *i); + bool init(const char *connectString = 0, + const char *fileName = 0); void printError() const; void printUsage() const; void setError(int lineNumber, const char * _msg); - bool readConnectString(const char * connectString, bool onlyNodeId = false); - bool readFile(const char * filename, bool &fopenError, bool onlyNodeId = false); + bool readConnectString(const char *); + bool readFile(const char * file, bool &fopenError); bool parseLine(char * line, int lineNumber); - + bool parseNodeId(const char *buf); bool parseHostName(const char *buf); bool parseFileName(const char *buf); - bool parseString(const char *buf, bool onlyNodeId, char *line); + bool parseString(const char *buf, char *line); }; #endif // LocalConfig_H diff --git a/ndb/include/mgmcommon/MgmtErrorReporter.hpp b/ndb/include/mgmcommon/MgmtErrorReporter.hpp index 925d9e6407a..0d980aa7245 100644 --- a/ndb/include/mgmcommon/MgmtErrorReporter.hpp +++ b/ndb/include/mgmcommon/MgmtErrorReporter.hpp @@ -63,12 +63,6 @@ // Returns: - //**************************************************************************** -#ifndef NDB_ASSERT -#define NDB_ASSERT(trueToContinue, message) \ - if ( !(trueToContinue) ) { \ -ndbout << "ASSERT FAILED. FILE: " << __FILE__ << ", LINE: " << __LINE__ << ", MSG: " << message << endl;exit(-1);} -#endif - #define MGM_REQUIRE(x) \ if (!(x)) { ndbout << __FILE__ << " " << __LINE__ \ << ": Warning! Requirement failed" << endl; } diff --git a/ndb/include/mgmcommon/NdbConfig.h b/ndb/include/mgmcommon/NdbConfig.h index d9b484edcc5..5c83a348df2 100644 --- a/ndb/include/mgmcommon/NdbConfig.h +++ b/ndb/include/mgmcommon/NdbConfig.h @@ -21,11 +21,14 @@ extern "C" { #endif -const char* NdbConfig_HomePath(char* buf, int buflen); - -const char* NdbConfig_NdbCfgName(char* buf, int buflen, int with_ndb_home); -const char* NdbConfig_ErrorFileName(char* buf, int buflen); -const char* NdbConfig_ClusterLogFileName(char* buf, int buflen); +char* NdbConfig_NdbCfgName(int with_ndb_home); +char* NdbConfig_ErrorFileName(int node_id); +char* NdbConfig_ClusterLogFileName(int node_id); +char* NdbConfig_SignalLogFileName(int node_id); +char* NdbConfig_TraceFileName(int node_id, int file_no); +char* NdbConfig_NextTraceFileName(int node_id); +char* NdbConfig_PidFileName(int node_id); +char* NdbConfig_StdoutFileName(int node_id); #ifdef __cplusplus } diff --git a/ndb/include/ndb_global.h b/ndb/include/ndb_global.h index f871acbc075..b8fcca6dbb1 100644 --- a/ndb/include/ndb_global.h +++ b/ndb/include/ndb_global.h @@ -3,6 +3,10 @@ #define NDBGLOBAL_H #include <my_global.h> +#define NDB_BASE_PORT 2200 + +/** signal & SIG_PIPE */ +#include <my_alarm.h> #if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32) #define NDB_WIN32 @@ -90,6 +94,14 @@ extern int strcasecmp(const char *s1, const char *s2); extern int strncasecmp(const char *s1, const char *s2, size_t n); #endif +#ifdef SCO + +#ifndef PATH_MAX +#define PATH_MAX 1024 +#endif + +#endif /* SCO */ + #ifdef __cplusplus } #endif diff --git a/ndb/include/ndbapi/Ndb.hpp b/ndb/include/ndbapi/Ndb.hpp index 27da5c3fa39..7904ecef305 100644 --- a/ndb/include/ndbapi/Ndb.hpp +++ b/ndb/include/ndbapi/Ndb.hpp @@ -867,6 +867,7 @@ class NdbObjectIdMap; class NdbOperation; class NdbEventOperationImpl; class NdbScanOperation; +class NdbIndexScanOperation; class NdbIndexOperation; class NdbConnection; class NdbApiSignal; @@ -875,7 +876,6 @@ class NdbLabel; class NdbBranch; class NdbSubroutine; class NdbCall; -class NdbScanReceiver; class Table; class BaseString; class NdbEventOperation; @@ -961,8 +961,9 @@ class Ndb friend class NdbConnection; friend class Table; friend class NdbApiSignal; - friend class NdbScanReceiver; friend class NdbIndexOperation; + friend class NdbScanOperation; + friend class NdbIndexScanOperation; friend class NdbDictionaryImpl; friend class NdbDictInterface; friend class NdbBlob; @@ -1413,12 +1414,24 @@ public: * * @return tuple id or 0 on error */ - Uint64 getAutoIncrementValue(const char* aTableName, Uint32 cacheSize = 1); - bool setAutoIncrementValue(const char* aTableName, Uint64 val); - Uint64 getTupleIdFromNdb(const char* aTableName, Uint32 cacheSize = 1000 ); - Uint64 getTupleIdFromNdb(Uint32 aTableId, Uint32 cacheSize = 1000 ); - bool setTupleIdInNdb(const char* aTableName, Uint64 val); - bool setTupleIdInNdb(Uint32 aTableId, Uint64 val); + Uint64 getAutoIncrementValue(const char* aTableName, + Uint32 cacheSize = 1); + Uint64 getAutoIncrementValue(NdbDictionary::Table * aTable, + Uint32 cacheSize = 1); + Uint64 readAutoIncrementValue(const char* aTableName); + Uint64 readAutoIncrementValue(NdbDictionary::Table * aTable); + bool setAutoIncrementValue(const char* aTableName, Uint64 val, + bool increase = false); + bool setAutoIncrementValue(NdbDictionary::Table * aTable, Uint64 val, + bool increase = false); + Uint64 getTupleIdFromNdb(const char* aTableName, + Uint32 cacheSize = 1000); + Uint64 getTupleIdFromNdb(Uint32 aTableId, + Uint32 cacheSize = 1000); + Uint64 readTupleIdFromNdb(Uint32 aTableId); + bool setTupleIdInNdb(const char* aTableName, Uint64 val, + bool increase); + bool setTupleIdInNdb(Uint32 aTableId, Uint64 val, bool increase); Uint64 opTupleIdOnNdb(Uint32 aTableId, Uint64 opValue, Uint32 op); #endif @@ -1441,7 +1454,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 @@ -1450,7 +1463,7 @@ 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(); @@ -1458,14 +1471,14 @@ private: 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 releaseNdbBlob(NdbBlob* aBlob); void check_send_timeout(); @@ -1565,7 +1578,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); @@ -1607,7 +1619,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. NdbConnection* theTransactionList; NdbConnection** theConnectionArray; @@ -1617,7 +1629,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; NdbBlob* theNdbBlobIdleList; Uint32 theMyRef; // My block reference diff --git a/ndb/include/ndbapi/NdbApi.hpp b/ndb/include/ndbapi/NdbApi.hpp index 515f39433e4..add733cccd7 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 "NdbRecAttr.hpp" #include "NdbResultSet.hpp" #include "NdbDictionary.hpp" diff --git a/ndb/include/ndbapi/NdbBlob.hpp b/ndb/include/ndbapi/NdbBlob.hpp index 9398f77c474..dc47115d16f 100644 --- a/ndb/include/ndbapi/NdbBlob.hpp +++ b/ndb/include/ndbapi/NdbBlob.hpp @@ -50,24 +50,33 @@ class NdbColumnImpl; * - closed: after transaction commit * - invalid: after rollback or transaction close * - * NdbBlob supports 2 styles of data access: + * NdbBlob supports 3 styles of data access: * * - in prepare phase, NdbBlob methods getValue and setValue are used to - * prepare a read or write of a single blob value of known size + * prepare a read or write of a blob value of known size * - * - in active phase, NdbBlob methods readData and writeData are used to - * read or write blob data of undetermined size + * - in prepare phase, setActiveHook is used to define a routine which + * is invoked as soon as the handle becomes active + * + * - in active phase, readData and writeData are used to read or write + * blob data of arbitrary size + * + * The styles can be applied in combination (in above order). + * + * Blob operations take effect at next transaction execute. In some + * cases NdbBlob is forced to do implicit executes. To avoid this, + * operate on complete blob parts. + * + * Use NdbConnection::executePendingBlobOps to flush your reads and + * writes. It avoids execute penalty if nothing is pending. It is not + * needed after execute (obviously) or after next scan result. * * NdbBlob methods return -1 on error and 0 on success, and use output * parameters when necessary. * * Notes: * - table and its blob part tables are not created atomically - * - blob data operations take effect at next transaction execute - * - NdbBlob may need to do implicit executes on the transaction - * - read and write of complete parts is much more efficient * - scan must use the "new" interface NdbScanOperation - * - scan with blobs applies hold-read-lock (at minimum) * - to update a blob in a read op requires exclusive tuple lock * - update op in scan must do its own getBlobHandle * - delete creates implicit, not-accessible blob handles @@ -78,12 +87,16 @@ class NdbColumnImpl; * - scan must use exclusive locking for now * * Todo: - * - add scan method hold-read-lock-until-next + return-keyinfo - * - better check of keyinfo length when setting keys - * - better check of allowed blob op vs locking mode + * - add scan method hold-read-lock + return-keyinfo + * - check keyinfo length when setting keys + * - check allowed blob ops vs locking mode + * - overload control (too many pending ops) */ class NdbBlob { public: + /** + * State. + */ enum State { Idle = 0, Prepared = 1, @@ -93,8 +106,14 @@ public: }; State getState(); /** + * Inline blob header. + */ + struct Head { + Uint64 length; + }; + /** * Prepare to read blob value. The value is available after execute. - * Use isNull to check for NULL and getLength to get the real length + * Use getNull to check for NULL and getLength to get the real length * and to check for truncation. Sets current read/write position to * after the data read. */ @@ -107,6 +126,20 @@ public: */ int setValue(const void* data, Uint32 bytes); /** + * Callback for setActiveHook. Invoked immediately when the prepared + * operation has been executed (but not committed). Any getValue or + * setValue is done first. The blob handle is active so readData or + * writeData etc can be used to manipulate blob value. A user-defined + * argument is passed along. Returns non-zero on error. + */ + typedef int ActiveHook(NdbBlob* me, void* arg); + /** + * Define callback for blob handle activation. The queue of prepared + * operations will be executed in no commit mode up to this point and + * then the callback is invoked. + */ + int setActiveHook(ActiveHook* activeHook, void* arg); + /** * Check if blob is null. */ int getNull(bool& isNull); @@ -115,7 +148,7 @@ public: */ int setNull(); /** - * Get current length in bytes. Use isNull to distinguish between + * Get current length in bytes. Use getNull to distinguish between * length 0 blob and NULL blob. */ int getLength(Uint64& length); @@ -180,6 +213,13 @@ public: static const int ErrAbort = 4268; // "Unknown blob error" static const int ErrUnknown = 4269; + /** + * Return info about all blobs in this operation. + */ + // Get first blob in list + NdbBlob* blobsFirstBlob(); + // Get next blob in list after this one + NdbBlob* blobsNextBlob(); private: friend class Ndb; @@ -187,20 +227,20 @@ private: friend class NdbOperation; friend class NdbScanOperation; friend class NdbDictionaryImpl; + friend class NdbResultSet; // atNextResult // state State theState; void setState(State newState); // define blob table static void getBlobTableName(char* btname, const NdbTableImpl* t, const NdbColumnImpl* c); static void getBlobTable(NdbTableImpl& bt, const NdbTableImpl* t, const NdbColumnImpl* c); - // table name - char theBlobTableName[BlobTableNameSize]; // ndb api stuff Ndb* theNdb; NdbConnection* theNdbCon; NdbOperation* theNdbOp; NdbTableImpl* theTable; NdbTableImpl* theAccessTable; + NdbTableImpl* theBlobTable; const NdbColumnImpl* theColumn; char theFillChar; // sizes @@ -213,10 +253,11 @@ private: bool theSetFlag; const char* theSetBuf; Uint32 theGetSetBytes; - // head - struct Head { - Uint64 length; - }; + // pending ops + Uint8 thePendingBlobOps; + // activation callback + ActiveHook* theActiveHook; + void* theActiveHookArg; // buffers struct Buf { char* data; @@ -234,7 +275,6 @@ private: char* theInlineData; NdbRecAttr* theHeadInlineRecAttr; bool theHeadInlineUpdateFlag; - bool theNewPartFlag; // length and read/write position int theNullFlag; Uint64 theLength; @@ -275,6 +315,11 @@ private: int insertParts(const char* buf, Uint32 part, Uint32 count); int updateParts(const char* buf, Uint32 part, Uint32 count); int deleteParts(Uint32 part, Uint32 count); + // pending ops + int executePendingBlobReads(); + int executePendingBlobWrites(); + // callbacks + int invokeActiveHook(); // blob handle maintenance int atPrepare(NdbConnection* aCon, NdbOperation* anOp, const NdbColumnImpl* aColumn); int preExecute(ExecType anExecType, bool& batch); @@ -286,6 +331,7 @@ private: void setErrorCode(NdbOperation* anOp, bool invalidFlag = true); void setErrorCode(NdbConnection* aCon, bool invalidFlag = true); #ifdef VM_TRACE + int getOperationType() const; friend class NdbOut& operator<<(NdbOut&, const NdbBlob&); #endif }; diff --git a/ndb/include/ndbapi/NdbConnection.hpp b/ndb/include/ndbapi/NdbConnection.hpp index c620578cabd..c268f9aab04 100644 --- a/ndb/include/ndbapi/NdbConnection.hpp +++ b/ndb/include/ndbapi/NdbConnection.hpp @@ -19,15 +19,15 @@ #include <ndb_types.h> #include <NdbError.hpp> +#include <NdbDictionary.hpp> class NdbConnection; class NdbOperation; -class NdbCursorOperation; class NdbScanOperation; +class NdbIndexScanOperation; class NdbIndexOperation; class NdbApiSignal; class Ndb; -class NdbScanReceiver; class NdbBlob; @@ -160,7 +160,7 @@ class NdbConnection friend class NdbOperation; friend class NdbScanOperation; friend class NdbIndexOperation; - friend class NdbScanReceiver; + friend class NdbIndexScanOperation; friend class NdbBlob; public: @@ -178,56 +178,31 @@ 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. @@ -337,76 +312,17 @@ public: */ void close(); - /** @} *********************************************************************/ - - /** - * @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. + * Restart transaction * - * @note Please contact for examples of efficient scan - * updates and deletes. + * Once a transaction has been completed successfully + * it can be started again wo/ calling closeTransaction/startTransaction * - * @return - * - -1: if unsuccessful,<br> - * - 0: if another tuple was received, and<br> - * - 1: if there are no more tuples to scan. - * - 2: if there are no more cached records in NdbApi + * Note this method also releases completed operations */ - int nextScanResult(bool fetchAllowed = true); + int restart(); - /** - * 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 @@ -514,15 +430,30 @@ public: */ const NdbOperation * getNextCompletedOperation(const NdbOperation * op)const; + /** @} *********************************************************************/ + /** - * Release completed operations + * Execute the transaction in NoCommit mode if there are any not-yet + * executed blob part operations of given types. Otherwise do + * nothing. The flags argument is bitwise OR of (1 << optype) where + * optype comes from NdbOperation::OperationType. Only the basic PK + * ops are used (read, insert, update, delete). */ - void releaseCompletedOperations(); + int executePendingBlobOps(Uint8 flags = 0xFF); - - /** @} *********************************************************************/ + // Fast path calls for MySQL ha_ndbcluster + NdbOperation* getNdbOperation(NdbDictionary::Table * table); + NdbIndexOperation* getNdbIndexOperation(NdbDictionary::Index * index, + NdbDictionary::Table * table); + NdbScanOperation* getNdbScanOperation(NdbDictionary::Table * table); + NdbIndexScanOperation* getNdbIndexScanOperation(NdbDictionary::Index * index, + NdbDictionary::Table * table); private: + /** + * Release completed operations + */ + void releaseCompletedOperations(); typedef Uint64 TimeMillis_t; /************************************************************************** @@ -587,13 +518,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 @@ -616,7 +541,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); @@ -633,10 +558,12 @@ private: int checkMagicNumber(); // Verify correct object NdbOperation* getNdbOperation(class NdbTableImpl* aTable, NdbOperation* aNextOp = 0); - NdbScanOperation* getNdbScanOperation(class NdbTableImpl* aTable); + NdbIndexScanOperation* getNdbScanOperation(class NdbTableImpl* aTable); NdbIndexOperation* getNdbIndexOperation(class NdbIndexImpl* anIndex, class NdbTableImpl* aTable, NdbOperation* aNextOp = 0); + NdbIndexScanOperation* getNdbIndexScanOperation(NdbIndexImpl* index, + NdbTableImpl* table); void handleExecuteCompletion(); @@ -687,7 +614,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 @@ -723,23 +649,20 @@ private: Uint32 theNodeSequence; // The sequence no of the db node bool theReleaseOnClose; - // Cursor operations + // Scan operations bool m_waitForReply; - NdbCursorOperation* m_theFirstCursorOperation; - NdbCursorOperation* m_theLastCursorOperation; + NdbIndexScanOperation* m_theFirstScanOperation; + NdbIndexScanOperation* m_theLastScanOperation; - NdbCursorOperation* m_firstExecutedCursorOp; - // Scan operations - bool theScanFinished; + 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; // optim: any blobs bool theBlobFlag; + Uint8 thePendingBlobOps; static void sendTC_COMMIT_ACK(NdbApiSignal *, Uint32 transId1, Uint32 transId2, @@ -749,6 +672,7 @@ private: #ifdef VM_TRACE void printState(); #endif + bool checkState_TransId(const Uint32 * transId) const; }; inline @@ -783,6 +707,16 @@ NdbConnection::checkMagicNumber() } } +inline +bool +NdbConnection::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; + return b; +} + /************************************************************************************************ void setTransactionId(Uint64 aTransactionId); @@ -956,6 +890,21 @@ NdbConnection::OpSent() theNoOfOpSent++; } +/****************************************************************************** +void executePendingBlobOps(); +******************************************************************************/ +#include <stdlib.h> +inline +int +NdbConnection::executePendingBlobOps(Uint8 flags) +{ + if (thePendingBlobOps & flags) { + // not executeNoBlobs because there can be new ops with blobs + return execute(NoCommit); + } + return 0; +} + inline Uint32 NdbConnection::ptr2int(){ @@ -963,5 +912,3 @@ NdbConnection::ptr2int(){ } #endif - - 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 <NdbOperation.hpp> - -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/NdbDictionary.hpp b/ndb/include/ndbapi/NdbDictionary.hpp index 3b38e33ec91..b5c3985c6cb 100644 --- a/ndb/include/ndbapi/NdbDictionary.hpp +++ b/ndb/include/ndbapi/NdbDictionary.hpp @@ -144,6 +144,8 @@ public: FragAllLarge = 4 ///< Eight fragments per node group. }; }; + + class Table; // forward declaration /** * @class Column @@ -183,7 +185,7 @@ public: Datetime, ///< Precision down to 1 sec (sizeof(Datetime) == 8 bytes ) Timespec, ///< Precision down to 1 nsec(sizeof(Datetime) == 12 bytes ) Blob, ///< Binary large object (see NdbBlob) - Clob ///< Text blob + Text ///< Text blob }; /** @@ -309,7 +311,8 @@ public: /** * For blob, set or get "part size" i.e. number of bytes to store in - * each tuple of the "blob table". Must be less than 64k. + * each tuple of the "blob table". Can be set to zero to omit parts + * and to allow only inline bytes ("tinyblob"). */ void setPartSize(int size) { setScale(size); } int getPartSize() const { return getScale(); } @@ -324,7 +327,7 @@ public: /** * Get size of element */ - int Column::getSize() const; + int getSize() const; /** * Set distribution key @@ -364,6 +367,8 @@ public: void setIndexOnlyStorage(bool); bool getIndexOnlyStorage() const; + const Table * getBlobTable() const; + /** * @name ODBC Specific methods * @{ @@ -1060,6 +1065,6 @@ public: }; }; -class NdbOut& operator <<(class NdbOut& ndbout, const NdbDictionary::Column::Type type); +class NdbOut& operator <<(class NdbOut& out, const NdbDictionary::Column& col); #endif diff --git a/ndb/include/ndbapi/NdbIndexOperation.hpp b/ndb/include/ndbapi/NdbIndexOperation.hpp index baf31dca0ee..2d873c52e56 100644 --- a/ndb/include/ndbapi/NdbIndexOperation.hpp +++ b/ndb/include/ndbapi/NdbIndexOperation.hpp @@ -29,7 +29,7 @@ #ifndef NdbIndexOperation_H #define NdbIndexOperation_H -#include <NdbCursorOperation.hpp> +#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..82aed04a9fc --- /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 <NdbScanOperation.hpp> + +/** + * @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 lower and/or upper bound, or can be set + * equal to a value. The bounds can be defined in any order but + * a duplicate definition is an error. + * + * The bounds must specify a single range i.e. they are on an initial + * sequence of index keys and the condition is equality for all but + * (at most) the last key which has a lower and/or upper bound. + * + * NULL is treated like a normal value which is less than any not-NULL + * value and equal to another NULL value. To search for NULL use + * setBound with null pointer (0). + * + * An index stores also all-NULL keys (this may become optional). + * Doing index scan with empty bound set returns all table tuples. + * + * @param attrName Attribute name, alternatively: + * @param anAttrId Index column id (starting from 0) + * @param type Type of bound + * @param value Pointer to bound value, 0 for NULL + * @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); + int saveBoundATTRINFO(); + + 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 cfa656cb2d5..c48dccd4864 100644 --- a/ndb/include/ndbapi/NdbOperation.hpp +++ b/ndb/include/ndbapi/NdbOperation.hpp @@ -42,8 +42,8 @@ class NdbOperation friend class NdbScanReceiver; friend class NdbScanFilter; friend class NdbScanFilterImpl; + friend class NdbReceiver; friend class NdbBlob; - public: /** * @name Define Standard Operation Type @@ -196,196 +196,7 @@ 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 @@ -883,16 +694,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 @@ -938,19 +740,12 @@ 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); int prepareSendInterpreted(); // Help routine to prepare* - void TCOPCONF(Uint32 anNdbColumnImplLen); // Handle TC[KEY/INDX]CONF signal - int receiveTCKEYREF(NdbApiSignal*); @@ -958,7 +753,7 @@ protected: int receiveREAD_CONF(const Uint32* aDataPtr, Uint32 aDataLength); - int checkMagicNumber(); // Verify correct object + int checkMagicNumber(bool b = true); // Verify correct object int checkState_TransId(NdbApiSignal* aSignal); @@ -966,10 +761,8 @@ protected: * These are support methods only used locally in this class. ******************************************************************************/ - virtual int equal_impl(const NdbColumnImpl* anAttrObject, - const char* aValue, - Uint32 len); - NdbRecAttr* getValue(const NdbColumnImpl* anAttrObject, char* aValue = 0); + virtual int equal_impl(const NdbColumnImpl*,const char* aValue, Uint32 len); + virtual NdbRecAttr* getValue_impl(const NdbColumnImpl*, char* aValue = 0); int setValue(const NdbColumnImpl* anAttrObject, const char* aValue, Uint32 len); NdbBlob* getBlobHandle(NdbConnection* aCon, const NdbColumnImpl* anAttrObject); int incValue(const NdbColumnImpl* anAttrObject, Uint32 aValue); @@ -981,15 +774,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, @@ -1013,12 +803,8 @@ protected: Uint32 ptr2int() { return theReceiver.getId(); }; - NdbOperation* - takeOverScanOp(OperationType opType, NdbConnection* updateTrans); - // get table or index key from prepared signals int getKeyFromTCREQ(Uint32* data, unsigned size); - int getKeyFromKEYINFO20(Uint32* data, unsigned size); /****************************************************************************** * These are the private variables that are defined in the operation objects. @@ -1032,7 +818,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 @@ -1043,9 +828,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; @@ -1060,11 +842,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 class NdbTableImpl* m_currentTable; // The current table class NdbTableImpl* m_accessTable; @@ -1106,15 +883,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; @@ -1130,11 +898,11 @@ protected: inline int -NdbOperation::checkMagicNumber() +NdbOperation::checkMagicNumber(bool b) { if (theMagicNumber != 0xABCDEF01){ #ifdef NDB_NO_DROPPED_SIGNAL - abort(); + if(b) abort(); #endif return -1; } diff --git a/ndb/include/ndbapi/NdbRecAttr.hpp b/ndb/include/ndbapi/NdbRecAttr.hpp index 36b54035d96..da03df13027 100644 --- a/ndb/include/ndbapi/NdbRecAttr.hpp +++ b/ndb/include/ndbapi/NdbRecAttr.hpp @@ -73,8 +73,9 @@ class NdbOperation; class NdbRecAttr { friend class NdbOperation; + friend class NdbIndexScanOperation; friend class NdbEventOperationImpl; - friend class NdbScanReceiver; + friend class NdbReceiver; friend class Ndb; friend class NdbOut& operator<<(class NdbOut&, const class AttributeS&); @@ -244,9 +245,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 */ @@ -269,6 +269,7 @@ private: Uint32 theAttrId; /* The attribute id */ int theNULLind; + bool m_nullable; Uint32 theAttrSize; Uint32 theArraySize; const NdbDictionary::Column* m_column; @@ -289,29 +290,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 @@ -449,24 +428,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..13898fc8e5f 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, @@ -32,6 +38,7 @@ public: NdbReceiver(Ndb *aNdb); void init(ReceiverType type, void* owner); + 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..483e08179c0 100644 --- a/ndb/include/ndbapi/NdbResultSet.hpp +++ b/ndb/include/ndbapi/NdbResultSet.hpp @@ -30,17 +30,15 @@ #define NdbResultSet_H -#include <NdbCursorOperation.hpp> -#include <NdbIndexOperation.hpp> #include <NdbScanOperation.hpp> /** * @class NdbResultSet - * @brief NdbResultSet contains a NdbCursorOperation. + * @brief NdbResultSet contains a NdbScanOperation. */ class NdbResultSet { - friend class NdbCursorOperation; + friend class NdbScanOperation; public: @@ -93,22 +91,62 @@ public: */ int nextResult(bool fetchAllowed = true); + /** + * Close result set (scan) + */ void close(); - NdbOperation* updateTuple(); - NdbOperation* updateTuple(NdbConnection* takeOverTransaction); + /** + * Restart + */ + int restart(); + /** + * 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* 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 151dc5bb99f..c7ae029e742 100644 --- a/ndb/include/ndbapi/NdbScanOperation.hpp +++ b/ndb/include/ndbapi/NdbScanOperation.hpp @@ -29,9 +29,7 @@ #ifndef NdbScanOperation_H #define NdbScanOperation_H - #include <NdbOperation.hpp> -#include <NdbCursorOperation.hpp> class NdbBlob; @@ -39,63 +37,71 @@ class NdbBlob; * @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; - + friend class NdbBlob; 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); + + inline NdbResultSet* readTuples(int parallell){ + return readTuples(LM_Read, 0, parallell); + } + + inline NdbResultSet* readTuplesExclusive(int parallell = 0){ + return readTuples(LM_Exclusive, 0, parallell); + } -#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL - - 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 - NdbBlob* getBlobHandle(const char* anAttrName); NdbBlob* getBlobHandle(Uint32 anAttrId); -private: - NdbScanOperation(Ndb* aNdb); +protected: + CursorType m_cursor_type; + NdbScanOperation(Ndb* aNdb); ~NdbScanOperation(); - NdbCursorOperation::CursorType cursorType(); - - virtual int nextResult(bool fetchAllowed = true); + int nextResult(bool fetchAllowed = true); virtual void release(); void closeScan(); @@ -111,125 +117,54 @@ 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) -{ -} + int getFirstATTRINFOScan(); + int doSendScan(int ProcessorId); + int prepareSendScan(Uint32 TC_ConnectPtr, Uint64 TransactionId); + + int fix_receivers(Uint32 parallel); + Uint32* m_array; // containing all arrays below + Uint32 m_allocated_receivers; + NdbReceiver** m_receivers; // All receivers -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; -}; + 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(); -inline -SetValueRecList::SetValueRecList() : - first(0), - last(0) -{ -} + int getKeyFromKEYINFO20(Uint32* data, unsigned size); + NdbOperation* takeOverScanOp(OperationType opType, NdbConnection*); -inline -SetValueRecList::~SetValueRecList() { - if (first) delete first; - first = last = 0; -} + Uint32 m_ordered; + int restart(); +}; 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/include/portlib/NdbTCP.h b/ndb/include/portlib/NdbTCP.h index 42c34855c39..4dc8435eef1 100644 --- a/ndb/include/portlib/NdbTCP.h +++ b/ndb/include/portlib/NdbTCP.h @@ -64,7 +64,7 @@ typedef int socklen_t; #define NDB_NONBLOCK O_NONBLOCK #define NDB_SOCKET_TYPE int #define NDB_INVALID_SOCKET -1 -#define NDB_CLOSE_SOCKET(x) close(x) +#define NDB_CLOSE_SOCKET(x) ::close(x) #define InetErrno errno diff --git a/ndb/include/transporter/TransporterDefinitions.hpp b/ndb/include/transporter/TransporterDefinitions.hpp index cb859e310db..0301d12348f 100644 --- a/ndb/include/transporter/TransporterDefinitions.hpp +++ b/ndb/include/transporter/TransporterDefinitions.hpp @@ -69,6 +69,7 @@ struct TCP_TransporterConfiguration { * SHM Transporter Configuration */ struct SHM_TransporterConfiguration { + Uint32 port; NodeId remoteNodeId; NodeId localNodeId; bool compression; diff --git a/ndb/include/transporter/TransporterRegistry.hpp b/ndb/include/transporter/TransporterRegistry.hpp index 6c979777f18..3c6c307406c 100644 --- a/ndb/include/transporter/TransporterRegistry.hpp +++ b/ndb/include/transporter/TransporterRegistry.hpp @@ -29,20 +29,10 @@ #define TransporterRegistry_H #include "TransporterDefinitions.hpp" +#include <SocketServer.hpp> #include <NdbTCP.h> -// A transporter is always in a PerformState. -// PerformIO is used initially and as long as any of the events -// PerformConnect, ... -enum PerformState { - PerformNothing = 4, // Does nothing - PerformIO = 0, // Is connected - PerformConnect = 1, // Is trying to connect - PerformDisconnect = 2, // Trying to disconnect - RemoveTransporter = 3 // Will be removed -}; - // A transporter is always in an IOState. // NoHalt is used initially and as long as it is no restrictions on // sending or receiving. @@ -60,18 +50,45 @@ enum TransporterType { tt_OSE_TRANSPORTER = 4 }; +static const char *performStateString[] = + { "is connected", + "is trying to connect", + "does nothing", + "is trying to disconnect" }; + class Transporter; class TCP_Transporter; class SCI_Transporter; class SHM_Transporter; class OSE_Transporter; +class TransporterRegistry; +class SocketAuthenticator; + +class TransporterService : public SocketServer::Service { + SocketAuthenticator * m_auth; + TransporterRegistry * m_transporter_registry; +public: + TransporterService(SocketAuthenticator *auth= 0) + { + m_auth= auth; + m_transporter_registry= 0; + } + void setTransporterRegistry(TransporterRegistry *t) + { + m_transporter_registry= t; + } + SocketServer::Session * newSession(NDB_SOCKET_TYPE socket); +}; + /** * @class TransporterRegistry * @brief ... */ class TransporterRegistry { friend class OSE_Receiver; + friend class Transporter; + friend class TransporterService; public: /** * Constructor @@ -98,6 +115,12 @@ public: */ ~TransporterRegistry(); + bool start_service(SocketServer& server); + bool start_clients(); + bool stop_clients(); + void start_clients_thread(); + void update_connections(); + /** * Start/Stop receiving */ @@ -110,16 +133,26 @@ public: void startSending(); void stopSending(); + // A transporter is always in a PerformState. + // PerformIO is used initially and as long as any of the events + // PerformConnect, ... + enum PerformState { + CONNECTED = 0, + CONNECTING = 1, + DISCONNECTED = 2, + DISCONNECTING = 3 + }; + const char *getPerformStateString(NodeId nodeId) const + { return performStateString[(unsigned)performStates[nodeId]]; }; + /** * Get and set methods for PerformState */ - PerformState performState(NodeId nodeId); - void setPerformState(NodeId nodeId, PerformState state); - - /** - * Set perform state for all transporters - */ - void setPerformState(PerformState state); + void do_connect(NodeId node_id); + void do_disconnect(NodeId node_id); + bool is_connected(NodeId node_id) { return performStates[node_id] == CONNECTED; }; + void report_connect(NodeId node_id); + void report_disconnect(NodeId node_id, int errnum); /** * Get and set methods for IOState @@ -174,8 +207,6 @@ public: void performReceive(); void performSend(); - void checkConnections(); - /** * Force sending if more than or equal to sendLimit * number have asked for send. Returns 0 if not sending @@ -187,11 +218,18 @@ public: void printState(); #endif + unsigned short m_service_port; + protected: private: void * callbackObj; + TransporterService *m_transporter_service; + char *m_interface_name; + struct NdbThread *m_start_clients_thread; + bool m_run_start_clients_thread; + int sendCounter; NodeId localNodeId; bool nodeIdSpecified; @@ -202,11 +240,6 @@ private: int nSHMTransporters; int nOSETransporters; - int m_ccCount; - int m_ccIndex; - int m_ccStep; - int m_nTransportersPerformConnect; - bool m_ccReady; /** * Arrays holding all transporters in the order they are created */ diff --git a/ndb/include/util/BaseString.hpp b/ndb/include/util/BaseString.hpp index 8755c13e9bb..a1bb91ea9c5 100644 --- a/ndb/include/util/BaseString.hpp +++ b/ndb/include/util/BaseString.hpp @@ -176,7 +176,7 @@ public: /** * Trim string from <i>delim</i> */ - static char* trim(char * src, const char * delim = " \t"); + static char* trim(char * src, const char * delim); private: char* m_chr; unsigned m_len; diff --git a/ndb/include/util/Bitmask.hpp b/ndb/include/util/Bitmask.hpp index 7355742f845..bb217adab5f 100644 --- a/ndb/include/util/Bitmask.hpp +++ b/ndb/include/util/Bitmask.hpp @@ -19,11 +19,6 @@ #include <ndb_global.h> -#ifndef NDB_ASSERT -#define NDB_ASSERT(x, s) \ - do { if (!(x)) { printf("%s\n", s); abort(); } } while (0) -#endif - /** * Bitmask implementation. Size is given explicitly * (as first argument). All methods are static. @@ -140,7 +135,7 @@ public: inline bool BitmaskImpl::get(unsigned size, const Uint32 data[], unsigned n) { - NDB_ASSERT(n < (size << 5), "bit get out of range"); + assert(n < (size << 5)); return (data[n >> 5] & (1 << (n & 31))) != 0; } @@ -153,7 +148,7 @@ BitmaskImpl::set(unsigned size, Uint32 data[], unsigned n, bool value) inline void BitmaskImpl::set(unsigned size, Uint32 data[], unsigned n) { - NDB_ASSERT(n < (size << 5), "bit set out of range"); + assert(n < (size << 5)); data[n >> 5] |= (1 << (n & 31)); } @@ -176,7 +171,7 @@ BitmaskImpl::assign(unsigned size, Uint32 dst[], const Uint32 src[]) inline void BitmaskImpl::clear(unsigned size, Uint32 data[], unsigned n) { - NDB_ASSERT(n < (size << 5), "bit clear out of range"); + assert(n < (size << 5)); data[n >> 5] &= ~(1 << (n & 31)); } @@ -326,7 +321,7 @@ BitmaskImpl::getText(unsigned size, const Uint32 data[], char* buf) * XXX replace size by length in bits */ template <unsigned size> -class Bitmask { +struct BitmaskPOD { public: /** * POD data representation @@ -334,7 +329,7 @@ public: struct Data { Uint32 data[size]; #if 0 - Data & operator=(const Bitmask<size> & src) { + Data & operator=(const BitmaskPOD<size> & src) { src.copyto(size, data); return *this; } @@ -348,19 +343,17 @@ public: STATIC_CONST( NotFound = BitmaskImpl::NotFound ); STATIC_CONST( TextLength = size * 8 ); - Bitmask() { clear();} - /** * assign - Set all bits in <em>dst</em> to corresponding in <em>src/<em> */ - void assign(const typename Bitmask<size>::Data & src); + void assign(const typename BitmaskPOD<size>::Data & src); /** * assign - Set all bits in <em>dst</em> to corresponding in <em>src/<em> */ static void assign(Uint32 dst[], const Uint32 src[]); - static void assign(Uint32 dst[], const Bitmask<size> & src); - void assign(const Bitmask<size> & src); + static void assign(Uint32 dst[], const BitmaskPOD<size> & src); + void assign(const BitmaskPOD<size> & src); /** * copy this to <em>dst</em> @@ -432,43 +425,43 @@ public: * equal - Bitwise equal. */ static bool equal(const Uint32 data[], const Uint32 data2[]); - bool equal(const Bitmask<size>& mask2) const; + bool equal(const BitmaskPOD<size>& mask2) const; /** * bitOR - Bitwise (x | y) into first operand. */ static void bitOR(Uint32 data[], const Uint32 data2[]); - Bitmask<size>& bitOR(const Bitmask<size>& mask2); + BitmaskPOD<size>& bitOR(const BitmaskPOD<size>& mask2); /** * bitAND - Bitwise (x & y) into first operand. */ static void bitAND(Uint32 data[], const Uint32 data2[]); - Bitmask<size>& bitAND(const Bitmask<size>& mask2); + BitmaskPOD<size>& bitAND(const BitmaskPOD<size>& mask2); /** * bitANDC - Bitwise (x & ~y) into first operand. */ static void bitANDC(Uint32 data[], const Uint32 data2[]); - Bitmask<size>& bitANDC(const Bitmask<size>& mask2); + BitmaskPOD<size>& bitANDC(const BitmaskPOD<size>& mask2); /** * bitXOR - Bitwise (x ^ y) into first operand. */ static void bitXOR(Uint32 data[], const Uint32 data2[]); - Bitmask<size>& bitXOR(const Bitmask<size>& mask2); + BitmaskPOD<size>& bitXOR(const BitmaskPOD<size>& mask2); /** * contains - Check if all bits set in data2 (that) are also set in data (this) */ static bool contains(Uint32 data[], const Uint32 data2[]); - bool contains(Bitmask<size> that); + bool contains(BitmaskPOD<size> that); /** - * overlaps - Check if any bit set in this Bitmask (data) is also set in that (data2) + * overlaps - Check if any bit set in this BitmaskPOD (data) is also set in that (data2) */ static bool overlaps(Uint32 data[], const Uint32 data2[]); - bool overlaps(Bitmask<size> that); + bool overlaps(BitmaskPOD<size> that); /** * getText - Return as hex-digits (only for debug routines). @@ -479,286 +472,292 @@ public: template <unsigned size> inline void -Bitmask<size>::assign(Uint32 dst[], const Uint32 src[]) +BitmaskPOD<size>::assign(Uint32 dst[], const Uint32 src[]) { BitmaskImpl::assign(size, dst, src); } template <unsigned size> inline void -Bitmask<size>::assign(Uint32 dst[], const Bitmask<size> & src) +BitmaskPOD<size>::assign(Uint32 dst[], const BitmaskPOD<size> & src) { BitmaskImpl::assign(size, dst, src.rep.data); } template <unsigned size> inline void -Bitmask<size>::assign(const typename Bitmask<size>::Data & src) +BitmaskPOD<size>::assign(const typename BitmaskPOD<size>::Data & src) { - assign(rep.data, src.data); + BitmaskPOD<size>::assign(rep.data, src.data); } template <unsigned size> inline void -Bitmask<size>::assign(const Bitmask<size> & src) +BitmaskPOD<size>::assign(const BitmaskPOD<size> & src) { - assign(rep.data, src.rep.data); + BitmaskPOD<size>::assign(rep.data, src.rep.data); } template <unsigned size> inline void -Bitmask<size>::copyto(unsigned sz, Uint32 dst[]) const +BitmaskPOD<size>::copyto(unsigned sz, Uint32 dst[]) const { BitmaskImpl::assign(sz, dst, rep.data); } template <unsigned size> inline void -Bitmask<size>::assign(unsigned sz, const Uint32 src[]) +BitmaskPOD<size>::assign(unsigned sz, const Uint32 src[]) { BitmaskImpl::assign(sz, rep.data, src); } template <unsigned size> inline bool -Bitmask<size>::get(const Uint32 data[], unsigned n) +BitmaskPOD<size>::get(const Uint32 data[], unsigned n) { return BitmaskImpl::get(size, data, n); } template <unsigned size> inline bool -Bitmask<size>::get(unsigned n) const +BitmaskPOD<size>::get(unsigned n) const { - return get(rep.data, n); + return BitmaskPOD<size>::get(rep.data, n); } template <unsigned size> inline void -Bitmask<size>::set(Uint32 data[], unsigned n, bool value) +BitmaskPOD<size>::set(Uint32 data[], unsigned n, bool value) { BitmaskImpl::set(size, data, n, value); } template <unsigned size> inline void -Bitmask<size>::set(unsigned n, bool value) +BitmaskPOD<size>::set(unsigned n, bool value) { - set(rep.data, n, value); + BitmaskPOD<size>::set(rep.data, n, value); } template <unsigned size> inline void -Bitmask<size>::set(Uint32 data[], unsigned n) +BitmaskPOD<size>::set(Uint32 data[], unsigned n) { BitmaskImpl::set(size, data, n); } template <unsigned size> inline void -Bitmask<size>::set(unsigned n) +BitmaskPOD<size>::set(unsigned n) { - set(rep.data, n); + BitmaskPOD<size>::set(rep.data, n); } template <unsigned size> inline void -Bitmask<size>::set(Uint32 data[]) +BitmaskPOD<size>::set(Uint32 data[]) { BitmaskImpl::set(size, data); } template <unsigned size> inline void -Bitmask<size>::set() +BitmaskPOD<size>::set() { - set(rep.data); + BitmaskPOD<size>::set(rep.data); } template <unsigned size> inline void -Bitmask<size>::clear(Uint32 data[], unsigned n) +BitmaskPOD<size>::clear(Uint32 data[], unsigned n) { BitmaskImpl::clear(size, data, n); } template <unsigned size> inline void -Bitmask<size>::clear(unsigned n) +BitmaskPOD<size>::clear(unsigned n) { - clear(rep.data, n); + BitmaskPOD<size>::clear(rep.data, n); } template <unsigned size> inline void -Bitmask<size>::clear(Uint32 data[]) +BitmaskPOD<size>::clear(Uint32 data[]) { BitmaskImpl::clear(size, data); } template <unsigned size> inline void -Bitmask<size>::clear() +BitmaskPOD<size>::clear() { - clear(rep.data); + BitmaskPOD<size>::clear(rep.data); } template <unsigned size> inline bool -Bitmask<size>::isclear(const Uint32 data[]) +BitmaskPOD<size>::isclear(const Uint32 data[]) { return BitmaskImpl::isclear(size, data); } template <unsigned size> inline bool -Bitmask<size>::isclear() const +BitmaskPOD<size>::isclear() const { - return isclear(rep.data); + return BitmaskPOD<size>::isclear(rep.data); } template <unsigned size> unsigned -Bitmask<size>::count(const Uint32 data[]) +BitmaskPOD<size>::count(const Uint32 data[]) { return BitmaskImpl::count(size, data); } template <unsigned size> inline unsigned -Bitmask<size>::count() const +BitmaskPOD<size>::count() const { - return count(rep.data); + return BitmaskPOD<size>::count(rep.data); } template <unsigned size> unsigned -Bitmask<size>::find(const Uint32 data[], unsigned n) +BitmaskPOD<size>::find(const Uint32 data[], unsigned n) { return BitmaskImpl::find(size, data, n); } template <unsigned size> inline unsigned -Bitmask<size>::find(unsigned n) const +BitmaskPOD<size>::find(unsigned n) const { - return find(rep.data, n); + return BitmaskPOD<size>::find(rep.data, n); } template <unsigned size> inline bool -Bitmask<size>::equal(const Uint32 data[], const Uint32 data2[]) +BitmaskPOD<size>::equal(const Uint32 data[], const Uint32 data2[]) { return BitmaskImpl::equal(size, data, data2); } template <unsigned size> inline bool -Bitmask<size>::equal(const Bitmask<size>& mask2) const +BitmaskPOD<size>::equal(const BitmaskPOD<size>& mask2) const { - return equal(rep.data, mask2.rep.data); + return BitmaskPOD<size>::equal(rep.data, mask2.rep.data); } template <unsigned size> inline void -Bitmask<size>::bitOR(Uint32 data[], const Uint32 data2[]) +BitmaskPOD<size>::bitOR(Uint32 data[], const Uint32 data2[]) { BitmaskImpl::bitOR(size,data, data2); } template <unsigned size> -inline Bitmask<size>& -Bitmask<size>::bitOR(const Bitmask<size>& mask2) +inline BitmaskPOD<size>& +BitmaskPOD<size>::bitOR(const BitmaskPOD<size>& mask2) { - bitOR(rep.data, mask2.rep.data); + BitmaskPOD<size>::bitOR(rep.data, mask2.rep.data); return *this; } template <unsigned size> inline void -Bitmask<size>::bitAND(Uint32 data[], const Uint32 data2[]) +BitmaskPOD<size>::bitAND(Uint32 data[], const Uint32 data2[]) { BitmaskImpl::bitAND(size,data, data2); } template <unsigned size> -inline Bitmask<size>& -Bitmask<size>::bitAND(const Bitmask<size>& mask2) +inline BitmaskPOD<size>& +BitmaskPOD<size>::bitAND(const BitmaskPOD<size>& mask2) { - bitAND(rep.data, mask2.rep.data); + BitmaskPOD<size>::bitAND(rep.data, mask2.rep.data); return *this; } template <unsigned size> inline void -Bitmask<size>::bitANDC(Uint32 data[], const Uint32 data2[]) +BitmaskPOD<size>::bitANDC(Uint32 data[], const Uint32 data2[]) { BitmaskImpl::bitANDC(size,data, data2); } template <unsigned size> -inline Bitmask<size>& -Bitmask<size>::bitANDC(const Bitmask<size>& mask2) +inline BitmaskPOD<size>& +BitmaskPOD<size>::bitANDC(const BitmaskPOD<size>& mask2) { - bitANDC(rep.data, mask2.rep.data); + BitmaskPOD<size>::bitANDC(rep.data, mask2.rep.data); return *this; } template <unsigned size> inline void -Bitmask<size>::bitXOR(Uint32 data[], const Uint32 data2[]) +BitmaskPOD<size>::bitXOR(Uint32 data[], const Uint32 data2[]) { BitmaskImpl::bitXOR(size,data, data2); } template <unsigned size> -inline Bitmask<size>& -Bitmask<size>::bitXOR(const Bitmask<size>& mask2) +inline BitmaskPOD<size>& +BitmaskPOD<size>::bitXOR(const BitmaskPOD<size>& mask2) { - bitXOR(rep.data, mask2.rep.data); + BitmaskPOD<size>::bitXOR(rep.data, mask2.rep.data); return *this; } template <unsigned size> char * -Bitmask<size>::getText(const Uint32 data[], char* buf) +BitmaskPOD<size>::getText(const Uint32 data[], char* buf) { return BitmaskImpl::getText(size, data, buf); } template <unsigned size> inline char * -Bitmask<size>::getText(char* buf) const +BitmaskPOD<size>::getText(char* buf) const { - return getText(rep.data, buf); + return BitmaskPOD<size>::getText(rep.data, buf); } template <unsigned size> inline bool -Bitmask<size>::contains(Uint32 data[], const Uint32 data2[]) +BitmaskPOD<size>::contains(Uint32 data[], const Uint32 data2[]) { return BitmaskImpl::contains(size, data, data2); } template <unsigned size> inline bool -Bitmask<size>::contains(Bitmask<size> that) +BitmaskPOD<size>::contains(BitmaskPOD<size> that) { - return contains(this->rep.data, that.rep.data); + return BitmaskPOD<size>::contains(this->rep.data, that.rep.data); } template <unsigned size> inline bool -Bitmask<size>::overlaps(Uint32 data[], const Uint32 data2[]) +BitmaskPOD<size>::overlaps(Uint32 data[], const Uint32 data2[]) { return BitmaskImpl::overlaps(size, data, data2); } template <unsigned size> inline bool -Bitmask<size>::overlaps(Bitmask<size> that) +BitmaskPOD<size>::overlaps(BitmaskPOD<size> that) { - return overlaps(this->rep.data, that.rep.data); + return BitmaskPOD<size>::overlaps(this->rep.data, that.rep.data); } +template <unsigned size> +class Bitmask : public BitmaskPOD<size> { +public: + Bitmask() { this->clear();} +}; + #endif diff --git a/ndb/include/util/ConfigValues.hpp b/ndb/include/util/ConfigValues.hpp index 3fbeedb25a0..457488e3c42 100644 --- a/ndb/include/util/ConfigValues.hpp +++ b/ndb/include/util/ConfigValues.hpp @@ -32,9 +32,8 @@ public: class ConstIterator { friend class ConfigValuesFactory; const ConfigValues & m_cfg; - protected: - Uint32 m_currentSection; public: + Uint32 m_currentSection; ConstIterator(const ConfigValues&c) : m_cfg(c) { m_currentSection = 0;} bool openSection(Uint32 key, Uint32 no); @@ -57,6 +56,9 @@ public: ConfigValues & m_cfg; public: Iterator(ConfigValues&c) : ConstIterator(c), m_cfg(c) {} + Iterator(ConfigValues&c, const ConstIterator& i):ConstIterator(c),m_cfg(c){ + m_currentSection = i.m_currentSection; + } bool set(Uint32 key, Uint32 value); bool set(Uint32 key, Uint64 value); diff --git a/ndb/include/util/NdbSqlUtil.hpp b/ndb/include/util/NdbSqlUtil.hpp index 841da513d4a..a79245868e0 100644 --- a/ndb/include/util/NdbSqlUtil.hpp +++ b/ndb/include/util/NdbSqlUtil.hpp @@ -17,8 +17,7 @@ #ifndef NDB_SQL_UTIL_HPP #define NDB_SQL_UTIL_HPP -#include <string.h> -#include <ndb_types.h> +#include <ndb_global.h> #include <kernel/ndb_limits.h> class NdbSqlUtil { @@ -80,7 +79,7 @@ public: Datetime, // Precision down to 1 sec (size 8 bytes) Timespec, // Precision down to 1 nsec (size 12 bytes) Blob, // Blob - Clob // Text blob + Text // Text blob }; Enum m_typeId; Cmp* m_cmp; // set to NULL if cmp not implemented @@ -125,12 +124,13 @@ private: static Cmp cmpDatetime; static Cmp cmpTimespec; static Cmp cmpBlob; - static Cmp cmpClob; + static Cmp cmpText; }; inline int NdbSqlUtil::cmp(Uint32 typeId, const Uint32* p1, const Uint32* p2, Uint32 full, Uint32 size) { + // XXX require size >= 1 if (size > full) return CmpError; switch ((Type::Enum)typeId) { @@ -192,10 +192,38 @@ NdbSqlUtil::cmp(Uint32 typeId, const Uint32* p1, const Uint32* p2, Uint32 full, } return CmpUnknown; } - case Type::Mediumint: // XXX fix these - break; + case Type::Mediumint: + { + if (size >= 1) { + union { const Uint32* p; const unsigned char* v; } u1, u2; + u1.p = p1; + u2.p = p2; + Int32 v1 = sint3korr(u1.v); + Int32 v2 = sint3korr(u2.v); + if (v1 < v2) + return -1; + if (v1 > v2) + return +1; + return 0; + } + return CmpUnknown; + } case Type::Mediumunsigned: - break; + { + if (size >= 1) { + union { const Uint32* p; const unsigned char* v; } u1, u2; + u1.p = p1; + u2.p = p2; + Uint32 v1 = uint3korr(u1.v); + Uint32 v2 = uint3korr(u2.v); + if (v1 < v2) + return -1; + if (v1 > v2) + return +1; + return 0; + } + return CmpUnknown; + } case Type::Int: { if (size >= 1) { @@ -287,6 +315,7 @@ NdbSqlUtil::cmp(Uint32 typeId, const Uint32* p1, const Uint32* p2, Uint32 full, return CmpUnknown; } case Type::Decimal: + // XXX not used by MySQL or NDB break; case Type::Char: { @@ -317,10 +346,28 @@ NdbSqlUtil::cmp(Uint32 typeId, const Uint32* p1, const Uint32* p2, Uint32 full, } return CmpUnknown; } - case Type::Binary: // XXX fix these - break; + case Type::Binary: + { + // compare byte wise + union { const Uint32* p; const char* v; } u1, u2; + u1.p = p1; + u2.p = p2; + int k = memcmp(u1.v, u2.v, size << 2); + return k < 0 ? -1 : k > 0 ? +1 : full == size ? 0 : CmpUnknown; + } case Type::Varbinary: - break; + { + // assume correctly padded and compare byte wise + if (size >= 1) { + union { const Uint32* p; const char* v; } u1, u2; + u1.p = p1; + u2.p = p2; + // length in first 2 bytes + int k = memcmp(u1.v + 2, u2.v + 2, (size << 2) - 2); + return k < 0 ? -1 : k > 0 ? +1 : full == size ? 0 : CmpUnknown; + } + return CmpUnknown; + } case Type::Datetime: { /* @@ -331,29 +378,66 @@ NdbSqlUtil::cmp(Uint32 typeId, const Uint32* p1, const Uint32* p2, Uint32 full, u1.p = p1; u2.p = p2; // skip format check - int k = strncmp(u1.v, u2.v, 4); + int k = memcmp(u1.v, u2.v, 4); if (k != 0) - return k; + return k < 0 ? -1 : +1; if (size >= 2) { - return strncmp(u1.v + 4, u2.v + 4, 4); + k = memcmp(u1.v + 4, u2.v + 4, 4); + return k < 0 ? -1 : k > 0 ? +1 : 0; } } return CmpUnknown; } - case Type::Timespec: // XXX fix this - break; - case Type::Blob: // XXX fix - break; - case Type::Clob: + case Type::Timespec: + { + /* + * Timespec is CC YY MM DD hh mm ss \0 NN NN NN NN + */ + if (size >= 1) { + union { const Uint32* p; const char* v; } u1, u2; + u1.p = p1; + u2.p = p2; + // skip format check + int k = memcmp(u1.v, u2.v, 4); + if (k != 0) + return k < 0 ? -1 : +1; + if (size >= 2) { + k = memcmp(u1.v + 4, u2.v + 4, 4); + if (k != 0) + return k < 0 ? -1 : +1; + Uint32 n1 = *(const Uint32*)(u1.v + 8); + Uint32 n2 = *(const Uint32*)(u2.v + 8); + if (n1 < n2) + return -1; + if (n2 > n1) + return +1; + return 0; + } + } + return CmpUnknown; + } + case Type::Blob: { - // skip blob head, the rest is varchar + // skip blob head, the rest is binary const unsigned skip = NDB_BLOB_HEAD_SIZE; if (size >= skip + 1) { union { const Uint32* p; const char* v; } u1, u2; u1.p = p1 + skip; u2.p = p2 + skip; - // length in first 2 bytes - int k = strncmp(u1.v + 2, u2.v + 2, ((size - skip) << 2) - 2); + int k = memcmp(u1.v, u2.v, (size - 1) << 2); + return k < 0 ? -1 : k > 0 ? +1 : full == size ? 0 : CmpUnknown; + } + return CmpUnknown; + } + case Type::Text: + { + // skip blob head, the rest is char + const unsigned skip = NDB_BLOB_HEAD_SIZE; + if (size >= skip + 1) { + union { const Uint32* p; const char* v; } u1, u2; + u1.p = p1 + skip; + u2.p = p2 + skip; + int k = memcmp(u1.v, u2.v, (size - 1) << 2); return k < 0 ? -1 : k > 0 ? +1 : full == size ? 0 : CmpUnknown; } return CmpUnknown; diff --git a/ndb/include/util/Properties.hpp b/ndb/include/util/Properties.hpp index 2c30f7f7e3c..df8e2887001 100644 --- a/ndb/include/util/Properties.hpp +++ b/ndb/include/util/Properties.hpp @@ -55,7 +55,7 @@ public: static const char delimiter = ':'; static const char version[]; - Properties(); + Properties(bool case_insensitive= false); Properties(const Properties &); Properties(const Property *, int len); virtual ~Properties(); diff --git a/ndb/include/util/SocketAuthenticator.hpp b/ndb/include/util/SocketAuthenticator.hpp new file mode 100644 index 00000000000..1b82567feaa --- /dev/null +++ b/ndb/include/util/SocketAuthenticator.hpp @@ -0,0 +1,39 @@ +/* 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 SOCKET_AUTHENTICATOR_HPP +#define SOCKET_AUTHENTICATOR_HPP + +class SocketAuthenticator +{ +public: + virtual ~SocketAuthenticator() {}; + virtual bool client_authenticate(int sockfd) = 0; + virtual bool server_authenticate(int sockfd) = 0; +}; + +class SocketAuthSimple : public SocketAuthenticator +{ + const char *m_passwd; + const char *m_username; +public: + SocketAuthSimple(const char *username, const char *passwd); + virtual ~SocketAuthSimple(); + virtual bool client_authenticate(int sockfd); + virtual bool server_authenticate(int sockfd); +}; + +#endif // SOCKET_AUTHENTICATOR_HPP diff --git a/ndb/include/util/SocketClient.hpp b/ndb/include/util/SocketClient.hpp new file mode 100644 index 00000000000..de9a081464a --- /dev/null +++ b/ndb/include/util/SocketClient.hpp @@ -0,0 +1,38 @@ +/* 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 SOCKET_CLIENT_HPP +#define SOCKET_CLIENT_HPP + +#include <NdbTCP.h> +class SocketAuthenticator; + +class SocketClient +{ + NDB_SOCKET_TYPE m_sockfd; + struct sockaddr_in m_servaddr; + unsigned short m_port; + char *m_server_name; + SocketAuthenticator *m_auth; +public: + SocketClient(const char *server_name, unsigned short port, SocketAuthenticator *sa = 0); + ~SocketClient(); + bool init(); + NDB_SOCKET_TYPE connect(); + bool close(); +}; + +#endif // SOCKET_ClIENT_HPP diff --git a/ndb/src/common/debugger/DebuggerNames.cpp b/ndb/src/common/debugger/DebuggerNames.cpp index ebe94a6059f..2142138e435 100644 --- a/ndb/src/common/debugger/DebuggerNames.cpp +++ b/ndb/src/common/debugger/DebuggerNames.cpp @@ -29,10 +29,11 @@ static const char * localBlockNames[NO_OF_BLOCKS]; static int initSignalNames(const char * dst[], const GsnName src[], unsigned short len){ - for(int i = 0; i<=MAX_GSN; i++) + int i; + for(i = 0; i<=MAX_GSN; i++) dst[i] = 0; - for(int i = 0; i<len; i++){ + for(i = 0; i<len; i++){ unsigned short gsn = src[i].gsn; const char * name = src[i].name; @@ -54,10 +55,11 @@ int initSignalPrinters(SignalDataPrintFunction dst[], const NameFunctionPair src[], unsigned short len){ - for(int i = 0; i<=MAX_GSN; i++) + int i; + for(i = 0; i<=MAX_GSN; i++) dst[i] = 0; - for(int i = 0; i<len; i++){ + for(i = 0; i<len; i++){ unsigned short gsn = src[i].gsn; SignalDataPrintFunction fun = src[i].function; @@ -79,10 +81,11 @@ int initBlockNames(const char * dst[], const BlockName src[], unsigned len){ - for(int i = 0; i<NO_OF_BLOCKS; i++) + int i; + for(i = 0; i<NO_OF_BLOCKS; i++) dst[i] = 0; - for(unsigned i = 0; i<len; i++){ + for(i = 0; i<len; i++){ const int index = src[i].number - MIN_BLOCK_NO; if(index < 0 && index >= NO_OF_BLOCKS || dst[index] != 0){ fprintf(stderr, diff --git a/ndb/src/common/debugger/EventLogger.cpp b/ndb/src/common/debugger/EventLogger.cpp index dd957d67383..50c3b778731 100644 --- a/ndb/src/common/debugger/EventLogger.cpp +++ b/ndb/src/common/debugger/EventLogger.cpp @@ -135,7 +135,7 @@ EventLogger::defEventLogMatrixSize = sizeof(EventLogger::defEventLogMatrix)/ */ const EventLogger::EventCategoryName EventLogger::eventCategoryNames[] = { { LogLevel::llStartUp, "STARTUP" }, - { LogLevel::llStatistic, "STATISTIC" }, + { LogLevel::llStatistic, "STATISTICS" }, { LogLevel::llCheckpoint, "CHECKPOINT" }, { LogLevel::llNodeRestart, "NODERESTART" }, { LogLevel::llConnection, "CONNECTION" }, @@ -1303,14 +1303,15 @@ bool EventLogger::matchEventCategory(const char * str, LogLevel::EventCategory * cat, bool exactMatch){ + unsigned i; if(cat == 0 || str == 0) return false; char * tmp = strdup(str); - for(size_t i = 0; i<strlen(tmp); i++) + for(i = 0; i<strlen(tmp); i++) tmp[i] = toupper(tmp[i]); - for(Uint32 i = 0; i<noOfEventCategoryNames; i++){ + for(i = 0; i<noOfEventCategoryNames; i++){ if(strcmp(tmp, eventCategoryNames[i].name) == 0){ * cat = eventCategoryNames[i].category; free(tmp); @@ -1350,15 +1351,6 @@ EventLogger::EventLogger() : Logger(), m_logLevel(), m_filterLevel(15) EventLogger::~EventLogger() { - -} - -bool -EventLogger::open() -{ - char clusterLog[128]; - NdbConfig_ClusterLogFileName(clusterLog, 128); - return open(clusterLog); } bool diff --git a/ndb/src/common/debugger/SignalLoggerManager.cpp b/ndb/src/common/debugger/SignalLoggerManager.cpp index 3839a348222..d642ed09a68 100644 --- a/ndb/src/common/debugger/SignalLoggerManager.cpp +++ b/ndb/src/common/debugger/SignalLoggerManager.cpp @@ -488,31 +488,6 @@ SignalLoggerManager::printLinearSection(FILE * output, } void -SignalLoggerManager::printSegmentedSection(FILE * output, - const SignalHeader & sh, - const SegmentedSectionPtr ptr[3], - unsigned i) -{ - fprintf(output, "SECTION %u type=segmented", i); - if (i >= 3) { - fprintf(output, " *** invalid ***\n"); - return; - } - const Uint32 len = ptr[i].sz; - SectionSegment * ssp = ptr[i].p; - Uint32 pos = 0; - fprintf(output, " size=%u\n", (unsigned)len); - while (pos < len) { - if (pos > 0 && pos % SectionSegment::DataLength == 0) { - ssp = g_sectionSegmentPool.getPtr(ssp->m_nextSegment); - } - printDataWord(output, pos, ssp->theData[pos % SectionSegment::DataLength]); - } - if (len > 0) - putc('\n', output); -} - -void SignalLoggerManager::printDataWord(FILE * output, Uint32 & pos, const Uint32 data) { const char* const hex = "0123456789abcdef"; 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/LCP.cpp b/ndb/src/common/debugger/signaldata/LCP.cpp index 825659d13b3..6b4bb13e2cd 100644 --- a/ndb/src/common/debugger/signaldata/LCP.cpp +++ b/ndb/src/common/debugger/signaldata/LCP.cpp @@ -25,7 +25,8 @@ printSTART_LCP_REQ(FILE * output, const Uint32 * theData, const StartLcpReq * const sig = (StartLcpReq *) theData; - char buf1[sig->participatingDIH.TextLength+1], buf2[sig->participatingLQH.TextLength+1]; + char buf1[8*_NDB_NODE_BITMASK_SIZE+1]; + char buf2[8*_NDB_NODE_BITMASK_SIZE+1]; fprintf(output, " Sender: %d LcpId: %d\n" " ParticipatingDIH = %s\n" diff --git a/ndb/src/common/debugger/signaldata/Makefile.am b/ndb/src/common/debugger/signaldata/Makefile.am index 0d6ed45dcef..0a5806e1e00 100644 --- a/ndb/src/common/debugger/signaldata/Makefile.am +++ b/ndb/src/common/debugger/signaldata/Makefile.am @@ -22,7 +22,7 @@ libsignaldataprint_la_SOURCES = \ CopyGCI.cpp SystemError.cpp StartRec.cpp NFCompleteRep.cpp \ FailRep.cpp DisconnectRep.cpp SignalDroppedRep.cpp \ SumaImpl.cpp NdbSttor.cpp CreateFragmentation.cpp \ - UtilLock.cpp TuxMaint.cpp TupAccess.cpp AccLock.cpp \ + UtilLock.cpp TuxMaint.cpp AccLock.cpp \ LqhTrans.cpp ReadNodesConf.cpp CntrStart.cpp include $(top_srcdir)/ndb/config/common.mk.am @@ -30,3 +30,4 @@ include $(top_srcdir)/ndb/config/type_ndbapi.mk.am # Don't update the files from bitkeeper %::SCCS/s.% + diff --git a/ndb/src/common/debugger/signaldata/ScanTab.cpp b/ndb/src/common/debugger/signaldata/ScanTab.cpp index b4246059f6a..4b057171963 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; i<restLen; i++) + fprintf(output, " H\'%.8x", rest[i]); + fprintf(output, "\n"); } return false; } @@ -60,51 +74,28 @@ printSCANTABCONF(FILE * output, const Uint32 * theData, Uint32 len, Uint16 recei fprintf(output, " transId(1, 2): (H\'%.8x, H\'%.8x)\n", sig->transId1, 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, " requestInfo: Eod: %d OpCount: %d\n", + (requestInfo & ScanTabConf::EndOfData == ScanTabConf::EndOfData), + (requestInfo & (~ScanTabConf::EndOfData))); + size_t op_count= requestInfo & (~ScanTabConf::EndOfData); + if(op_count){ + fprintf(output, " Operation(s) [api tc rows len]:\n"); + ScanTabConf::OpData * op = (ScanTabConf::OpData*) + (theData + ScanTabConf::SignalLength); + for(int i = 0; i<op_count; i++){ + if(op->info != ScanTabConf::EndOfData) + fprintf(output, " [0x%x 0x%x %d %d]", + op->apiPtrI, op->tcPtrI, + ScanTabConf::getRows(op->info), + ScanTabConf::getLength(op->info)); + else + fprintf(output, " [0x%x 0x%x eod]", + op->apiPtrI, op->tcPtrI); + + op++; + } + fprintf(output, "\n"); } - fprintf(output, "\"))\n"); -#if 0 - fprintf(output, " Operation(s):\n"); - for(int i = 0; i<16; i++){ - fprintf(output, " [%.2u]ix=%d l=%.2d,", - i, sig->getIdx(sig->operLenAndIdx[i]), sig->getLen(sig->operLenAndIdx[i])); - if (((i+1) % 4) == 0) - fprintf(output, "\n"); - } -#endif - return false; -} - -bool -printSCANTABINFO(FILE * output, const Uint32 * theData, Uint32 len, Uint16 receiverBlockNo){ - - const ScanTabInfo * const sig = (ScanTabInfo *) theData; - - fprintf(output, " apiConnectPtr: H\'%.8x\n", - sig->apiConnectPtr); - - fprintf(output, " Operation(s):\n"); - for(int i = 0; i<16; i++){ - fprintf(output, " [%.2u]ix=%d l=%.2d,", - i, sig->getIdx(sig->operLenAndIdx[i]), sig->getLen(sig->operLenAndIdx[i])); - if (((i+1) % 4) == 0) - fprintf(output, "\n"); - } - return false; } @@ -120,8 +111,8 @@ printSCANTABREF(FILE * output, const Uint32 * theData, Uint32 len, Uint16 receiv sig->transId1, sig->transId2); fprintf(output, " Errorcode: %u\n", sig->errorCode); - - // fprintf(output, " sendScanNextReqWithClose: %u\n", sig->sendScanNextReqWithClose); + + fprintf(output, " closeNeeded: %u\n", sig->closeNeeded); return false; } @@ -147,13 +138,21 @@ printSCANNEXTREQ(FILE * output, const Uint32 * theData, Uint32 len, Uint16 recei if(receiverBlockNo == DBTC){ const ScanNextReq * const sig = (ScanNextReq *) theData; - fprintf(output, " aipConnectPtr: H\'%.8x\n", + fprintf(output, " apiConnectPtr: H\'%.8x\n", sig->apiConnectPtr); - fprintf(output, " transId(1, 2): (H\'%.8x, H\'%.8x)\n", + fprintf(output, " transId(1, 2): (H\'%.8x, H\'%.8x) ", sig->transId1, sig->transId2); fprintf(output, " Stop this scan: %u\n", sig->stopScan); + + const Uint32 * ops = theData + ScanNextReq::SignalLength; + if(len > ScanNextReq::SignalLength){ + fprintf(output, " tcFragPtr(s): "); + for(size_t i = ScanNextReq::SignalLength; i<len; i++) + fprintf(output, " 0x%x", * ops++); + fprintf(output, "\n"); + } } if (receiverBlockNo == DBLQH){ return printSCANFRAGNEXTREQ(output, theData, len, receiverBlockNo); diff --git a/ndb/src/common/debugger/signaldata/SignalDataPrint.cpp b/ndb/src/common/debugger/signaldata/SignalDataPrint.cpp index d49e316ad38..65351663789 100644 --- a/ndb/src/common/debugger/signaldata/SignalDataPrint.cpp +++ b/ndb/src/common/debugger/signaldata/SignalDataPrint.cpp @@ -73,7 +73,6 @@ #include <signaldata/CntrStart.hpp> #include <signaldata/ReadNodesConf.hpp> #include <signaldata/TuxMaint.hpp> -#include <signaldata/TupAccess.hpp> #include <signaldata/AccLock.hpp> bool printCONTINUEB(FILE *, const Uint32 *, Uint32, Uint16); @@ -249,14 +248,15 @@ SignalDataPrintFunctions[] = { ,{ GSN_READ_NODESCONF, printREAD_NODES_CONF } ,{ GSN_TUX_MAINT_REQ, printTUX_MAINT_REQ } - ,{ GSN_TUP_READ_ATTRS, printTUP_READ_ATTRS } - ,{ GSN_TUP_QUERY_TH, printTUP_QUERY_TH } - ,{ GSN_TUP_STORE_TH, printTUP_STORE_TH } ,{ GSN_ACC_LOCKREQ, printACC_LOCKREQ } ,{ GSN_LQH_TRANSCONF, printLQH_TRANSCONF } }; const unsigned short NO_OF_PRINT_FUNCTIONS = sizeof(SignalDataPrintFunctions)/sizeof(NameFunctionPair); - - +template class Bitmask<1>; +template class Bitmask<2>; +template class Bitmask<4>; +template struct BitmaskPOD<1>; +template struct BitmaskPOD<2>; +template struct BitmaskPOD<4>; diff --git a/ndb/src/common/debugger/signaldata/SignalNames.cpp b/ndb/src/common/debugger/signaldata/SignalNames.cpp index 377a588dbb0..9d4d5bdf6f5 100644 --- a/ndb/src/common/debugger/signaldata/SignalNames.cpp +++ b/ndb/src/common/debugger/signaldata/SignalNames.cpp @@ -32,7 +32,6 @@ const GsnName SignalNames [] = { ,{ GSN_READCONF, "READCONF" } ,{ GSN_SCAN_NEXTREQ, "SCAN_NEXTREQ" } ,{ GSN_SCAN_TABCONF, "SCAN_TABCONF" } - ,{ GSN_SCAN_TABINFO, "SCAN_TABINFO" } ,{ GSN_SCAN_TABREF, "SCAN_TABREF" } ,{ GSN_SCAN_TABREQ, "SCAN_TABREQ" } ,{ GSN_TC_COMMITCONF, "TC_COMMITCONF" } @@ -641,9 +640,6 @@ const GsnName SignalNames [] = { ,{ GSN_TUX_MAINT_REQ, "TUX_MAINT_REQ" } ,{ GSN_TUX_MAINT_CONF, "TUX_MAINT_CONF" } ,{ GSN_TUX_MAINT_REF, "TUX_MAINT_REF" } - ,{ GSN_TUP_READ_ATTRS, "TUP_READ_ATTRS" } - ,{ GSN_TUP_QUERY_TH, "TUP_QUERY_TH" } - ,{ GSN_TUP_STORE_TH, "TUP_STORE_TH" } ,{ GSN_TUX_BOUND_INFO, "TUX_BOUND_INFO" } ,{ GSN_ACC_LOCKREQ, "ACC_LOCKREQ" } diff --git a/ndb/src/common/debugger/signaldata/TupAccess.cpp b/ndb/src/common/debugger/signaldata/TupAccess.cpp deleted file mode 100644 index e94d4636cf5..00000000000 --- a/ndb/src/common/debugger/signaldata/TupAccess.cpp +++ /dev/null @@ -1,131 +0,0 @@ -/* 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 */ - -#include <signaldata/TupAccess.hpp> -#include <SignalLoggerManager.hpp> -#include <AttributeHeader.hpp> - -bool -printTUP_READ_ATTRS(FILE* output, const Uint32* theData, Uint32 len, Uint16 rbn) -{ - const TupReadAttrs* const sig = (const TupReadAttrs*)theData; - if (sig->errorCode == RNIL) - fprintf(output, " errorCode=RNIL flags=%x\n", sig->requestInfo); - else - fprintf(output, " errorCode=%u flags=%x\n", sig->errorCode, sig->requestInfo); - fprintf(output, " table: id=%u", sig->tableId); - fprintf(output, " fragment: id=%u ptr=0x%x\n", sig->fragId, sig->fragPtrI); - fprintf(output, " tuple: addr=0x%x version=%u", sig->tupAddr, sig->tupVersion); - fprintf(output, " realPage=0x%x offset=%u\n", sig->pageId, sig->pageOffset); - const Uint32* buffer = (const Uint32*)sig + TupReadAttrs::SignalLength; - Uint32 attrCount = buffer[0]; - bool readKeys = (sig->requestInfo & TupReadAttrs::ReadKeys); - if (sig->errorCode == RNIL && ! readKeys || - sig->errorCode == 0 && readKeys) { - fprintf(output, " input: attrCount=%u\n", attrCount); - for (unsigned i = 0; i < attrCount; i++) { - AttributeHeader ah(buffer[1 + i]); - fprintf(output, " %u: attrId=%u\n", i, ah.getAttributeId()); - } - } - if (sig->errorCode == 0) { - fprintf(output, " output: attrCount=%u\n", attrCount); - Uint32 pos = 1 + attrCount; - for (unsigned i = 0; i < attrCount; i++) { - AttributeHeader ah(buffer[pos++]); - fprintf(output, " %u: attrId=%u dataSize=%u\n", i, ah.getAttributeId(), ah.getDataSize()); - Uint32 next = pos + ah.getDataSize(); - Uint32 printpos = 0; - while (pos < next) { - SignalLoggerManager::printDataWord(output, printpos, buffer[pos]); - pos++; - } - if (ah.getDataSize() > 0) - fprintf(output, "\n"); - } - } - return true; -} - -bool -printTUP_QUERY_TH(FILE* output, const Uint32* theData, Uint32 len, Uint16 rbn) -{ - const TupQueryTh* const sig = (const TupQueryTh*)theData; - fprintf(output, "tableId = %u, fragId = %u ", sig->tableId, sig->fragId); - fprintf(output, "tuple: addr = 0x%x version = %u\n", sig->tupAddr, - sig->tupVersion); - fprintf(output, "transId1 = 0x%x, transId2 = 0x%x, savePointId = %u\n", - sig->transId1, sig->transId2, sig->savePointId); - return true; -} - -bool -printTUP_STORE_TH(FILE* output, const Uint32* theData, Uint32 len, Uint16 rbn) -{ - const TupStoreTh* const sig = (const TupStoreTh*)theData; - if (sig->errorCode == RNIL) - fprintf(output, " errorCode=RNIL\n"); - else - fprintf(output, " errorCode=%u\n", sig->errorCode); - fprintf(output, " table: id=%u", sig->tableId); - fprintf(output, " fragment: id=%u ptr=0x%x\n", sig->fragId, sig->fragPtrI); - fprintf(output, " tuple: addr=0x%x", sig->tupAddr); - if ((sig->tupAddr & 0x1) == 0) { - fprintf(output, " fragPage=0x%x index=%u", - sig->tupAddr >> MAX_TUPLES_BITS, - (sig->tupAddr & ((1 <<MAX_TUPLES_BITS) - 1)) >> 1); - fprintf(output, " realPage=0x%x offset=%u\n", sig->pageId, sig->pageOffset); - } else { - fprintf(output, " cacheId=%u\n", - sig->tupAddr >> 1); - } - if (sig->tupVersion != 0) { - fprintf(output, " version=%u ***invalid***\n", sig->tupVersion); - } - bool showdata = true; - switch (sig->opCode) { - case TupStoreTh::OpRead: - fprintf(output, " operation=Read\n"); - showdata = false; - break; - case TupStoreTh::OpInsert: - fprintf(output, " operation=Insert\n"); - break; - case TupStoreTh::OpUpdate: - fprintf(output, " operation=Update\n"); - break; - case TupStoreTh::OpDelete: - fprintf(output, " operation=Delete\n"); - showdata = false; - break; - default: - fprintf(output, " operation=%u ***invalid***\n", sig->opCode); - break; - } - fprintf(output, " data: offset=%u size=%u", sig->dataOffset, sig->dataSize); - if (! showdata) { - fprintf(output, " [not printed]\n"); - } else { - fprintf(output, "\n"); - const Uint32* buffer = (const Uint32*)sig + TupStoreTh::SignalLength; - Uint32 pos = 0; - while (pos < sig->dataSize) - SignalLoggerManager::printDataWord(output, pos, buffer[sig->dataOffset + pos]); - if (sig->dataSize > 0) - fprintf(output, "\n"); - } - return true; -}; diff --git a/ndb/src/common/logger/FileLogHandler.cpp b/ndb/src/common/logger/FileLogHandler.cpp index d13dd7b2a78..632db71db15 100644 --- a/ndb/src/common/logger/FileLogHandler.cpp +++ b/ndb/src/common/logger/FileLogHandler.cpp @@ -14,8 +14,8 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include <ndb_global.h> #include <FileLogHandler.hpp> - #include <File.hpp> // @@ -146,7 +146,7 @@ FileLogHandler::createNewFile() { bool rc = true; int fileNo = 1; - char newName[MAXPATHLEN]; + char newName[PATH_MAX]; do { diff --git a/ndb/src/common/logger/Logger.cpp b/ndb/src/common/logger/Logger.cpp index 9c9f1eece18..c2fdecb642b 100644 --- a/ndb/src/common/logger/Logger.cpp +++ b/ndb/src/common/logger/Logger.cpp @@ -350,3 +350,4 @@ Logger::log(LoggerLevel logLevel, const char* pMsg, va_list ap) const // PRIVATE // +template class Vector<LogHandler*>; diff --git a/ndb/src/common/mgmcommon/ConfigInfo.cpp b/ndb/src/common/mgmcommon/ConfigInfo.cpp index c2b5fdabf01..552b49727fb 100644 --- a/ndb/src/common/mgmcommon/ConfigInfo.cpp +++ b/ndb/src/common/mgmcommon/ConfigInfo.cpp @@ -14,15 +14,26 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include <NdbTCP.h> #include "ConfigInfo.hpp" #include <mgmapi_config_parameters.h> +#include <ndb_limits.h> #define MAX_LINE_LENGTH 255 #define KEY_INTERNAL 0 - +#define MAX_INT_RNIL (RNIL - 1) /**************************************************************************** * Section names ****************************************************************************/ + +const ConfigInfo::AliasPair +ConfigInfo::m_sectionNameAliases[]={ + {"API", "MYSQLD"}, + {"DB", "NDBD"}, + {"MGM", "NDB_MGMD"}, + {0, 0} +}; + const char* ConfigInfo::m_sectionNames[]={ "SYSTEM", @@ -47,24 +58,25 @@ sizeof(m_sectionNames)/sizeof(char*); /**************************************************************************** * Section Rules declarations ****************************************************************************/ -bool transformComputer(InitConfigFileParser::Context & ctx, const char *); -bool transformSystem(InitConfigFileParser::Context & ctx, const char *); -bool transformExternalSystem(InitConfigFileParser::Context & ctx, const char *); -bool transformNode(InitConfigFileParser::Context & ctx, const char *); -bool transformExtNode(InitConfigFileParser::Context & ctx, const char *); -bool transformConnection(InitConfigFileParser::Context & ctx, const char *); -bool applyDefaultValues(InitConfigFileParser::Context & ctx, const char *); -bool checkMandatory(InitConfigFileParser::Context & ctx, const char *); -bool fixPortNumber(InitConfigFileParser::Context & ctx, const char *); -bool fixShmkey(InitConfigFileParser::Context & ctx, const char *); -bool checkDbConstraints(InitConfigFileParser::Context & ctx, const char *); -bool checkConnectionConstraints(InitConfigFileParser::Context &, const char *); -bool fixNodeHostname(InitConfigFileParser::Context & ctx, const char * data); -bool fixHostname(InitConfigFileParser::Context & ctx, const char * data); -bool fixNodeId(InitConfigFileParser::Context & ctx, const char * data); -bool fixExtConnection(InitConfigFileParser::Context & ctx, const char * data); -bool fixDepricated(InitConfigFileParser::Context & ctx, const char *); -bool saveInConfigValues(InitConfigFileParser::Context & ctx, const char *); +static bool transformComputer(InitConfigFileParser::Context & ctx, const char *); +static bool transformSystem(InitConfigFileParser::Context & ctx, const char *); +static bool transformExternalSystem(InitConfigFileParser::Context & ctx, const char *); +static bool transformNode(InitConfigFileParser::Context & ctx, const char *); +static bool transformExtNode(InitConfigFileParser::Context & ctx, const char *); +static bool transformConnection(InitConfigFileParser::Context & ctx, const char *); +static bool applyDefaultValues(InitConfigFileParser::Context & ctx, const char *); +static bool checkMandatory(InitConfigFileParser::Context & ctx, const char *); +static bool fixPortNumber(InitConfigFileParser::Context & ctx, const char *); +static bool fixShmkey(InitConfigFileParser::Context & ctx, const char *); +static bool checkDbConstraints(InitConfigFileParser::Context & ctx, const char *); +static bool checkConnectionConstraints(InitConfigFileParser::Context &, const char *); +static bool checkTCPConstraints(InitConfigFileParser::Context &, const char *); +static bool fixNodeHostname(InitConfigFileParser::Context & ctx, const char * data); +static bool fixHostname(InitConfigFileParser::Context & ctx, const char * data); +static bool fixNodeId(InitConfigFileParser::Context & ctx, const char * data); +static bool fixExtConnection(InitConfigFileParser::Context & ctx, const char * data); +static bool fixDepricated(InitConfigFileParser::Context & ctx, const char *); +static bool saveInConfigValues(InitConfigFileParser::Context & ctx, const char *); const ConfigInfo::SectionRule ConfigInfo::m_SectionRules[] = { @@ -83,9 +95,6 @@ ConfigInfo::m_SectionRules[] = { { "SCI", transformConnection, 0 }, { "OSE", transformConnection, 0 }, - { "TCP", fixPortNumber, 0 }, - //{ "SHM", fixShmKey, 0 }, - { "DB", fixNodeHostname, 0 }, { "API", fixNodeHostname, 0 }, { "MGM", fixNodeHostname, 0 }, @@ -106,6 +115,10 @@ ConfigInfo::m_SectionRules[] = { { "OSE", fixHostname, "HostName1" }, { "OSE", fixHostname, "HostName2" }, + { "TCP", fixPortNumber, 0 }, // has to come after fixHostName + { "SHM", fixPortNumber, 0 }, // has to come after fixHostName + //{ "SHM", fixShmKey, 0 }, + /** * fixExtConnection must be after fixNodeId */ @@ -128,7 +141,9 @@ ConfigInfo::m_SectionRules[] = { { "SCI", checkConnectionConstraints, 0 }, { "OSE", checkConnectionConstraints, 0 }, - + { "TCP", checkTCPConstraints, "HostName1" }, + { "TCP", checkTCPConstraints, "HostName2" }, + { "*", checkMandatory, 0 }, { "DB", saveInConfigValues, 0 }, @@ -146,13 +161,21 @@ const int ConfigInfo::m_NoOfRules = sizeof(m_SectionRules)/sizeof(SectionRule); /**************************************************************************** * Config Rules declarations ****************************************************************************/ -bool addNodeConnections(Vector<ConfigInfo::ConfigRuleSection>§ions, - struct InitConfigFileParser::Context &ctx, - const char * ruleData); +static bool add_node_connections(Vector<ConfigInfo::ConfigRuleSection>§ions, + struct InitConfigFileParser::Context &ctx, + const char * rule_data); +static bool add_server_ports(Vector<ConfigInfo::ConfigRuleSection>§ions, + struct InitConfigFileParser::Context &ctx, + const char * rule_data); +static bool check_node_vs_replicas(Vector<ConfigInfo::ConfigRuleSection>§ions, + struct InitConfigFileParser::Context &ctx, + const char * rule_data); const ConfigInfo::ConfigRule ConfigInfo::m_ConfigRules[] = { - { addNodeConnections, 0 }, + { add_node_connections, 0 }, + { add_server_ports, 0 }, + { check_node_vs_replicas, 0 }, { 0, 0 } }; @@ -166,24 +189,8 @@ struct DepricationTransform { static const DepricationTransform f_deprication[] = { - { "DB", "NoOfIndexPages", "IndexMemory", 0, 8192 } - ,{ "DB", "MemorySpaceIndexes", "IndexMemory", 0, 8192 } - ,{ "DB", "NoOfDataPages", "DataMemory", 0, 8192 } - ,{ "DB", "MemorySpaceTuples", "DataMemory", 0, 8192 } - ,{ "DB", "TransactionInactiveTimeBeforeAbort", "TransactionInactiveTimeout", - 0, 1 } - ,{ "TCP", "ProcessId1", "NodeId1", 0, 1} - ,{ "TCP", "ProcessId2", "NodeId2", 0, 1} - ,{ "TCP", "SendBufferSize", "SendBufferMemory", 0, 16384 } - ,{ "TCP", "MaxReceiveSize", "ReceiveBufferMemory", 0, 16384 } - - ,{ "SHM", "ProcessId1", "NodeId1", 0, 1} - ,{ "SHM", "ProcessId2", "NodeId2", 0, 1} - ,{ "SCI", "ProcessId1", "NodeId1", 0, 1} - ,{ "SCI", "ProcessId2", "NodeId2", 0, 1} - ,{ "OSE", "ProcessId1", "NodeId1", 0, 1} - ,{ "OSE", "ProcessId2", "NodeId2", 0, 1} - ,{ 0, 0, 0, 0, 0} + { "DB", "Discless", "Diskless", 0, 1 }, + { 0, 0, 0, 0, 0} }; /** @@ -241,27 +248,14 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { KEY_INTERNAL, "HostName", "COMPUTER", - "Hostname of computer (e.g. alzato.com)", + "Hostname of computer (e.g. mysql.com)", ConfigInfo::USED, false, ConfigInfo::STRING, MANDATORY, 0, - 0x7FFFFFFF }, + MAX_INT_RNIL }, - { - CFG_NODE_BYTE_ORDER, - "ByteOrder", - "COMPUTER", - "Not yet implemented", - ConfigInfo::USED, // Actually not used, but since it is MANDATORY, - // we don't want any warning message - false, - ConfigInfo::STRING, - MANDATORY, // Big == 0, Little == 1, NotSet == 2 (?) - 0, - 1 }, - /**************************************************************************** * SYSTEM ***************************************************************************/ @@ -311,7 +305,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::INT, 0, 0, - 0x7FFFFFFF }, + MAX_INT_RNIL }, { CFG_SYS_CONFIG_GENERATION, @@ -323,7 +317,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::INT, 0, 0, - 0x7FFFFFFF }, + MAX_INT_RNIL }, /*************************************************************************** * DB @@ -350,7 +344,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::STRING, UNDEFINED, 0, - 0x7FFFFFFF }, + MAX_INT_RNIL }, { CFG_NODE_SYSTEM, @@ -362,7 +356,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::STRING, UNDEFINED, 0, - 0x7FFFFFFF }, + MAX_INT_RNIL }, { CFG_NODE_ID, @@ -377,6 +371,18 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { (MAX_NODES - 1) }, { + KEY_INTERNAL, + "ServerPort", + "DB", + "Port used to setup transporter", + ConfigInfo::USED, + false, + ConfigInfo::INT, + UNDEFINED, + 1, + 65535 }, + + { CFG_DB_NO_REPLICAS, "NoOfReplicas", "DB", @@ -386,7 +392,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::INT, MANDATORY, 1, - 2 }, + 4 }, { CFG_DB_NO_ATTRIBUTES, @@ -398,7 +404,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::INT, 1000, 32, - 4096 }, + MAX_INT_RNIL/16 }, { CFG_DB_NO_TABLES, @@ -408,9 +414,9 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::USED, false, ConfigInfo::INT, - 32, + 128, 8, - 128 }, + MAX_INT_RNIL }, { CFG_DB_NO_INDEXES, @@ -422,7 +428,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::INT, 128, 0, - 2048 }, + MAX_INT_RNIL }, { CFG_DB_NO_INDEX_OPS, @@ -434,8 +440,8 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::INT, 8192, 0, - 1000000 - }, + MAX_INT_RNIL + }, { CFG_DB_NO_TRIGGERS, @@ -447,7 +453,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::INT, 768, 0, - 2432 }, + MAX_INT_RNIL }, { CFG_DB_NO_TRIGGER_OPS, @@ -457,9 +463,9 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::USED, false, ConfigInfo::INT, - 1000, + 4000, 0, - 1000000 }, + MAX_INT_RNIL }, { KEY_INTERNAL, @@ -471,7 +477,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::STRING, MANDATORY, 0, - 0x7FFFFFFF }, + MAX_INT_RNIL }, { CFG_DB_NO_SAVE_MSGS, @@ -483,7 +489,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::INT, 25, 0, - 0x7FFFFFFF }, + MAX_INT_RNIL }, { CFG_DB_MEMLOCK, @@ -495,33 +501,9 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::BOOL, false, 0, - 0x7FFFFFFF }, - - { - KEY_INTERNAL, - "SleepWhenIdle", - "DB", - 0, - ConfigInfo::DEPRICATED, - true, - ConfigInfo::BOOL, - true, - 0, - 0x7FFFFFFF }, + MAX_INT_RNIL }, { - KEY_INTERNAL, - "NoOfSignalsToExecuteBetweenCommunicationInterfacePoll", - "DB", - 0, - ConfigInfo::DEPRICATED, - true, - ConfigInfo::INT, - 20, - 1, - 0x7FFFFFFF }, - - { CFG_DB_WATCHDOG_INTERVAL, "TimeBetweenWatchDogCheck", "DB", @@ -529,9 +511,9 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::USED, true, ConfigInfo::INT, - 4000, + 6000, 70, - 0x7FFFFFFF }, + MAX_INT_RNIL }, { CFG_DB_STOP_ON_ERROR, @@ -543,7 +525,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::BOOL, true, 0, - 0x7FFFFFFF }, + MAX_INT_RNIL }, { CFG_DB_STOP_ON_ERROR_INSERT, @@ -565,9 +547,9 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::USED, false, ConfigInfo::INT, - 8192, + 32768, 32, - 1000000 }, + MAX_INT_RNIL }, { CFG_DB_NO_TRANSACTIONS, @@ -579,7 +561,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::INT, 4096, 32, - 1000000 }, + MAX_INT_RNIL }, { CFG_DB_NO_SCANS, @@ -589,7 +571,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::USED, false, ConfigInfo::INT, - 25, + 256, 2, 500 }, @@ -601,9 +583,9 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::USED, false, ConfigInfo::INT, - 1024000, + (1024 * 1024), 1024, - 0x7FFFFFFF }, + MAX_INT_RNIL }, { CFG_DB_INDEX_MEM, @@ -613,33 +595,9 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::USED, false, ConfigInfo::INT64, - 3000 * 8192, + 3 * 1024 * 8192, 128 * 8192, - ((Uint64)192000) * ((Uint64)8192) }, - - { - KEY_INTERNAL, - "NoOfIndexPages", - "DB", - "IndexMemory", - ConfigInfo::DEPRICATED, - false, - ConfigInfo::INT, - 3000, - 128, - 192000 }, - - { - KEY_INTERNAL, - "MemorySpaceIndexes", - "DB", - "IndexMemory", - ConfigInfo::DEPRICATED, - false, - ConfigInfo::INT, - UNDEFINED, - 128, - 192000 }, + ((Uint64)MAX_INT_RNIL) * ((Uint64)8192) }, { CFG_DB_DATA_MEM, @@ -649,35 +607,11 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::USED, false, ConfigInfo::INT64, - 10000 * 8192, + 10 * 1024 * 8192, 128 * 8192, - ((Uint64)400000) * ((Uint64)8192) }, + ((Uint64)MAX_INT_RNIL) * ((Uint64)8192) }, { - KEY_INTERNAL, - "NoOfDataPages", - "DB", - "DataMemory", - ConfigInfo::DEPRICATED, - false, - ConfigInfo::INT, - 10000, - 128, - 400000 }, - - { - KEY_INTERNAL, - "MemorySpaceTuples", - "DB", - "DataMemory", - ConfigInfo::DEPRICATED, - false, - ConfigInfo::INT, - UNDEFINED, - 128, - 400000 }, - - { CFG_DB_START_PARTIAL_TIMEOUT, "StartPartialTimeout", "DB", @@ -709,23 +643,11 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::USED, true, ConfigInfo::INT, - 5*60000, + 0, 0, ~0 }, { - KEY_INTERNAL, - "TimeToWaitAlive", - "DB", - "Start{Partial/Partitioned/Failure}Time", - ConfigInfo::DEPRICATED, - true, - ConfigInfo::INT, - 25, - 2, - 4000 }, - - { CFG_DB_HEARTBEAT_INTERVAL, "HeartbeatIntervalDbDb", "DB", @@ -735,7 +657,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::INT, 1500, 10, - 0x7FFFFFFF }, + MAX_INT_RNIL }, { CFG_DB_API_HEARTBEAT_INTERVAL, @@ -747,7 +669,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::INT, 1500, 100, - 0x7FFFFFFF }, + MAX_INT_RNIL }, { CFG_DB_LCP_INTERVAL, @@ -783,7 +705,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::INT, 8, 1, - 0x7FFFFFFF }, + MAX_INT_RNIL }, { KEY_INTERNAL, @@ -808,7 +730,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::INT, 1000, 1000, - 0x7FFFFFFF }, + MAX_INT_RNIL }, { CFG_DB_TRANSACTION_INACTIVE_TIMEOUT, @@ -822,9 +744,9 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::USED, true, ConfigInfo::INT, - 3000, + MAX_INT_RNIL, 0, - 0x7FFFFFFF }, + MAX_INT_RNIL }, { CFG_DB_TRANSACTION_DEADLOCK_TIMEOUT, @@ -837,33 +759,21 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::USED, true, ConfigInfo::INT, - 3000, + 1200, 50, - 0x7FFFFFFF }, + MAX_INT_RNIL }, { KEY_INTERNAL, - "TransactionInactiveTimeBeforeAbort", - "DB", - "TransactionInactiveTimeout", - ConfigInfo::DEPRICATED, - true, - ConfigInfo::INT, - 3000, - 20, - 0x7FFFFFFF }, - - { - KEY_INTERNAL, "NoOfDiskPagesToDiskDuringRestartTUP", "DB", "?", ConfigInfo::USED, true, ConfigInfo::INT, - 50, + 40, 1, - 0x7FFFFFFF }, + MAX_INT_RNIL }, { KEY_INTERNAL, @@ -873,9 +783,9 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::USED, true, ConfigInfo::INT, - 10, + 40, 1, - 0x7FFFFFFF }, + MAX_INT_RNIL }, { KEY_INTERNAL, @@ -885,9 +795,9 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::USED, true, ConfigInfo::INT, - 25, + 20, 1, - 0x7FFFFFFF }, + MAX_INT_RNIL }, { KEY_INTERNAL, @@ -897,14 +807,14 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::USED, true, ConfigInfo::INT, - 5, + 20, 1, - 0x7FFFFFFF }, + MAX_INT_RNIL }, { CFG_DB_DISCLESS, - "Discless", + "Diskless", "DB", "Run wo/ disk", ConfigInfo::USED, @@ -913,6 +823,20 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { 0, 0, 1}, + + { + KEY_INTERNAL, + "Discless", + "DB", + "Diskless", + ConfigInfo::DEPRICATED, + true, + ConfigInfo::BOOL, + 0, + 0, + 1}, + + { CFG_DB_ARBIT_TIMEOUT, @@ -922,9 +846,9 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::USED, false, ConfigInfo::INT, - 1000, + 3000, 10, - 0x7FFFFFFF }, + MAX_INT_RNIL }, { CFG_DB_FILESYSTEM_PATH, @@ -936,7 +860,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::STRING, UNDEFINED, 0, - 0x7FFFFFFF }, + MAX_INT_RNIL }, { CFG_LOGLEVEL_STARTUP, @@ -1059,7 +983,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::INT, (2 * 1024 * 1024) + (2 * 1024 * 1024), // sum of BackupDataBufferSize and BackupLogBufferSize 0, - 0x7FFFFFFF }, + MAX_INT_RNIL }, { CFG_DB_BACKUP_DATA_BUFFER_MEM, @@ -1071,7 +995,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::INT, (2 * 1024 * 1024), // remember to change BackupMemory 0, - 0x7FFFFFFF }, + MAX_INT_RNIL }, { CFG_DB_BACKUP_LOG_BUFFER_MEM, @@ -1083,7 +1007,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::INT, (2 * 1024 * 1024), // remember to change BackupMemory 0, - 0x7FFFFFFF }, + MAX_INT_RNIL }, { CFG_DB_BACKUP_WRITE_SIZE, @@ -1095,7 +1019,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::INT, 32768, 0, - 0x7FFFFFFF }, + MAX_INT_RNIL }, /*************************************************************************** * REP @@ -1122,7 +1046,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::STRING, UNDEFINED, 0, - 0x7FFFFFFF }, + MAX_INT_RNIL }, { CFG_NODE_SYSTEM, @@ -1134,7 +1058,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::STRING, UNDEFINED, 0, - 0x7FFFFFFF }, + MAX_INT_RNIL }, { CFG_NODE_ID, @@ -1158,7 +1082,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::STRING, MANDATORY, 0, - 0x7FFFFFFF }, + MAX_INT_RNIL }, { CFG_REP_HEARTBEAT_INTERVAL, @@ -1170,7 +1094,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::INT, 3000, 100, - 0x7FFFFFFF }, + MAX_INT_RNIL }, /*************************************************************************** * API @@ -1197,7 +1121,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::STRING, UNDEFINED, 0, - 0x7FFFFFFF }, + MAX_INT_RNIL }, { CFG_NODE_SYSTEM, @@ -1209,7 +1133,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::STRING, UNDEFINED, 0, - 0x7FFFFFFF }, + MAX_INT_RNIL }, { CFG_NODE_ID, @@ -1231,9 +1155,9 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::USED, false, ConfigInfo::STRING, - MANDATORY, 0, - 0x7FFFFFFF }, + 0, + MAX_INT_RNIL }, { CFG_NODE_ARBIT_RANK, @@ -1243,7 +1167,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::USED, false, ConfigInfo::INT, - 2, + 0, 0, 2 }, @@ -1257,7 +1181,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::INT, 0, 0, - 0x7FFFFFFF }, + MAX_INT_RNIL }, /**************************************************************************** * MGM @@ -1284,7 +1208,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::STRING, UNDEFINED, 0, - 0x7FFFFFFF }, + MAX_INT_RNIL }, { CFG_NODE_SYSTEM, @@ -1296,7 +1220,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::STRING, UNDEFINED, 0, - 0x7FFFFFFF }, + MAX_INT_RNIL }, { CFG_NODE_ID, @@ -1320,7 +1244,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::STRING, 0, 0, - 0x7FFFFFFF }, + MAX_INT_RNIL }, { KEY_INTERNAL, @@ -1330,9 +1254,9 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::USED, false, ConfigInfo::STRING, - MANDATORY, 0, - 0x7FFFFFFF }, + 0, + MAX_INT_RNIL }, { KEY_INTERNAL, @@ -1344,7 +1268,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::INT, 100, 0, - 0x7FFFFFFF }, + MAX_INT_RNIL }, { CFG_MGM_PORT, @@ -1354,9 +1278,9 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::USED, false, ConfigInfo::INT, - 2200, + NDB_BASE_PORT, 0, - 0x7FFFFFFF }, + MAX_INT_RNIL }, { KEY_INTERNAL, @@ -1368,7 +1292,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::INT, 2199, 0, - 0x7FFFFFFF }, + MAX_INT_RNIL }, { CFG_NODE_ARBIT_RANK, @@ -1378,7 +1302,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::USED, false, ConfigInfo::INT, - 2, + 1, 0, 2 }, @@ -1392,7 +1316,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::INT, 0, 0, - 0x7FFFFFFF }, + MAX_INT_RNIL }, /**************************************************************************** * TCP @@ -1419,7 +1343,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::STRING, UNDEFINED, 0, - 0x7FFFFFFF }, + MAX_INT_RNIL }, { CFG_TCP_HOSTNAME_2, @@ -1431,7 +1355,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::STRING, UNDEFINED, 0, - 0x7FFFFFFF }, + MAX_INT_RNIL }, { CFG_CONNECTION_NODE_1, @@ -1443,19 +1367,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::STRING, MANDATORY, 0, - 0x7FFFFFFF }, - - { - KEY_INTERNAL, - "ProcessId1", - "TCP", - "NodeId1", - ConfigInfo::DEPRICATED, - false, - ConfigInfo::INT, - UNDEFINED, - 0, - 0x7FFFFFFF }, + MAX_INT_RNIL }, { CFG_CONNECTION_NODE_2, @@ -1467,43 +1379,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::STRING, MANDATORY, 0, - 0x7FFFFFFF }, - - { - KEY_INTERNAL, - "ProcessId2", - "TCP", - "NodeId2", - ConfigInfo::DEPRICATED, - false, - ConfigInfo::INT, - UNDEFINED, - 0, - 0x7FFFFFFF }, - - { - KEY_INTERNAL, - "IpAddress1", - "TCP", - "HostName1", - ConfigInfo::DEPRICATED, - false, - ConfigInfo::STRING, - UNDEFINED, - 0, - 0x7FFFFFFF }, - - { - KEY_INTERNAL, - "IpAddress2", - "TCP", - "HostName2", - ConfigInfo::DEPRICATED, - false, - ConfigInfo::STRING, - UNDEFINED, - 0, - 0 }, + MAX_INT_RNIL }, { CFG_CONNECTION_SEND_SIGNAL_ID, @@ -1515,7 +1391,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::BOOL, true, 0, - 0x7FFFFFFF }, + MAX_INT_RNIL }, { @@ -1528,19 +1404,19 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::BOOL, false, 0, - 0x7FFFFFFF }, + MAX_INT_RNIL }, { - CFG_TCP_SERVER_PORT, + CFG_CONNECTION_SERVER_PORT, "PortNumber", "TCP", "Port used for this transporter", ConfigInfo::USED, false, ConfigInfo::INT, - 2202, + MANDATORY, 0, - 0x7FFFFFFF }, + MAX_INT_RNIL }, { CFG_TCP_SEND_BUFFER_SIZE, @@ -1552,21 +1428,9 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::INT, 16 * 16384, 1 * 16384, - 0x7FFFFFFF }, + MAX_INT_RNIL }, { - KEY_INTERNAL, - "SendBufferSize", - "TCP", - "SendBufferMemory", - ConfigInfo::DEPRICATED, - false, - ConfigInfo::INT, - 16, - 1, - 0x7FFFFFFF }, - - { CFG_TCP_RECEIVE_BUFFER_SIZE, "ReceiveBufferMemory", "TCP", @@ -1576,19 +1440,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::INT, 4 * 16384, 1 * 16384, - 0x7FFFFFFF }, - - { - KEY_INTERNAL, - "MaxReceiveSize", - "TCP", - "ReceiveBufferMemory", - ConfigInfo::DEPRICATED, - false, - ConfigInfo::INT, - 4, - 1, - 0x7FFFFFFF }, + MAX_INT_RNIL }, { CFG_TCP_PROXY, @@ -1603,19 +1455,6 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { 0 }, { - KEY_INTERNAL, - "Compression", - "TCP", - 0, - ConfigInfo::DEPRICATED, - false, - ConfigInfo::BOOL, - false, - 0, - 0x7FFFFFFF }, - - - { CFG_CONNECTION_NODE_1_SYSTEM, "NodeId1_System", "TCP", @@ -1625,7 +1464,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::STRING, UNDEFINED, 0, - 0x7FFFFFFF }, + MAX_INT_RNIL }, { CFG_CONNECTION_NODE_2_SYSTEM, @@ -1637,7 +1476,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::STRING, UNDEFINED, 0, - 0x7FFFFFFF }, + MAX_INT_RNIL }, /**************************************************************************** @@ -1665,20 +1504,20 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::STRING, MANDATORY, 0, - 0x7FFFFFFF }, + MAX_INT_RNIL }, { - KEY_INTERNAL, - "ProcessId1", + CFG_CONNECTION_SERVER_PORT, + "PortNumber", "SHM", - "NodeId1", - ConfigInfo::DEPRICATED, + "Port used for this transporter", + ConfigInfo::USED, false, - ConfigInfo::STRING, - UNDEFINED, + ConfigInfo::INT, + MANDATORY, 0, - 0x7FFFFFFF }, - + MAX_INT_RNIL }, + { CFG_CONNECTION_NODE_2, "NodeId2", @@ -1689,19 +1528,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::STRING, MANDATORY, 0, - 0x7FFFFFFF }, - - { - KEY_INTERNAL, - "ProcessId2", - "SHM", - "NodeId1", - ConfigInfo::DEPRICATED, - false, - ConfigInfo::STRING, - UNDEFINED, - 0, - 0x7FFFFFFF }, + MAX_INT_RNIL }, { CFG_CONNECTION_SEND_SIGNAL_ID, @@ -1713,7 +1540,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::BOOL, false, 0, - 0x7FFFFFFF }, + MAX_INT_RNIL }, { @@ -1726,7 +1553,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::BOOL, true, 0, - 0x7FFFFFFF }, + MAX_INT_RNIL }, { CFG_SHM_KEY, @@ -1738,7 +1565,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::INT, MANDATORY, 0, - 0x7FFFFFFF }, + MAX_INT_RNIL }, { CFG_SHM_BUFFER_MEM, @@ -1750,21 +1577,9 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::INT, 1048576, 4096, - 0x7FFFFFFF }, + MAX_INT_RNIL }, { - KEY_INTERNAL, - "Compression", - "SHM", - 0, - ConfigInfo::DEPRICATED, - false, - ConfigInfo::BOOL, - false, - 0, - 0x7FFFFFFF }, - - { CFG_CONNECTION_NODE_1_SYSTEM, "NodeId1_System", "SHM", @@ -1774,7 +1589,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::STRING, UNDEFINED, 0, - 0x7FFFFFFF }, + MAX_INT_RNIL }, { CFG_CONNECTION_NODE_2_SYSTEM, @@ -1786,7 +1601,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::STRING, UNDEFINED, 0, - 0x7FFFFFFF }, + MAX_INT_RNIL }, /**************************************************************************** * SCI @@ -1813,19 +1628,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::INT, MANDATORY, 0, - 0x7FFFFFFF }, - - { - KEY_INTERNAL, - "ProcessId1", - "SCI", - "NodeId1", - ConfigInfo::DEPRICATED, - false, - ConfigInfo::INT, - UNDEFINED, - 0, - 0x7FFFFFFF }, + MAX_INT_RNIL }, { CFG_CONNECTION_NODE_2, @@ -1837,19 +1640,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::INT, MANDATORY, 0, - 0x7FFFFFFF }, - - { - KEY_INTERNAL, - "ProcessId2", - "SCI", - "NodeId2", - ConfigInfo::DEPRICATED, - false, - ConfigInfo::INT, - UNDEFINED, - 0, - 0x7FFFFFFF }, + MAX_INT_RNIL }, { CFG_SCI_ID_0, @@ -1861,7 +1652,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::INT, MANDATORY, 0, - 0x7FFFFFFF }, + MAX_INT_RNIL }, { CFG_SCI_ID_1, @@ -1873,7 +1664,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::INT, MANDATORY, 0, - 0x7FFFFFFF }, + MAX_INT_RNIL }, { CFG_CONNECTION_SEND_SIGNAL_ID, @@ -1885,7 +1676,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::BOOL, true, 0, - 0x7FFFFFFF }, + MAX_INT_RNIL }, { CFG_CONNECTION_CHECKSUM, @@ -1897,7 +1688,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::BOOL, false, 0, - 0x7FFFFFFF }, + MAX_INT_RNIL }, { CFG_SCI_SEND_LIMIT, @@ -1909,7 +1700,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::INT, 2048, 512, - 0x7FFFFFFF }, + MAX_INT_RNIL }, { CFG_SCI_BUFFER_MEM, @@ -1921,67 +1712,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::INT, 1048576, 262144, - 0x7FFFFFFF }, - - { - KEY_INTERNAL, - "Node1_NoOfAdapters", - "SCI", - 0, - ConfigInfo::DEPRICATED, - false, - ConfigInfo::INT, - UNDEFINED, - 0, - 0x7FFFFFFF }, - - { - KEY_INTERNAL, - "Node2_NoOfAdapters", - "SCI", - 0, - ConfigInfo::DEPRICATED, - false, - ConfigInfo::INT, - UNDEFINED, - 0, - 0x7FFFFFFF }, - - { - KEY_INTERNAL, - "Node1_Adapter", - "SCI", - 0, - ConfigInfo::DEPRICATED, - false, - ConfigInfo::INT, - UNDEFINED, - 0, - 0x7FFFFFFF }, - - { - KEY_INTERNAL, - "Node2_Adapter", - "SCI", - 0, - ConfigInfo::DEPRICATED, - false, - ConfigInfo::INT, - UNDEFINED, - 0, - 0x7FFFFFFF }, - - { - KEY_INTERNAL, - "Compression", - "SCI", - 0, - ConfigInfo::DEPRICATED, - false, - ConfigInfo::BOOL, - false, - 0, - 0x7FFFFFFF }, + MAX_INT_RNIL }, { CFG_CONNECTION_NODE_1_SYSTEM, @@ -1993,7 +1724,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::STRING, UNDEFINED, 0, - 0x7FFFFFFF }, + MAX_INT_RNIL }, { CFG_CONNECTION_NODE_2_SYSTEM, @@ -2005,7 +1736,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::STRING, UNDEFINED, 0, - 0x7FFFFFFF }, + MAX_INT_RNIL }, /**************************************************************************** * OSE @@ -2032,7 +1763,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::STRING, UNDEFINED, 0, - 0x7FFFFFFF }, + MAX_INT_RNIL }, { CFG_OSE_HOSTNAME_2, @@ -2044,7 +1775,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::STRING, UNDEFINED, 0, - 0x7FFFFFFF }, + MAX_INT_RNIL }, { CFG_CONNECTION_NODE_1, @@ -2056,19 +1787,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::INT, MANDATORY, 0, - 0x7FFFFFFF }, - - { - KEY_INTERNAL, - "ProcessId1", - "OSE", - "NodeId1", - ConfigInfo::DEPRICATED, - false, - ConfigInfo::INT, - UNDEFINED, - 0, - 0x7FFFFFFF }, + MAX_INT_RNIL }, { CFG_CONNECTION_NODE_2, @@ -2080,19 +1799,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::INT, UNDEFINED, 0, - 0x7FFFFFFF }, - - { - KEY_INTERNAL, - "ProcessId2", - "OSE", - "NodeId2", - ConfigInfo::DEPRICATED, - false, - ConfigInfo::INT, - MANDATORY, - 0, - 0x7FFFFFFF }, + MAX_INT_RNIL }, { CFG_CONNECTION_SEND_SIGNAL_ID, @@ -2104,7 +1811,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::BOOL, true, 0, - 0x7FFFFFFF }, + MAX_INT_RNIL }, { CFG_CONNECTION_CHECKSUM, @@ -2116,7 +1823,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::BOOL, false, 0, - 0x7FFFFFFF }, + MAX_INT_RNIL }, { CFG_OSE_PRIO_A_SIZE, @@ -2128,7 +1835,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::INT, 1000, 0, - 0x7FFFFFFF }, + MAX_INT_RNIL }, { CFG_OSE_PRIO_B_SIZE, @@ -2140,7 +1847,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::INT, 1000, 0, - 0x7FFFFFFF }, + MAX_INT_RNIL }, { CFG_OSE_RECEIVE_ARRAY_SIZE, @@ -2152,19 +1859,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::INT, 10, 0, - 0x7FFFFFFF }, - - { - KEY_INTERNAL, - "Compression", - "OSE", - 0, - ConfigInfo::DEPRICATED, - false, - ConfigInfo::BOOL, - false, - 0, - 0x7FFFFFFF }, + MAX_INT_RNIL }, { CFG_CONNECTION_NODE_1_SYSTEM, @@ -2176,7 +1871,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::STRING, UNDEFINED, 0, - 0x7FFFFFFF }, + MAX_INT_RNIL}, { CFG_CONNECTION_NODE_2_SYSTEM, @@ -2188,7 +1883,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::STRING, UNDEFINED, 0, - 0x7FFFFFFF }, + MAX_INT_RNIL }, }; const int ConfigInfo::m_NoOfParams = sizeof(m_ParamInfo) / sizeof(ParamInfo); @@ -2197,22 +1892,21 @@ const int ConfigInfo::m_NoOfParams = sizeof(m_ParamInfo) / sizeof(ParamInfo); /**************************************************************************** * Ctor ****************************************************************************/ -inline void require(bool v) { if(!v) abort();} +static void require(bool v) { if(!v) abort();} -ConfigInfo::ConfigInfo() { +ConfigInfo::ConfigInfo() + : m_info(true), m_systemDefaults(true) +{ + int i; Properties *section; const Properties *oldpinfo; - m_info.setCaseInsensitiveNames(true); - m_systemDefaults.setCaseInsensitiveNames(true); - - for (int i=0; i<m_NoOfParams; i++) { + for (i=0; i<m_NoOfParams; i++) { const ParamInfo & param = m_ParamInfo[i]; // Create new section if it did not exist if (!m_info.getCopy(param._section, §ion)) { - Properties newsection; - newsection.setCaseInsensitiveNames(true); + Properties newsection(true); m_info.put(param._section, &newsection); } @@ -2220,7 +1914,7 @@ ConfigInfo::ConfigInfo() { m_info.getCopy(param._section, §ion); // Create pinfo (parameter info) entry - Properties pinfo; + Properties pinfo(true); pinfo.put("Id", param._paramId); pinfo.put("Fname", param._fname); pinfo.put("Description", param._description); @@ -2248,8 +1942,7 @@ ConfigInfo::ConfigInfo() { if(param._type != ConfigInfo::SECTION){ Properties * p; if(!m_systemDefaults.getCopy(param._section, &p)){ - p = new Properties(); - p->setCaseInsensitiveNames(true); + p = new Properties(true); } if(param._type != STRING && param._default != UNDEFINED && @@ -2261,7 +1954,7 @@ ConfigInfo::ConfigInfo() { } } - for (int i=0; i<m_NoOfParams; i++) { + for (i=0; i<m_NoOfParams; i++) { if(m_ParamInfo[i]._section == NULL){ ndbout << "Check that each entry has a section failed." << endl; ndbout << "Parameter \"" << m_ParamInfo[i]._fname << endl; @@ -2376,6 +2069,14 @@ ConfigInfo::isSection(const char * section) const { return false; } +const char* +ConfigInfo::getAlias(const char * section) const { + for (int i = 0; m_sectionNameAliases[i].name != 0; i++) + if(!strcmp(section, m_sectionNameAliases[i].alias)) + return m_sectionNameAliases[i].name; + return 0; +} + bool ConfigInfo::verify(const Properties * section, const char* fname, Uint64 value) const { @@ -2489,11 +2190,27 @@ transformNode(InitConfigFileParser::Context & ctx, const char * data){ Uint32 id; if(!ctx.m_currentSection->get("Id", &id)){ + Uint32 nextNodeId= 1; + ctx.m_userProperties.get("NextNodeId", &nextNodeId); + id= nextNodeId; + while (ctx.m_userProperties.get("AllocatedNodeId_", id, &id)) + id++; + ctx.m_userProperties.put("NextNodeId", id+1, true); + ctx.m_currentSection->put("Id", id); +#if 0 ctx.reportError("Mandatory parameter Id missing from section " "[%s] starting at line: %d", ctx.fname, ctx.m_sectionLineno); return false; +#endif + } else if(ctx.m_userProperties.get("AllocatedNodeId_", id, &id)) { + ctx.reportError("Duplicate Id in section " + "[%s] starting at line: %d", + ctx.fname, ctx.m_sectionLineno); + return false; } + + ctx.m_userProperties.put("AllocatedNodeId_", id, id); snprintf(ctx.pname, sizeof(ctx.pname), "Node_%d", id); ctx.m_currentSection->put("Type", ctx.fname); @@ -2502,6 +2219,13 @@ transformNode(InitConfigFileParser::Context & ctx, const char * data){ ctx.m_userProperties.get("NoOfNodes", &nodes); ctx.m_userProperties.put("NoOfNodes", ++nodes, true); + /** + * Update count (per type) + */ + nodes = 0; + ctx.m_userProperties.get(ctx.fname, &nodes); + ctx.m_userProperties.put(ctx.fname, ++nodes, true); + return true; } @@ -2510,10 +2234,16 @@ fixNodeHostname(InitConfigFileParser::Context & ctx, const char * data){ const char * compId; if(!ctx.m_currentSection->get("ExecuteOnComputer", &compId)){ - ctx.reportError("Parameter \"ExecuteOnComputer\" missing from section " - "[%s] starting at line: %d", - ctx.fname, ctx.m_sectionLineno); - return false; + require(ctx.m_currentSection->put("HostName", "")); + + const char * type; + if(ctx.m_currentSection->get("Type", &type) && strcmp(type,"DB") == 0) { + ctx.reportError("Parameter \"ExecuteOnComputer\" missing from DB section" + " [%s] starting at line: %d", + ctx.fname, ctx.m_sectionLineno); + return false; + } + return true; } const Properties * computer; @@ -2598,6 +2328,9 @@ transformSystem(InitConfigFileParser::Context & ctx, const char * data){ ctx.fname, ctx.m_sectionLineno); return false; } + + ndbout << "transformSystem " << name << endl; + snprintf(ctx.pname, sizeof(ctx.pname), "SYSTEM_%s", name); return true; @@ -2638,6 +2371,22 @@ transformComputer(InitConfigFileParser::Context & ctx, const char * data){ ctx.m_userProperties.get("NoOfComputers", &computers); ctx.m_userProperties.put("NoOfComputers", ++computers, true); + const char * hostname = 0; + ctx.m_currentSection->get("HostName", &hostname); + if(!hostname){ + return true; + } + + if(!strcmp(hostname, "localhost") || !strcmp(hostname, "127.0.0.1")){ + if(ctx.m_userProperties.get("$computer-localhost", &hostname)){ + ctx.reportError("Mixing of localhost with other hostname(%s) is illegal", + hostname); + return false; + } + } else { + ctx.m_userProperties.put("$computer-localhost", hostname); + } + return true; } @@ -2725,7 +2474,7 @@ checkMandatory(InitConfigFileParser::Context & ctx, const char * data){ * Transform a string "NodeidX" (e.g. "uppsala.32") * into a Uint32 "NodeIdX" (e.g. 32) and a string "SystemX" (e.g. "uppsala"). */ -bool fixNodeId(InitConfigFileParser::Context & ctx, const char * data) +static bool fixNodeId(InitConfigFileParser::Context & ctx, const char * data) { char buf[] = "NodeIdX"; buf[6] = data[sizeof("NodeI")]; char sysbuf[] = "SystemX"; sysbuf[6] = data[sizeof("NodeI")]; @@ -2761,7 +2510,7 @@ bool fixNodeId(InitConfigFileParser::Context & ctx, const char * data) * - name of external system in parameter extSystemName, and * - nodeId of external node in parameter extSystemNodeId. */ -bool +static bool isExtConnection(InitConfigFileParser::Context & ctx, const char **extSystemName, Uint32 * extSystemNodeId){ @@ -2789,7 +2538,7 @@ isExtConnection(InitConfigFileParser::Context & ctx, * If connection is to an external system, then move connection into * external system configuration (i.e. a sub-property). */ -bool +static bool fixExtConnection(InitConfigFileParser::Context & ctx, const char * data){ const char * extSystemName; @@ -2844,7 +2593,7 @@ fixExtConnection(InitConfigFileParser::Context & ctx, const char * data){ * -# Via Node's ExecuteOnComputer lookup Hostname * -# Add HostName to Connection */ -bool +static bool fixHostname(InitConfigFileParser::Context & ctx, const char * data){ char buf[] = "NodeIdX"; buf[6] = data[sizeof("HostNam")]; @@ -2867,28 +2616,61 @@ fixHostname(InitConfigFileParser::Context & ctx, const char * data){ /** * Connection rule: Fix port number (using a port number adder) */ -bool +static bool fixPortNumber(InitConfigFileParser::Context & ctx, const char * data){ - if(!ctx.m_currentSection->contains("PortNumber")){ - Uint32 adder = 0; - ctx.m_userProperties.get("PortNumberAdder", &adder); - Uint32 base = 0; - if(!(ctx.m_userDefaults && ctx.m_userDefaults->get("PortNumber", &base)) && - !ctx.m_systemDefaults->get("PortNumber", &base)){ - return false; + Uint32 id1= 0, id2= 0; + require(ctx.m_currentSection->get("NodeId1", &id1)); + require(ctx.m_currentSection->get("NodeId2", &id2)); + id1 = id1 < id2 ? id1 : id2; + + const Properties * node; + require(ctx.m_config->get("Node", id1, &node)); + BaseString hostname; + require(node->get("HostName", hostname)); + + if (hostname.c_str()[0] == 0) { + ctx.reportError("Hostname required on nodeid %d since it will act as server.", id1); + return false; + } + + Uint32 port= 0; + if (!node->get("ServerPort", &port) && !ctx.m_userProperties.get("ServerPort_", id1, &port)) { + Uint32 adder= 0; + { + BaseString server_port_adder(hostname); + server_port_adder.append("_ServerPortAdder"); + ctx.m_userProperties.get(server_port_adder.c_str(), &adder); + ctx.m_userProperties.put(server_port_adder.c_str(), adder+1, true); + } + + Uint32 base= 0; + if (!ctx.m_userProperties.get("ServerPortBase", &base)){ + if(!(ctx.m_userDefaults && ctx.m_userDefaults->get("PortNumber", &base)) && + !ctx.m_systemDefaults->get("PortNumber", &base)) { + base= NDB_BASE_PORT+2; + // ctx.reportError("Cannot retrieve base port number"); + // return false; + } + ctx.m_userProperties.put("ServerPortBase", base); } - ctx.m_currentSection->put("PortNumber", base + adder); - adder++; - ctx.m_userProperties.put("PortNumberAdder", adder, true); + port= base + adder; + ctx.m_userProperties.put("ServerPort_", id1, port); } + + if(ctx.m_currentSection->contains("PortNumber")) { + ndbout << "PortNumber should no longer be specificied per connection, please remove from config. Will be changed to " << port << endl; + ctx.m_currentSection->put("PortNumber", port, true); + } else + ctx.m_currentSection->put("PortNumber", port); + return true; } /** * DB Node rule: Check various constraints */ -bool +static bool checkDbConstraints(InitConfigFileParser::Context & ctx, const char *){ Uint32 t1 = 0, t2 = 0; @@ -2921,7 +2703,7 @@ checkDbConstraints(InitConfigFileParser::Context & ctx, const char *){ /** * Connection rule: Check varius constraints */ -bool +static bool checkConnectionConstraints(InitConfigFileParser::Context & ctx, const char *){ Uint32 id1 = 0, id2 = 0; @@ -2977,6 +2759,22 @@ checkConnectionConstraints(InitConfigFileParser::Context & ctx, const char *){ ctx.fname, ctx.m_sectionLineno); return false; } + + return true; +} + +static bool +checkTCPConstraints(InitConfigFileParser::Context & ctx, const char * data){ + + const char * host; + struct in_addr addr; + if(ctx.m_currentSection->get(data, &host) && strlen(host) && + Ndb_getInAddr(&addr, host)){ + ctx.reportError("Unable to lookup/illegal hostname %s" + " - [%s] starting at line: %d", + host, ctx.fname, ctx.m_sectionLineno); + return false; + } return true; } @@ -3000,7 +2798,8 @@ transform(InitConfigFileParser::Context & ctx, require(ctx.m_currentSection->getTypeOf(oldName, &oldType)); ConfigInfo::Type newType = ctx.m_info->getType(ctx.m_currentInfo, newName); if(!((oldType == PropertiesType_Uint32 || oldType == PropertiesType_Uint64) - && (newType == ConfigInfo::INT || newType == ConfigInfo::INT64))){ + && (newType == ConfigInfo::INT || newType == ConfigInfo::INT64 || newType == ConfigInfo::BOOL))){ + ndbout << "oldType: " << (int)oldType << ", newType: " << (int)newType << endl; ctx.reportError("Unable to handle type conversion w.r.t deprication %s %s" "- [%s] starting at line: %d", oldName, newName, @@ -3019,23 +2818,24 @@ transform(InitConfigFileParser::Context & ctx, return false; } - if(newType == ConfigInfo::INT){ + if(newType == ConfigInfo::INT || newType == ConfigInfo::BOOL){ require(dst.put(newName, (Uint32)newVal)); - } else { + } else if(newType == ConfigInfo::INT64) { require(dst.put64(newName, newVal)); } return true; } -bool +static bool fixDepricated(InitConfigFileParser::Context & ctx, const char * data){ + const char * name; /** * Transform old values to new values * Transform new values to old values (backward compatible) */ - Properties tmp; + Properties tmp(true); Properties::Iterator it(ctx.m_currentSection); - for (const char* name = it.first(); name != NULL; name = it.next()) { + for (name = it.first(); name != NULL; name = it.next()) { const DepricationTransform * p = &f_deprication[0]; while(p->m_section != 0){ if(strcmp(p->m_section, ctx.fname) == 0){ @@ -3056,7 +2856,7 @@ fixDepricated(InitConfigFileParser::Context & ctx, const char * data){ } Properties::Iterator it2(&tmp); - for (const char* name = it2.first(); name != NULL; name = it2.next()) { + for (name = it2.first(); name != NULL; name = it2.next()) { PropertiesType type; require(tmp.getTypeOf(name, &type)); switch(type){ @@ -3086,7 +2886,7 @@ fixDepricated(InitConfigFileParser::Context & ctx, const char * data){ return true; } -bool +static bool saveInConfigValues(InitConfigFileParser::Context & ctx, const char * data){ const Properties * sec; if(!ctx.m_currentInfo->get(ctx.fname, &sec)){ @@ -3151,22 +2951,24 @@ saveInConfigValues(InitConfigFileParser::Context & ctx, const char * data){ default: abort(); } + require(ok); } ctx.m_configValues.closeSection(); } while(0); return true; } -bool -addNodeConnections(Vector<ConfigInfo::ConfigRuleSection>§ions, +static bool +add_node_connections(Vector<ConfigInfo::ConfigRuleSection>§ions, struct InitConfigFileParser::Context &ctx, - const char * ruleData) + const char * rule_data) { + Uint32 i; Properties * props= ctx.m_config; - Properties p_connections; - Properties p_connections2; + Properties p_connections(true); + Properties p_connections2(true); - for (Uint32 i = 0;; i++){ + for (i = 0;; i++){ const Properties * tmp; Uint32 nodeId1, nodeId2; @@ -3184,11 +2986,11 @@ addNodeConnections(Vector<ConfigInfo::ConfigRuleSection>§ions, Uint32 nNodes; ctx.m_userProperties.get("NoOfNodes", &nNodes); - Properties p_db_nodes; - Properties p_api_mgm_nodes; + Properties p_db_nodes(true); + Properties p_api_mgm_nodes(true); - Uint32 i_db= 0, i_api_mgm= 0; - for (Uint32 i= 0, n= 0; n < nNodes; i++){ + Uint32 i_db= 0, i_api_mgm= 0, n; + for (i= 0, n= 0; n < nNodes; i++){ const Properties * tmp; if(!props->get("Node", i, &tmp)) continue; n++; @@ -3205,13 +3007,13 @@ addNodeConnections(Vector<ConfigInfo::ConfigRuleSection>§ions, Uint32 nodeId1, nodeId2, dummy; - for (Uint32 i= 0; p_db_nodes.get("", i, &nodeId1); i++){ + for (i= 0; p_db_nodes.get("", i, &nodeId1); i++){ for (Uint32 j= i+1;; j++){ if(!p_db_nodes.get("", j, &nodeId2)) break; if(!p_connections2.get("", nodeId1+nodeId2<<16, &dummy)) { ConfigInfo::ConfigRuleSection s; s.m_sectionType= BaseString("TCP"); - s.m_sectionData= new Properties; + s.m_sectionData= new Properties(true); char buf[16]; snprintf(buf, sizeof(buf), "%u", nodeId1); s.m_sectionData->put("NodeId1", buf); @@ -3222,13 +3024,13 @@ addNodeConnections(Vector<ConfigInfo::ConfigRuleSection>§ions, } } - for (Uint32 i= 0; p_api_mgm_nodes.get("", i, &nodeId1); i++){ + for (i= 0; p_api_mgm_nodes.get("", i, &nodeId1); i++){ if(!p_connections.get("", nodeId1, &dummy)) { for (Uint32 j= 0;; j++){ if(!p_db_nodes.get("", j, &nodeId2)) break; ConfigInfo::ConfigRuleSection s; s.m_sectionType= BaseString("TCP"); - s.m_sectionData= new Properties; + s.m_sectionData= new Properties(true); char buf[16]; snprintf(buf, sizeof(buf), "%u", nodeId1); s.m_sectionData->put("NodeId1", buf); @@ -3241,3 +3043,63 @@ addNodeConnections(Vector<ConfigInfo::ConfigRuleSection>§ions, return true; } + + +static bool add_server_ports(Vector<ConfigInfo::ConfigRuleSection>§ions, + struct InitConfigFileParser::Context &ctx, + const char * rule_data) +{ +#if 0 + Properties * props= ctx.m_config; + Properties computers(true); + Uint32 port_base = NDB_BASE_PORT+2; + + Uint32 nNodes; + ctx.m_userProperties.get("NoOfNodes", &nNodes); + + for (Uint32 i= 0, n= 0; n < nNodes; i++){ + Properties * tmp; + if(!props->get("Node", i, &tmp)) continue; + n++; + + const char * type; + if(!tmp->get("Type", &type)) continue; + + Uint32 port; + if (tmp->get("ServerPort", &port)) continue; + + Uint32 computer; + if (!tmp->get("ExecuteOnComputer", &computer)) continue; + + Uint32 adder= 0; + computers.get("",computer, &adder); + + if (strcmp(type,"DB") == 0) { + adder++; + tmp->put("ServerPort", port_base+adder); + computers.put("",computer, adder); + } + } +#endif + return true; +} + +static bool +check_node_vs_replicas(Vector<ConfigInfo::ConfigRuleSection>§ions, + struct InitConfigFileParser::Context &ctx, + const char * rule_data) +{ + Uint32 db_nodes = 0; + Uint32 replicas = 0; + ctx.m_userProperties.get("DB", &db_nodes); + ctx.m_userProperties.get("NoOfReplicas", &replicas); + if((db_nodes % replicas) != 0){ + ctx.reportError("Invalid no of db nodes wrt no of replicas.\n" + "No of nodes must be dividable with no or replicas"); + return false; + } + + return true; +} + +template class Vector<ConfigInfo::ConfigRuleSection>; diff --git a/ndb/src/common/mgmcommon/ConfigInfo.hpp b/ndb/src/common/mgmcommon/ConfigInfo.hpp index 79c17b436fe..9a954fe78d5 100644 --- a/ndb/src/common/mgmcommon/ConfigInfo.hpp +++ b/ndb/src/common/mgmcommon/ConfigInfo.hpp @@ -61,6 +61,11 @@ public: Uint64 _max; }; + struct AliasPair{ + const char * name; + const char * alias; + }; + /** * Entry for one section rule */ @@ -100,6 +105,7 @@ public: * @note Result is not defined if section/name are wrong! */ bool verify(const Properties* secti, const char* fname, Uint64 value) const; + const char* getAlias(const char*) const; bool isSection(const char*) const; const char* getDescription(const Properties * sec, const char* fname) const; @@ -123,6 +129,7 @@ private: static const ParamInfo m_ParamInfo[]; static const int m_NoOfParams; + static const AliasPair m_sectionNameAliases[]; static const char* m_sectionNames[]; static const int m_noOfSectionNames; diff --git a/ndb/src/common/mgmcommon/ConfigRetriever.cpp b/ndb/src/common/mgmcommon/ConfigRetriever.cpp index d2c622593de..2e809907058 100644 --- a/ndb/src/common/mgmcommon/ConfigRetriever.cpp +++ b/ndb/src/common/mgmcommon/ConfigRetriever.cpp @@ -37,37 +37,26 @@ #include <mgmapi.h> #include <mgmapi_config_parameters.h> +#include <mgmapi_configuration.hpp> #include <ConfigValues.hpp> #include <NdbHost.h> //**************************************************************************** //**************************************************************************** -ConfigRetriever::ConfigRetriever() { +ConfigRetriever::ConfigRetriever(Uint32 version, Uint32 node_type) { - _localConfigFileName = NULL; - m_defaultConnectString = NULL; - - - errorString = 0; - _localConfig = new LocalConfig(); - m_connectString = NULL; + m_handle= 0; + m_version = version; + m_node_type = node_type; } ConfigRetriever::~ConfigRetriever(){ - if(_localConfigFileName != 0) - free(_localConfigFileName); - - if(m_defaultConnectString != 0) - free(m_defaultConnectString); - if(m_connectString != 0) - free(m_connectString); - - if(errorString != 0) - free(errorString); - - delete _localConfig; + if (m_handle) { + ndb_mgm_disconnect(m_handle); + ndb_mgm_destroy_handle(&m_handle); + } } @@ -75,67 +64,51 @@ ConfigRetriever::~ConfigRetriever(){ //**************************************************************************** int -ConfigRetriever::init(bool onlyNodeId) { - if (_localConfig->init(onlyNodeId, m_connectString, _localConfigFileName, m_defaultConnectString)) { - return _ownNodeId = (*_localConfig)._ownNodeId; +ConfigRetriever::init() { + if (!_localConfig.init(m_connectString.c_str(), + _localConfigFileName.c_str())){ + + setError(CR_ERROR, "error in retrieving contact info for mgmtsrvr"); + _localConfig.printError(); + _localConfig.printUsage(); + return -1; } - - setError(CR_ERROR, "error in retrieving contact info for mgmtsrvr"); - _localConfig->printError(); - _localConfig->printUsage(); - - return -1; -} -//**************************************************************************** -//**************************************************************************** -//**************************************************************************** -//**************************************************************************** -struct ndb_mgm_configuration* -ConfigRetriever::getConfig(int verId, int nodeType) { + return _ownNodeId = _localConfig._ownNodeId; +} - int res = init(); - if (res == -1) { - return 0; - } +int +ConfigRetriever::do_connect(){ - if (_localConfig->items == 0){ - setError(CR_ERROR,"No Management Servers configured in local config file"); - return 0; + if(!m_handle) + m_handle= ndb_mgm_create_handle(); + + if (m_handle == 0) { + setError(CR_ERROR, "Unable to allocate mgm handle"); + return -1; } int retry = 1; int retry_max = 12; // Max number of retry attempts int retry_interval= 5; // Seconds between each retry - do { + while(retry < retry_max){ Uint32 type = CR_ERROR; - for (int i = 0; i<_localConfig->items; i++){ - MgmtSrvrId * m = _localConfig->ids[i]; - struct ndb_mgm_configuration * p = 0; + BaseString tmp; + for (int i = 0; i<_localConfig.ids.size(); i++){ + MgmtSrvrId * m = &_localConfig.ids[i]; switch(m->type){ case MgmId_TCP: - p = getConfig(m->data.tcp.remoteHost, m->data.tcp.port, verId); - break; - case MgmId_File: - p = getConfig(m->data.file.filename, verId); - break; - default: - setError(CR_ERROR, "Unknown error type"); - break; - } - - if (p != 0) { - if(!verifyConfig(p, nodeType)){ - free(p); + tmp.assfmt("%s:%d", m->name.c_str(), m->port); + if (ndb_mgm_connect(m_handle, tmp.c_str()) == 0) { return 0; } - return p; + setError(CR_RETRY, ndb_mgm_get_latest_error_desc(m_handle)); + case MgmId_File: + break; } - if(latestErrorType == CR_RETRY) - type = CR_RETRY; - } // for - - if(type == CR_RETRY){ + } + + if(latestErrorType == CR_RETRY){ REPORT_WARNING("Failed to retrieve cluster configuration"); ndbout << "(Cause of failure: " << getErrorString() << ")" << endl; ndbout << "Attempt " << retry << " of " << retry_max << ". " @@ -146,60 +119,63 @@ ConfigRetriever::getConfig(int verId, int nodeType) { break; } retry++; - - } while (retry <= retry_max); + } - return 0; + ndb_mgm_destroy_handle(&m_handle); + m_handle= 0; + return -1; } -ndb_mgm_configuration * -ConfigRetriever::getConfig(const char * mgmhost, - short port, - int versionId){ - - NdbMgmHandle h; - h = ndb_mgm_create_handle(); - if (h == NULL) { - setError(CR_ERROR, "Unable to allocate mgm handle"); - return 0; - } +//**************************************************************************** +//**************************************************************************** +//**************************************************************************** +//**************************************************************************** +struct ndb_mgm_configuration* +ConfigRetriever::getConfig() { + + struct ndb_mgm_configuration * p = 0; - BaseString tmp; - tmp.assfmt("%s:%d", mgmhost, port); - if (ndb_mgm_connect(h, tmp.c_str()) != 0) { - setError(CR_RETRY, ndb_mgm_get_latest_error_desc(h)); - ndb_mgm_destroy_handle(&h); + if(m_handle != 0){ + p = getConfig(m_handle); + } else { + for (int i = 0; i<_localConfig.ids.size(); i++){ + MgmtSrvrId * m = &_localConfig.ids[i]; + switch(m->type){ + case MgmId_File: + p = getConfig(m->name.c_str()); + break; + case MgmId_TCP: + break; + } + if(p) + break; + } + } + if(p == 0) return 0; + + if(!verifyConfig(p)){ + free(p); + p= 0; } + + return p; +} - ndb_mgm_configuration * conf = ndb_mgm_get_configuration(h, versionId); +ndb_mgm_configuration * +ConfigRetriever::getConfig(NdbMgmHandle m_handle){ + + ndb_mgm_configuration * conf = ndb_mgm_get_configuration(m_handle,m_version); if(conf == 0){ - setError(CR_ERROR, ndb_mgm_get_latest_error_desc(h)); - } - - ndb_mgm_disconnect(h); - ndb_mgm_destroy_handle(&h); - - return conf; -#if 0 - bool compatible; - if (global_ndb_check) - compatible = ndbCompatible_ndb_mgmt(versionId, version); - else - compatible = ndbCompatible_api_mgmt(versionId, version); - - if(!compatible){ // if(version != versionId){ - NDB_CLOSE_SOCKET(sockfd); - snprintf(err_buf, sizeof(err_buf), "Management Server: Invalid version. " - "Version from server: %d Own version: %d", version, versionId); - setError(CR_ERROR, err_buf); + setError(CR_ERROR, ndb_mgm_get_latest_error_desc(m_handle)); return 0; } -#endif + + return conf; } ndb_mgm_configuration * -ConfigRetriever::getConfig(const char * filename, int versionId){ +ConfigRetriever::getConfig(const char * filename){ struct stat sbuf; const int res = stat(filename, &sbuf); @@ -242,60 +218,29 @@ ConfigRetriever::getConfig(const char * filename, int versionId){ void ConfigRetriever::setError(ErrorType et, const char * s){ - if(errorString != 0){ - free(errorString); - } - if(s == 0) - errorString = 0; - else - errorString = strdup(s); + errorString.assign(s ? s : ""); latestErrorType = et; } const char * ConfigRetriever::getErrorString(){ - return errorString; + return errorString.c_str(); } void ConfigRetriever::setLocalConfigFileName(const char * localConfigFileName) { - if(_localConfigFileName != 0) - free(_localConfigFileName); - if(localConfigFileName != 0) - _localConfigFileName = strdup(localConfigFileName); - else - _localConfigFileName = 0; + _localConfigFileName.assign(localConfigFileName ? localConfigFileName : ""); } void ConfigRetriever::setConnectString(const char * connectString) { - if(m_connectString != 0) - free(m_connectString); - if (connectString != 0) { - m_connectString = strdup(connectString); - } else { - m_connectString = 0; - } -} - -/** - * @note Do not use! Use the one above if possible. /elathal - */ -void -ConfigRetriever::setDefaultConnectString(const char * defaultConnectString) { - if(m_defaultConnectString != 0) - free(m_defaultConnectString); - if (defaultConnectString != 0) { - m_defaultConnectString = strdup(defaultConnectString); - } else { - m_defaultConnectString = 0; - } + m_connectString.assign(connectString ? connectString : ""); } bool -ConfigRetriever::verifyConfig(const struct ndb_mgm_configuration * conf, - int type){ +ConfigRetriever::verifyConfig(const struct ndb_mgm_configuration * conf){ + char buf[255]; ndb_mgm_configuration_iterator * it; it = ndb_mgm_create_configuration_iterator((struct ndb_mgm_configuration *)conf, CFG_SECTION_NODE); @@ -308,8 +253,8 @@ ConfigRetriever::verifyConfig(const struct ndb_mgm_configuration * conf, } NdbAutoPtr<ndb_mgm_configuration_iterator> ptr(it); - if(ndb_mgm_find(it, CFG_NODE_ID, getOwnNodeId()) != 0){ - snprintf(buf, 255, "Unable to find node with id: %d", getOwnNodeId()); + if(ndb_mgm_find(it, CFG_NODE_ID, _ownNodeId) != 0){ + snprintf(buf, 255, "Unable to find node with id: %d", _ownNodeId); setError(CR_ERROR, buf); return false; } @@ -323,12 +268,15 @@ ConfigRetriever::verifyConfig(const struct ndb_mgm_configuration * conf, char localhost[MAXHOSTNAMELEN]; if(NdbHost_GetHostName(localhost) != 0){ - snprintf(buf, 255, "Unable to own hostname"); + snprintf(buf, 255, "Unable to get own hostname"); setError(CR_ERROR, buf); return false; } do { + if(strlen(hostname) == 0) + break; + if(strcasecmp(hostname, localhost) == 0) break; @@ -363,11 +311,67 @@ ConfigRetriever::verifyConfig(const struct ndb_mgm_configuration * conf, return false; } - if(_type != type){ + if(_type != m_node_type){ snprintf(buf, 255, "Supplied node type(%d) and config node type(%d) " - " don't match", type, _type); + " don't match", m_node_type, _type); setError(CR_ERROR, buf); return false; } + + /** + * Check hostnames + */ + ndb_mgm_configuration_iterator iter(* conf, CFG_SECTION_CONNECTION); + for(iter.first(); iter.valid(); iter.next()){ + + Uint32 type = CONNECTION_TYPE_TCP + 1; + if(iter.get(CFG_TYPE_OF_SECTION, &type)) continue; + if(type != CONNECTION_TYPE_TCP) continue; + + Uint32 nodeId1, nodeId2, remoteNodeId; + if(iter.get(CFG_CONNECTION_NODE_1, &nodeId1)) continue; + if(iter.get(CFG_CONNECTION_NODE_2, &nodeId2)) continue; + + if(nodeId1 != _ownNodeId && nodeId2 != _ownNodeId) continue; + remoteNodeId = (_ownNodeId == nodeId1 ? nodeId2 : nodeId1); + + const char * name; + struct in_addr addr; + BaseString tmp; + if(!iter.get(CFG_TCP_HOSTNAME_1, &name) && strlen(name)){ + if(Ndb_getInAddr(&addr, name) != 0){ + tmp.assfmt("Unable to lookup/illegal hostname %s, " + "connection from node %d to node %d", + name, _ownNodeId, remoteNodeId); + setError(CR_ERROR, tmp.c_str()); + return false; + } + } + + if(!iter.get(CFG_TCP_HOSTNAME_2, &name) && strlen(name)){ + if(Ndb_getInAddr(&addr, name) != 0){ + tmp.assfmt("Unable to lookup/illegal hostname %s, " + "connection from node %d to node %d", + name, _ownNodeId, remoteNodeId); + setError(CR_ERROR, tmp.c_str()); + return false; + } + } + } return true; } + +Uint32 +ConfigRetriever::allocNodeId(){ + unsigned nodeid= _ownNodeId; + + if(m_handle != 0){ + int res= ndb_mgm_alloc_nodeid(m_handle, m_version, &nodeid, m_node_type); + if(res != 0) { + setError(CR_ERROR, ndb_mgm_get_latest_error_desc(m_handle)); + return 0; + } + } + + return _ownNodeId= nodeid; +} diff --git a/ndb/src/common/mgmcommon/IPCConfig.cpp b/ndb/src/common/mgmcommon/IPCConfig.cpp index ba5fe7ace80..a76c541f3f6 100644 --- a/ndb/src/common/mgmcommon/IPCConfig.cpp +++ b/ndb/src/common/mgmcommon/IPCConfig.cpp @@ -339,12 +339,13 @@ IPCConfig::getNodeType(NodeId id) const { return out; } +#include <mgmapi.h> Uint32 IPCConfig::configureTransporters(Uint32 nodeId, const class ndb_mgm_configuration & config, class TransporterRegistry & tr){ - Uint32 noOfTransportersCreated = 0; + Uint32 noOfTransportersCreated= 0, server_port= 0; ndb_mgm_configuration_iterator iter(config, CFG_SECTION_CONNECTION); for(iter.first(); iter.valid(); iter.next()){ @@ -364,6 +365,16 @@ IPCConfig::configureTransporters(Uint32 nodeId, Uint32 type = ~0; if(iter.get(CFG_TYPE_OF_SECTION, &type)) continue; + Uint32 tmp_server_port= 0; + if(iter.get(CFG_CONNECTION_SERVER_PORT, &tmp_server_port)) break; + if (nodeId <= nodeId1 && nodeId <= nodeId2) { + if (server_port && server_port != tmp_server_port) { + ndbout << "internal error in config setup of server ports line= " << __LINE__ << endl; + exit(-1); + } + server_port= tmp_server_port; + } + switch(type){ case CONNECTION_TYPE_SHM:{ SHM_TransporterConfiguration conf; @@ -377,6 +388,8 @@ IPCConfig::configureTransporters(Uint32 nodeId, if(iter.get(CFG_SHM_KEY, &conf.shmKey)) break; if(iter.get(CFG_SHM_BUFFER_MEM, &conf.shmSize)) break; + conf.port= tmp_server_port; + if(!tr.createTransporter(&conf)){ ndbout << "Failed to create SHM Transporter from: " << conf.localNodeId << " to: " << conf.remoteNodeId << endl; @@ -428,10 +441,10 @@ IPCConfig::configureTransporters(Uint32 nodeId, if(iter.get(CFG_TCP_HOSTNAME_1, &host1)) break; if(iter.get(CFG_TCP_HOSTNAME_2, &host2)) break; - if(iter.get(CFG_TCP_SERVER_PORT, &conf.port)) break; if(iter.get(CFG_TCP_SEND_BUFFER_SIZE, &conf.sendBufferSize)) break; if(iter.get(CFG_TCP_RECEIVE_BUFFER_SIZE, &conf.maxReceiveSize)) break; + conf.port= tmp_server_port; const char * proxy; if (!iter.get(CFG_TCP_PROXY, &proxy)) { if (strlen(proxy) > 0 && nodeId2 == nodeId) { @@ -490,6 +503,8 @@ IPCConfig::configureTransporters(Uint32 nodeId, } } + tr.m_service_port= server_port; + return noOfTransportersCreated; } diff --git a/ndb/src/common/mgmcommon/InitConfigFileParser.cpp b/ndb/src/common/mgmcommon/InitConfigFileParser.cpp index d52bc54db52..7c842508491 100644 --- a/ndb/src/common/mgmcommon/InitConfigFileParser.cpp +++ b/ndb/src/common/mgmcommon/InitConfigFileParser.cpp @@ -43,10 +43,10 @@ InitConfigFileParser::~InitConfigFileParser() { // Read Config File //**************************************************************************** InitConfigFileParser::Context::Context(const ConfigInfo * info) - : m_configValues(1000, 20) { + : m_configValues(1000, 20), m_userProperties(true) { - m_config = new Properties(); - m_defaults = new Properties(); + m_config = new Properties(true); + m_defaults = new Properties(true); } InitConfigFileParser::Context::~Context(){ @@ -115,7 +115,7 @@ InitConfigFileParser::parseConfig(FILE * file) { snprintf(ctx.fname, sizeof(ctx.fname), section); free(section); ctx.type = InitConfigFileParser::DefaultSection; ctx.m_sectionLineno = ctx.m_lineno; - ctx.m_currentSection = new Properties(); + ctx.m_currentSection = new Properties(true); ctx.m_userDefaults = NULL; ctx.m_currentInfo = m_info->getInfo(ctx.fname); ctx.m_systemDefaults = m_info->getDefaults(ctx.fname); @@ -137,7 +137,7 @@ InitConfigFileParser::parseConfig(FILE * file) { free(section); ctx.type = InitConfigFileParser::Section; ctx.m_sectionLineno = ctx.m_lineno; - ctx.m_currentSection = new Properties(); + ctx.m_currentSection = new Properties(true); ctx.m_userDefaults = getSection(ctx.fname, ctx.m_defaults); ctx.m_currentInfo = m_info->getInfo(ctx.fname); ctx.m_systemDefaults = m_info->getDefaults(ctx.fname); @@ -222,6 +222,8 @@ bool InitConfigFileParser::parseNameValuePair(Context& ctx, const char* line) { char tmpLine[MAX_LINE_LENGTH]; char fname[MAX_LINE_LENGTH], rest[MAX_LINE_LENGTH]; char* t; + const char *separator_list[]= {":", "=", 0}; + const char *separator= 0; if (ctx.m_currentSection == NULL){ ctx.reportError("Value specified outside section"); @@ -233,7 +235,14 @@ bool InitConfigFileParser::parseNameValuePair(Context& ctx, const char* line) { // ************************************* // Check if a separator exists in line // ************************************* - if (!strchr(tmpLine, ':')) { + for(int i= 0; separator_list[i] != 0; i++) { + if(strchr(tmpLine, separator_list[i][0])) { + separator= separator_list[i]; + break; + } + } + + if (separator == 0) { ctx.reportError("Parse error"); return false; } @@ -241,13 +250,13 @@ bool InitConfigFileParser::parseNameValuePair(Context& ctx, const char* line) { // ******************************************* // Get pointer to substring before separator // ******************************************* - t = strtok(tmpLine, ":"); + t = strtok(tmpLine, separator); // ***************************************** // Count number of tokens before separator // ***************************************** if (sscanf(t, "%120s%120s", fname, rest) != 1) { - ctx.reportError("Multiple names before \':\'"); + ctx.reportError("Multiple names before \'%c\'", separator[0]); return false; } if (!ctx.m_currentInfo->contains(fname)) { @@ -475,8 +484,24 @@ InitConfigFileParser::parseSectionHeader(const char* line) const { tmp[0] = ' '; trim(tmp); + // Convert section header to upper + for(int i= strlen(tmp)-1; i >= 0; i--) + tmp[i]= toupper(tmp[i]); + + // Get the correct header name if an alias + { + const char *tmp_alias= m_info->getAlias(tmp); + if (tmp_alias) { + free(tmp); + tmp= strdup(tmp_alias); + } + } + // Lookup token among sections - if(!m_info->isSection(tmp)) return NULL; + if(!m_info->isSection(tmp)) { + free(tmp); + return NULL; + } if(m_info->getInfo(tmp)) return tmp; free(tmp); @@ -497,7 +522,7 @@ InitConfigFileParser::parseDefaultSectionHeader(const char* line) const { if (no != 2) return NULL; // Not correct keyword at end - if (!strcmp(token2, "DEFAULT") == 0) return NULL; + if (!strcasecmp(token2, "DEFAULT") == 0) return NULL; if(m_info->getInfo(token1)){ return strdup(token1); diff --git a/ndb/src/common/mgmcommon/LocalConfig.cpp b/ndb/src/common/mgmcommon/LocalConfig.cpp index 12e685ced34..0440ce84dba 100644 --- a/ndb/src/common/mgmcommon/LocalConfig.cpp +++ b/ndb/src/common/mgmcommon/LocalConfig.cpp @@ -17,17 +17,16 @@ #include "LocalConfig.hpp" #include <NdbEnv.h> #include <NdbConfig.h> +#include <NdbAutoPtr.hpp> LocalConfig::LocalConfig(){ - ids = 0; size = 0; items = 0; error_line = 0; error_msg[0] = 0; + _ownNodeId= 0; } bool -LocalConfig::init(bool onlyNodeId, - const char *connectString, - const char *fileName, - const char *defaultConnectString) { +LocalConfig::init(const char *connectString, + const char *fileName) { /** * Escalation: * 1. Check connectString @@ -39,8 +38,8 @@ LocalConfig::init(bool onlyNodeId, */ //1. Check connectString - if(connectString != 0) { - if(readConnectString(connectString, onlyNodeId)){ + if(connectString != 0 && connectString[0] != 0){ + if(readConnectString(connectString)){ return true; } return false; @@ -49,7 +48,7 @@ LocalConfig::init(bool onlyNodeId, //2. Check given filename if (fileName && strlen(fileName) > 0) { bool fopenError; - if(readFile(fileName, fopenError, onlyNodeId)){ + if(readFile(fileName, fopenError)){ return true; } return false; @@ -59,7 +58,7 @@ LocalConfig::init(bool onlyNodeId, char buf[255]; if(NdbEnv_GetEnv("NDB_CONNECTSTRING", buf, sizeof(buf)) && strlen(buf) != 0){ - if(readConnectString(buf, onlyNodeId)){ + if(readConnectString(buf)){ return true; } return false; @@ -68,10 +67,10 @@ LocalConfig::init(bool onlyNodeId, //4. Check Ndb.cfg in NDB_HOME { bool fopenError; - char buf[256]; - if(readFile(NdbConfig_NdbCfgName(buf, sizeof(buf), 1 /*true*/), fopenError, onlyNodeId)){ + char *buf= NdbConfig_NdbCfgName(1 /*true*/); + NdbAutoPtr<char> tmp_aptr(buf); + if(readFile(buf, fopenError)) return true; - } if (!fopenError) return false; } @@ -79,20 +78,20 @@ LocalConfig::init(bool onlyNodeId, //5. Check Ndb.cfg in cwd { bool fopenError; - char buf[256]; - if(readFile(NdbConfig_NdbCfgName(buf, sizeof(buf), 0 /*false*/), fopenError, onlyNodeId)){ + char *buf= NdbConfig_NdbCfgName(0 /*false*/); + NdbAutoPtr<char> tmp_aptr(buf); + if(readFile(buf, fopenError)) return true; - } if (!fopenError) return false; } - //6. Check defaultConnectString - if(defaultConnectString != 0) { - if(readConnectString(defaultConnectString, onlyNodeId)){ + //7. Check + { + char buf[256]; + snprintf(buf, sizeof(buf), "host=localhost:%u", NDB_BASE_PORT); + if(readConnectString(buf)) return true; - } - return false; } setError(0, ""); @@ -101,30 +100,8 @@ LocalConfig::init(bool onlyNodeId, } LocalConfig::~LocalConfig(){ - for(int i = 0; i<items; i++){ - if(ids[i]->type == MgmId_TCP) - free(ids[i]->data.tcp.remoteHost); - else if(ids[i]->type == MgmId_File) - free(ids[i]->data.file.filename); - delete ids[i]; - } - if(ids != 0) - delete[] ids; } -void LocalConfig::add(MgmtSrvrId * i){ - if(items == size){ - MgmtSrvrId ** tmp = new MgmtSrvrId * [size+10]; - if(ids != 0){ - memcpy(tmp, ids, items*sizeof(MgmtSrvrId *)); - delete []ids; - } - ids = tmp; - } - ids[items] = i; - items++; -} - void LocalConfig::setError(int lineNumber, const char * _msg) { error_line = lineNumber; strncpy(error_msg, _msg, sizeof(error_msg)); @@ -144,22 +121,22 @@ void LocalConfig::printUsage() const { ndbout << "1. Put a Ndb.cfg file in the directory where you start"<<endl << " the node. "<< endl << " Ex: Ndb.cfg" << endl - << " | nodeid=11;host=localhost:2200"<<endl<<endl; + << " | host=localhost:"<<NDB_BASE_PORT<<endl; ndbout << "2. Use the environment variable NDB_CONNECTSTRING to "<<endl << " provide this information." <<endl << " Ex: " << endl - << " >export NDB_CONNECTSTRING=\"nodeid=11;host=localhost:2200\"" + << " >export NDB_CONNECTSTRING=\"host=localhost:"<<NDB_BASE_PORT<<"\"" <<endl<<endl; } -char *nodeIdTokens[] = { +const char *nodeIdTokens[] = { "OwnProcessId %i", "nodeid=%i", 0 }; -char *hostNameTokens[] = { +const char *hostNameTokens[] = { "host://%[^:]:%i", "host=%[^:]:%i", "%[^:]:%i", @@ -167,7 +144,7 @@ char *hostNameTokens[] = { 0 }; -char *fileNameTokens[] = { +const char *fileNameTokens[] = { "file://%s", "file=%s", 0 @@ -183,15 +160,15 @@ LocalConfig::parseNodeId(const char * buf){ bool LocalConfig::parseHostName(const char * buf){ - char tempString[100]; + char tempString[1024]; int port; for(int i = 0; hostNameTokens[i] != 0; i++) { if (sscanf(buf, hostNameTokens[i], tempString, &port) == 2) { - MgmtSrvrId* mgmtSrvrId = new MgmtSrvrId(); - mgmtSrvrId->type = MgmId_TCP; - mgmtSrvrId->data.tcp.remoteHost = strdup(tempString); - mgmtSrvrId->data.tcp.port = port; - add(mgmtSrvrId); + MgmtSrvrId mgmtSrvrId; + mgmtSrvrId.type = MgmId_TCP; + mgmtSrvrId.name.assign(tempString); + mgmtSrvrId.port = port; + ids.push_back(mgmtSrvrId); return true; } } @@ -200,13 +177,13 @@ LocalConfig::parseHostName(const char * buf){ bool LocalConfig::parseFileName(const char * buf){ - char tempString[100]; + char tempString[1024]; for(int i = 0; fileNameTokens[i] != 0; i++) { if (sscanf(buf, fileNameTokens[i], tempString) == 1) { - MgmtSrvrId* mgmtSrvrId = new MgmtSrvrId(); - mgmtSrvrId->type = MgmId_File; - mgmtSrvrId->data.file.filename = strdup(tempString); - add(mgmtSrvrId); + MgmtSrvrId mgmtSrvrId; + mgmtSrvrId.type = MgmId_File; + mgmtSrvrId.name.assign(tempString); + ids.push_back(mgmtSrvrId); return true; } } @@ -214,17 +191,15 @@ LocalConfig::parseFileName(const char * buf){ } bool -LocalConfig::parseString(const char * connectString, bool onlyNodeId, char *line){ - bool return_value = true; - +LocalConfig::parseString(const char * connectString, char *line){ char * for_strtok; char * copy = strdup(connectString); + NdbAutoPtr<char> tmp_aptr(copy); bool b_nodeId = false; bool found_other = false; - for (char *tok = strtok_r(copy,";",&for_strtok); - tok != 0 && !(onlyNodeId && b_nodeId); + for (char *tok = strtok_r(copy,";",&for_strtok); tok != 0; tok = strtok_r(NULL, ";", &for_strtok)) { if (tok[0] == '#') continue; @@ -232,28 +207,27 @@ LocalConfig::parseString(const char * connectString, bool onlyNodeId, char *line if (!b_nodeId) // only one nodeid definition allowed if (b_nodeId = parseNodeId(tok)) continue; - if (onlyNodeId) - continue; if (found_other = parseHostName(tok)) continue; if (found_other = parseFileName(tok)) continue; - snprintf(line, 150, "Unexpected entry: \"%s\"", tok); - return_value = false; - break; + if (line) + snprintf(line, 150, "Unexpected entry: \"%s\"", tok); + return false; } - if (return_value && !onlyNodeId && !found_other) { - return_value = false; - snprintf(line, 150, "Missing host/file name extry in \"%s\"", connectString); + if (!found_other) { + if (line) + snprintf(line, 150, "Missing host/file name extry in \"%s\"", + connectString); + return false; } - free(copy); - return return_value; + return true; } -bool LocalConfig::readFile(const char * filename, bool &fopenError, bool onlyNodeId) +bool LocalConfig::readFile(const char * filename, bool &fopenError) { char line[150], line2[150]; @@ -284,7 +258,7 @@ bool LocalConfig::readFile(const char * filename, bool &fopenError, bool onlyNod strcat(theString, line); } - bool return_value = parseString(theString, onlyNodeId, line); + bool return_value = parseString(theString, line); if (!return_value) { snprintf(line2, 150, "Reading %s: %s", filename, line); @@ -297,12 +271,14 @@ bool LocalConfig::readFile(const char * filename, bool &fopenError, bool onlyNod } bool -LocalConfig::readConnectString(const char * connectString, bool onlyNodeId){ +LocalConfig::readConnectString(const char * connectString){ char line[150], line2[150]; - bool return_value = parseString(connectString, onlyNodeId, line); + bool return_value = parseString(connectString, line); if (!return_value) { snprintf(line2, 150, "Reading NDB_CONNECTSTRING \"%s\": %s", connectString, line); setError(0,line2); } return return_value; } + +template class Vector<MgmtSrvrId>; diff --git a/ndb/src/common/mgmcommon/NdbConfig.c b/ndb/src/common/mgmcommon/NdbConfig.c index 827ef34a840..6b609b22fa4 100644 --- a/ndb/src/common/mgmcommon/NdbConfig.c +++ b/ndb/src/common/mgmcommon/NdbConfig.c @@ -18,43 +18,93 @@ #include <NdbConfig.h> #include <NdbEnv.h> -const char* -NdbConfig_HomePath(char* buf, int buflen){ - const char* p; - p = NdbEnv_GetEnv("NDB_HOME", buf, buflen); - if (p == NULL){ - strlcpy(buf, "", buflen); - p = buf; - } else { - const int len = strlen(buf); - if(len != 0 && buf[len-1] != '/'){ - buf[len] = '/'; - buf[len+1] = 0; - } - } - return p; -} - -const char* -NdbConfig_NdbCfgName(char* buf, int buflen, int with_ndb_home){ - if (with_ndb_home) - NdbConfig_HomePath(buf, buflen); +static char* +NdbConfig_AllocHomePath(int _len) +{ + const char *path= NdbEnv_GetEnv("NDB_HOME", 0, 0); + int len= _len; + int path_len= 0; + char *buf; + + if (path) + path_len= strlen(path); + + len+= path_len; + buf= malloc(len); + if (path_len > 0) + snprintf(buf, len, "%s%s", path, DIR_SEPARATOR); else - buf[0] = 0; - strlcat(buf, "Ndb.cfg", buflen); + buf[0]= 0; + + return buf; +} + +char* +NdbConfig_NdbCfgName(int with_ndb_home){ + char *buf; + int len= 0; + + if (with_ndb_home) { + buf= NdbConfig_AllocHomePath(128); + len= strlen(buf); + } else + buf= malloc(128); + snprintf(buf+len, 128, "Ndb.cfg"); + return buf; +} + +char* +NdbConfig_ErrorFileName(int node_id){ + char *buf= NdbConfig_AllocHomePath(128); + int len= strlen(buf); + snprintf(buf+len, 128, "ndb_%u_error.log", node_id); + return buf; +} + +char* +NdbConfig_ClusterLogFileName(int node_id){ + char *buf= NdbConfig_AllocHomePath(128); + int len= strlen(buf); + snprintf(buf+len, 128, "ndb_%u_cluster.log", node_id); + return buf; +} + +char* +NdbConfig_SignalLogFileName(int node_id){ + char *buf= NdbConfig_AllocHomePath(128); + int len= strlen(buf); + snprintf(buf+len, 128, "ndb_%u_signal.log", node_id); + return buf; +} + +char* +NdbConfig_TraceFileName(int node_id, int file_no){ + char *buf= NdbConfig_AllocHomePath(128); + int len= strlen(buf); + snprintf(buf+len, 128, "ndb_%u_trace.log.%u", node_id, file_no); + return buf; +} + +char* +NdbConfig_NextTraceFileName(int node_id){ + char *buf= NdbConfig_AllocHomePath(128); + int len= strlen(buf); + snprintf(buf+len, 128, "ndb_%u_trace.log.next", node_id); return buf; } -const char* -NdbConfig_ErrorFileName(char* buf, int buflen){ - NdbConfig_HomePath(buf, buflen); - strlcat(buf, "error.log", buflen); +char* +NdbConfig_PidFileName(int node_id){ + char *buf= NdbConfig_AllocHomePath(128); + int len= strlen(buf); + snprintf(buf+len, 128, "ndb_%u.pid", node_id); return buf; } -const char* -NdbConfig_ClusterLogFileName(char* buf, int buflen){ - NdbConfig_HomePath(buf, buflen); - strlcat(buf, "cluster.log", buflen); +char* +NdbConfig_StdoutFileName(int node_id){ + char *buf= NdbConfig_AllocHomePath(128); + int len= strlen(buf); + snprintf(buf+len, 128, "ndb_%u_out.log", node_id); return buf; } diff --git a/ndb/src/common/portlib/Makefile.am b/ndb/src/common/portlib/Makefile.am index e6ecb30fe04..6f3a3fe01a9 100644 --- a/ndb/src/common/portlib/Makefile.am +++ b/ndb/src/common/portlib/Makefile.am @@ -4,7 +4,7 @@ noinst_LTLIBRARIES = libportlib.la libportlib_la_SOURCES = \ NdbCondition.c NdbMutex.c NdbSleep.c NdbTick.c \ - NdbEnv.c NdbThread.c NdbHost.c NdbTCP.c \ + NdbEnv.c NdbThread.c NdbHost.c NdbTCP.cpp \ NdbDaemon.c NdbMem.c include $(top_srcdir)/ndb/config/common.mk.am diff --git a/ndb/src/common/portlib/NdbTCP.c b/ndb/src/common/portlib/NdbTCP.cpp index 287dc6c2ecd..4bf4936aa30 100644 --- a/ndb/src/common/portlib/NdbTCP.c +++ b/ndb/src/common/portlib/NdbTCP.cpp @@ -16,14 +16,15 @@ #include <NdbMutex.h> -#include "NdbTCP.h" +#include <NdbTCP.h> -#ifdef NDB_WIN32 +#if defined NDB_WIN32 || defined SCO static NdbMutex & LOCK_gethostbyname = * NdbMutex_Create(); #else static NdbMutex LOCK_gethostbyname = NDB_MUTEX_INITIALIZER; #endif +extern "C" int Ndb_getInAddr(struct in_addr * dst, const char *address) { struct hostent * hostPtr; diff --git a/ndb/src/common/transporter/Packer.cpp b/ndb/src/common/transporter/Packer.cpp index fa72af12dac..645517a4b1a 100644 --- a/ndb/src/common/transporter/Packer.cpp +++ b/ndb/src/common/transporter/Packer.cpp @@ -391,6 +391,7 @@ Packer::pack(Uint32 * insertPtr, const SignalHeader * header, const Uint32 * theData, const LinearSectionPtr ptr[3]) const { + Uint32 i; Uint32 dataLen32 = header->theLength; Uint32 no_segs = header->m_noOfSections; @@ -400,7 +401,7 @@ Packer::pack(Uint32 * insertPtr, checksumUsed + signalIdUsed + (sizeof(Protocol6)/4); - for(Uint32 i = 0; i<no_segs; i++){ + for(i = 0; i<no_segs; i++){ len32 += ptr[i].sz; } @@ -429,12 +430,12 @@ Packer::pack(Uint32 * insertPtr, memcpy(tmpInserPtr, theData, 4 * dataLen32); tmpInserPtr += dataLen32; - for(Uint32 i = 0; i<no_segs; i++){ + for(i = 0; i<no_segs; i++){ tmpInserPtr[i] = ptr[i].sz; } tmpInserPtr += no_segs; - for(Uint32 i = 0; i<no_segs; i++){ + for(i = 0; i<no_segs; i++){ import(tmpInserPtr, ptr[i]); } @@ -450,6 +451,7 @@ Packer::pack(Uint32 * insertPtr, const Uint32 * theData, class SectionSegmentPool & thePool, const SegmentedSectionPtr ptr[3]) const { + Uint32 i; Uint32 dataLen32 = header->theLength; Uint32 no_segs = header->m_noOfSections; @@ -458,7 +460,7 @@ Packer::pack(Uint32 * insertPtr, dataLen32 + no_segs + checksumUsed + signalIdUsed + (sizeof(Protocol6)/4); - for(Uint32 i = 0; i<no_segs; i++){ + for(i = 0; i<no_segs; i++){ len32 += ptr[i].sz; } @@ -487,12 +489,12 @@ Packer::pack(Uint32 * insertPtr, memcpy(tmpInserPtr, theData, 4 * dataLen32); tmpInserPtr += dataLen32; - for(Uint32 i = 0; i<no_segs; i++){ + for(i = 0; i<no_segs; i++){ tmpInserPtr[i] = ptr[i].sz; } tmpInserPtr += no_segs; - for(Uint32 i = 0; i<no_segs; i++){ + for(i = 0; i<no_segs; i++){ copy(tmpInserPtr, thePool, ptr[i]); } diff --git a/ndb/src/common/transporter/SHM_Transporter.cpp b/ndb/src/common/transporter/SHM_Transporter.cpp index 7c673f93c22..aa6b650afa8 100644 --- a/ndb/src/common/transporter/SHM_Transporter.cpp +++ b/ndb/src/common/transporter/SHM_Transporter.cpp @@ -23,26 +23,22 @@ #include <NdbSleep.h> #include <NdbOut.hpp> -#ifndef NDB_WIN32 -#include <sys/ipc.h> -#include <sys/shm.h> -#endif - +#include <InputStream.hpp> +#include <OutputStream.hpp> -SHM_Transporter::SHM_Transporter(NodeId lNodeId, +SHM_Transporter::SHM_Transporter(TransporterRegistry &t_reg, + const char *lHostName, + const char *rHostName, + int r_port, + NodeId lNodeId, NodeId rNodeId, - key_t _shmKey, - Uint32 _shmSize, bool compression, bool checksum, - bool signalId) : - Transporter(lNodeId, - rNodeId, - 0, - compression, - checksum, - signalId), - isServer(lNodeId < rNodeId), + bool signalId, + key_t _shmKey, + Uint32 _shmSize) : + Transporter(t_reg, lHostName, rHostName, r_port, lNodeId, rNodeId, + 0, compression, checksum, signalId), shmKey(_shmKey), shmSize(_shmSize) { @@ -68,16 +64,6 @@ SHM_Transporter::initTransporter(){ return true; } -bool -SHM_Transporter::connectImpl(Uint32 timeOutMillis){ - bool res; - if(isServer) - res = connectServer(timeOutMillis); - else - res = connectClient(timeOutMillis); - return res; -} - void SHM_Transporter::setupBuffers(){ Uint32 sharedSize = 0; @@ -233,3 +219,127 @@ SHM_Transporter::prepareSend(const SignalHeader * const signalHeader, return SEND_DISCONNECTED; } #endif + + +bool +SHM_Transporter::connect_server_impl(NDB_SOCKET_TYPE sockfd) +{ + SocketOutputStream s_output(sockfd); + SocketInputStream s_input(sockfd); + char buf[256]; + + // Create + if(!_shmSegCreated){ + if (!ndb_shm_create()) { + report_error(TE_SHM_UNABLE_TO_CREATE_SEGMENT); + NDB_CLOSE_SOCKET(sockfd); + return false; + } + _shmSegCreated = true; + } + + // Attach + if(!_attached){ + if (!ndb_shm_attach()) { + report_error(TE_SHM_UNABLE_TO_ATTACH_SEGMENT); + NDB_CLOSE_SOCKET(sockfd); + return false; + } + _attached = true; + } + + // Send ok to client + s_output.println("shm server 1 ok"); + + // Wait for ok from client + if (s_input.gets(buf, 256) == 0) { + NDB_CLOSE_SOCKET(sockfd); + return false; + } + + int r= connect_common(sockfd); + + if (r) { + // Send ok to client + s_output.println("shm server 2 ok"); + // Wait for ok from client + if (s_input.gets(buf, 256) == 0) { + NDB_CLOSE_SOCKET(sockfd); + return false; + } + } + + NDB_CLOSE_SOCKET(sockfd); + return r; +} + +bool +SHM_Transporter::connect_client_impl(NDB_SOCKET_TYPE sockfd) +{ + SocketInputStream s_input(sockfd); + SocketOutputStream s_output(sockfd); + char buf[256]; + + // Wait for server to create and attach + if (s_input.gets(buf, 256) == 0) { + NDB_CLOSE_SOCKET(sockfd); + return false; + } + + // Create + if(!_shmSegCreated){ + if (!ndb_shm_get()) { + NDB_CLOSE_SOCKET(sockfd); + return false; + } + _shmSegCreated = true; + } + + // Attach + if(!_attached){ + if (!ndb_shm_attach()) { + report_error(TE_SHM_UNABLE_TO_ATTACH_SEGMENT); + NDB_CLOSE_SOCKET(sockfd); + return false; + } + _attached = true; + } + + // Send ok to server + s_output.println("shm client 1 ok"); + + int r= connect_common(sockfd); + + if (r) { + // Wait for ok from server + if (s_input.gets(buf, 256) == 0) { + NDB_CLOSE_SOCKET(sockfd); + return false; + } + // Send ok to server + s_output.println("shm client 2 ok"); + } + + NDB_CLOSE_SOCKET(sockfd); + return r; +} + +bool +SHM_Transporter::connect_common(NDB_SOCKET_TYPE sockfd) +{ + if (!checkConnected()) + return false; + + if(!setupBuffersDone) { + setupBuffers(); + setupBuffersDone=true; + } + + if(setupBuffersDone) { + NdbSleep_MilliSleep(m_timeOutMillis); + if(*serverStatusFlag == 1 && *clientStatusFlag == 1) + return true; + } + + return false; +} diff --git a/ndb/src/common/transporter/SHM_Transporter.hpp b/ndb/src/common/transporter/SHM_Transporter.hpp index da4566515e3..be54d0daa2a 100644 --- a/ndb/src/common/transporter/SHM_Transporter.hpp +++ b/ndb/src/common/transporter/SHM_Transporter.hpp @@ -32,13 +32,17 @@ typedef Uint32 key_t; class SHM_Transporter : public Transporter { friend class TransporterRegistry; public: - SHM_Transporter(NodeId lNodeId, + SHM_Transporter(TransporterRegistry &, + const char *lHostName, + const char *rHostName, + int r_port, + NodeId lNodeId, NodeId rNodeId, - key_t shmKey, - Uint32 shmSize, bool compression, bool checksum, - bool signalId); + bool signalId, + key_t shmKey, + Uint32 shmSize); /** * SHM destructor @@ -75,14 +79,6 @@ protected: void disconnectImpl(); /** - * Invokes the connectServer or connectClient. - * @param timeOutMillis - the timeout the connect thread waits before - * retrying. - * @return True if connectImpl successful, otherwise false. - */ - bool connectImpl(Uint32 timeOutMillis); - - /** * Blocking * * -# Create shm segment @@ -94,7 +90,7 @@ protected: * i.e., both agrees that the other one has setup the segment. * Otherwise false. */ - bool connectServer(Uint32 timeOutMillis); + virtual bool connect_server_impl(NDB_SOCKET_TYPE sockfd); /** * Blocking @@ -108,8 +104,13 @@ protected: * i.e., both agrees that the other one has setup the segment. * Otherwise false. */ - bool connectClient(Uint32 timeOutMillis); + virtual bool connect_client_impl(NDB_SOCKET_TYPE sockfd); + + bool connect_common(NDB_SOCKET_TYPE sockfd); + bool ndb_shm_create(); + bool ndb_shm_get(); + bool ndb_shm_attach(); /** * Check if there are two processes attached to the segment (a connection) @@ -127,7 +128,6 @@ private: bool _shmSegCreated; bool _attached; - const bool isServer; key_t shmKey; volatile Uint32 * serverStatusFlag; volatile Uint32 * clientStatusFlag; diff --git a/ndb/src/common/transporter/SHM_Transporter.unix.cpp b/ndb/src/common/transporter/SHM_Transporter.unix.cpp index afbf124432e..28882324fc0 100644 --- a/ndb/src/common/transporter/SHM_Transporter.unix.cpp +++ b/ndb/src/common/transporter/SHM_Transporter.unix.cpp @@ -26,114 +26,37 @@ #include <sys/ipc.h> #include <sys/shm.h> - - bool -SHM_Transporter::connectServer(Uint32 timeOutMillis){ - if(!_shmSegCreated){ - shmId = shmget(shmKey, shmSize, IPC_CREAT | 960); - if(shmId == -1){ - perror("shmget: "); - reportThreadError(remoteNodeId, TE_SHM_UNABLE_TO_CREATE_SEGMENT); - NdbSleep_MilliSleep(timeOutMillis); - return false; - } - _shmSegCreated = true; - } - - if(!_attached){ - shmBuf = (char *)shmat(shmId, 0, 0); - if(shmBuf == 0){ - perror("shmat: "); - reportThreadError(remoteNodeId, TE_SHM_UNABLE_TO_ATTACH_SEGMENT); - NdbSleep_MilliSleep(timeOutMillis); - return false; - } - _attached = true; - } - - struct shmid_ds info; - const int res = shmctl(shmId, IPC_STAT, &info); - if(res == -1){ - perror("shmctl: "); - reportThreadError(remoteNodeId, TE_SHM_IPC_STAT); - NdbSleep_MilliSleep(timeOutMillis); +SHM_Transporter::ndb_shm_create() +{ + shmId = shmget(shmKey, shmSize, IPC_CREAT | 960); + if(shmId == -1) { + perror("shmget: "); return false; } - - if(info.shm_nattch == 2 && !setupBuffersDone) { - setupBuffers(); - setupBuffersDone=true; - } - - if(setupBuffersDone) { - NdbSleep_MilliSleep(timeOutMillis); - if(*serverStatusFlag==1 && *clientStatusFlag==1) - return true; - } - - - if(info.shm_nattch > 2){ - reportThreadError(remoteNodeId, TE_SHM_DISCONNECT); - NdbSleep_MilliSleep(timeOutMillis); - return false; - } - - NdbSleep_MilliSleep(timeOutMillis); - return false; + return true; } bool -SHM_Transporter::connectClient(Uint32 timeOutMillis){ - if(!_shmSegCreated){ - - shmId = shmget(shmKey, shmSize, 0); - if(shmId == -1){ - NdbSleep_MilliSleep(timeOutMillis); - return false; - } - _shmSegCreated = true; - } - - if(!_attached){ - shmBuf = (char *)shmat(shmId, 0, 0); - if(shmBuf == 0){ - reportThreadError(remoteNodeId, TE_SHM_UNABLE_TO_ATTACH_SEGMENT); - NdbSleep_MilliSleep(timeOutMillis); - return false; - } - _attached = true; - } - - struct shmid_ds info; - - const int res = shmctl(shmId, IPC_STAT, &info); - if(res == -1){ - reportThreadError(remoteNodeId, TE_SHM_IPC_STAT); - NdbSleep_MilliSleep(timeOutMillis); +SHM_Transporter::ndb_shm_get() +{ + shmId = shmget(shmKey, shmSize, 0); + if(shmId == -1) { + perror("shmget: "); return false; } - - - if(info.shm_nattch == 2 && !setupBuffersDone) { - setupBuffers(); - setupBuffersDone=true; - } - - if(setupBuffersDone) { - NdbSleep_MilliSleep(timeOutMillis); - if(*serverStatusFlag==1 && *clientStatusFlag==1) - return true; - } + return true; +} - if(info.shm_nattch > 2){ - reportThreadError(remoteNodeId, TE_SHM_DISCONNECT); - NdbSleep_MilliSleep(timeOutMillis); +bool +SHM_Transporter::ndb_shm_attach() +{ + shmBuf = (char *)shmat(shmId, 0, 0); + if(shmBuf == 0) { + perror("shmat: "); return false; } - - NdbSleep_MilliSleep(timeOutMillis); - return false; + return true; } bool @@ -141,12 +64,12 @@ SHM_Transporter::checkConnected(){ struct shmid_ds info; const int res = shmctl(shmId, IPC_STAT, &info); if(res == -1){ - reportError(callbackObj, remoteNodeId, TE_SHM_IPC_STAT); + report_error(TE_SHM_IPC_STAT); return false; } if(info.shm_nattch != 2){ - reportError(callbackObj, remoteNodeId, TE_SHM_DISCONNECT); + report_error(TE_SHM_DISCONNECT); return false; } return true; @@ -168,11 +91,10 @@ SHM_Transporter::disconnectImpl(){ if(isServer && _shmSegCreated){ const int res = shmctl(shmId, IPC_RMID, 0); if(res == -1){ - reportError(callbackObj, remoteNodeId, TE_SHM_UNABLE_TO_REMOVE_SEGMENT); + report_error(TE_SHM_UNABLE_TO_REMOVE_SEGMENT); return; } _shmSegCreated = false; } setupBuffersDone=false; } - diff --git a/ndb/src/common/transporter/TCP_Transporter.cpp b/ndb/src/common/transporter/TCP_Transporter.cpp index 99b6a137797..8833b51e236 100644 --- a/ndb/src/common/transporter/TCP_Transporter.cpp +++ b/ndb/src/common/transporter/TCP_Transporter.cpp @@ -63,27 +63,23 @@ ndbstrerror::~ndbstrerror(void) #define ndbstrerror strerror #endif -TCP_Transporter::TCP_Transporter(int sendBufSize, int maxRecvSize, - int portNo, - const char *rHostName, +TCP_Transporter::TCP_Transporter(TransporterRegistry &t_reg, + int sendBufSize, int maxRecvSize, const char *lHostName, - NodeId rNodeId, NodeId lNodeId, + const char *rHostName, + int r_port, + NodeId lNodeId, + NodeId rNodeId, int byte_order, bool compr, bool chksm, bool signalId, Uint32 _reportFreq) : - Transporter(lNodeId, rNodeId, byte_order, compr, chksm, signalId), - m_sendBuffer(sendBufSize), - isServer(lNodeId < rNodeId), - port(portNo) + Transporter(t_reg, lHostName, rHostName, r_port, lNodeId, rNodeId, + byte_order, compr, chksm, signalId), + m_sendBuffer(sendBufSize) { maxReceiveSize = maxRecvSize; - strncpy(remoteHostName, rHostName, sizeof(remoteHostName)); - // Initialize member variables - Ndb_getInAddr(&remoteHostAddress, rHostName); - - Ndb_getInAddr(&localHostAddress, lHostName); theSocket = NDB_INVALID_SOCKET; sendCount = receiveCount = 0; @@ -108,6 +104,24 @@ TCP_Transporter::~TCP_Transporter() { receiveBuffer.destroy(); } +bool TCP_Transporter::connect_server_impl(NDB_SOCKET_TYPE sockfd) +{ + return connect_common(sockfd); +} + +bool TCP_Transporter::connect_client_impl(NDB_SOCKET_TYPE sockfd) +{ + return connect_common(sockfd); +} + +bool TCP_Transporter::connect_common(NDB_SOCKET_TYPE sockfd) +{ + theSocket = sockfd; + setSocketOptions(); + setSocketNonBlocking(theSocket); + return true; +} + bool TCP_Transporter::initTransporter() { @@ -316,7 +330,7 @@ TCP_Transporter::doSend() { sendCount ++; sendSize += nBytesSent; if(sendCount == reportFreq){ - reportSendLen(callbackObj,remoteNodeId, sendCount, sendSize); + reportSendLen(get_callback_obj(), remoteNodeId, sendCount, sendSize); sendCount = 0; sendSize = 0; } @@ -331,7 +345,7 @@ TCP_Transporter::doSend() { #endif if(DISCONNECT_ERRNO(InetErrno, nBytesSent)){ doDisconnect(); - reportDisconnect(callbackObj, remoteNodeId, InetErrno); + report_disconnect(InetErrno); } return false; @@ -361,14 +375,15 @@ TCP_Transporter::doReceive() { #endif ndbout_c("receiveBuffer.sizeOfData(%d) > receiveBuffer.sizeOfBuffer(%d)", receiveBuffer.sizeOfData, receiveBuffer.sizeOfBuffer); - reportError(callbackObj, remoteNodeId, TE_INVALID_MESSAGE_LENGTH); + report_error(TE_INVALID_MESSAGE_LENGTH); return 0; } receiveCount ++; receiveSize += nBytesRead; + if(receiveCount == reportFreq){ - reportReceiveLen(callbackObj, remoteNodeId, receiveCount, receiveSize); + reportReceiveLen(get_callback_obj(), remoteNodeId, receiveCount, receiveSize); receiveCount = 0; receiveSize = 0; } @@ -384,60 +399,17 @@ TCP_Transporter::doReceive() { if(DISCONNECT_ERRNO(InetErrno, nBytesRead)){ // The remote node has closed down doDisconnect(); - reportDisconnect(callbackObj, remoteNodeId,InetErrno); + report_disconnect(InetErrno); } } return nBytesRead; } -bool -TCP_Transporter::connectImpl(Uint32 timeOutMillis){ - struct timeval timeout = {0, 0}; - timeout.tv_sec = timeOutMillis / 1000; - timeout.tv_usec = (timeOutMillis % 1000)*1000; - - bool retVal = false; - - if(isServer){ - if(theSocket == NDB_INVALID_SOCKET){ - startTCPServer(); - } - if(theSocket == NDB_INVALID_SOCKET) - { - NdbSleep_MilliSleep(timeOutMillis); - return false; - } - retVal = acceptClient(&timeout); - } else { - // Is client - retVal = connectClient(&timeout); - } - - if(!retVal) { - NdbSleep_MilliSleep(timeOutMillis); - return false; - } - -#if defined NDB_OSE || defined NDB_SOFTOSE - if(setsockopt(theSocket, SOL_SOCKET, SO_OSEOWNER, - &theReceiverPid, sizeof(PROCESS)) != 0){ - - ndbout << "Failed to transfer ownership of socket" << endl; - NDB_CLOSE_SOCKET(theSocket); - theSocket = -1; - return false; - } -#endif - - return true; -} - - void -TCP_Transporter::disconnectImpl() { +TCP_Transporter::disconnectImpl() { if(theSocket != NDB_INVALID_SOCKET){ if(NDB_CLOSE_SOCKET(theSocket) < 0){ - reportError(callbackObj, remoteNodeId, TE_ERROR_CLOSING_SOCKET); + report_error(TE_ERROR_CLOSING_SOCKET); } } @@ -447,155 +419,3 @@ TCP_Transporter::disconnectImpl() { theSocket = NDB_INVALID_SOCKET; } - -bool -TCP_Transporter::startTCPServer() { - - int bindResult, listenResult; - - // The server variable is the remote server when we are a client - // htonl and htons returns the parameter in network byte order - // INADDR_ANY tells the OS kernel to choose the IP address - struct sockaddr_in server; - memset((void*)&server, 0, sizeof(server)); - server.sin_family = AF_INET; - server.sin_addr.s_addr = localHostAddress.s_addr; - server.sin_port = htons(port); - - if (theSocket != NDB_INVALID_SOCKET) { - return true; // Server socket is already initialized - } - - // Create the socket - theSocket = socket(AF_INET, SOCK_STREAM, 0); - if (theSocket == NDB_INVALID_SOCKET) { - reportThreadError(remoteNodeId, TE_COULD_NOT_CREATE_SOCKET); - return false; - } - - // Set the socket reuse addr to true, so we are sure we can bind the - // socket - int reuseAddr = 1; - setsockopt(theSocket, SOL_SOCKET, SO_REUSEADDR, - (char*)&reuseAddr, sizeof(reuseAddr)); - - // Set the TCP_NODELAY option so also small packets are sent - // as soon as possible - int nodelay = 1; - setsockopt(theSocket, IPPROTO_TCP, TCP_NODELAY, - (char*)&nodelay, sizeof(nodelay)); - - // Bind the socket - bindResult = bind(theSocket, (struct sockaddr *) &server, - sizeof(server)); - if (bindResult < 0) { - reportThreadError(remoteNodeId, TE_COULD_NOT_BIND_SOCKET); - NDB_CLOSE_SOCKET(theSocket); - theSocket = NDB_INVALID_SOCKET; - return false; - } - - // Perform listen. - listenResult = listen(theSocket, 1); - if (listenResult == 1) { - reportThreadError(remoteNodeId, TE_LISTEN_FAILED); - NDB_CLOSE_SOCKET(theSocket); - theSocket = NDB_INVALID_SOCKET; - return false; - } - - return true; -} - - -bool -TCP_Transporter::acceptClient (struct timeval * timeout){ - - struct sockaddr_in clientAddress; - - fd_set readset; - FD_ZERO(&readset); - FD_SET(theSocket, &readset); - const int res = select(theSocket + 1, &readset, 0, 0, timeout); - if(res == 0) - return false; - - if(res < 0){ - reportThreadError(remoteNodeId, TE_ERROR_IN_SELECT_BEFORE_ACCEPT); - return false; - } - - NDB_SOCKLEN_T clientAddressLen = sizeof(clientAddress); - const NDB_SOCKET_TYPE clientSocket = accept(theSocket, - (struct sockaddr*)&clientAddress, - &clientAddressLen); - if (clientSocket == NDB_INVALID_SOCKET) { - reportThreadError(remoteNodeId, TE_ACCEPT_RETURN_ERROR); - return false; - } - - if (clientAddress.sin_addr.s_addr != remoteHostAddress.s_addr) { - ndbout_c("Wrong client connecting!"); - ndbout_c("connecting address: %s", inet_ntoa(clientAddress.sin_addr)); - ndbout_c("expecting address: %s", inet_ntoa(remoteHostAddress)); - // The newly connected host is not the remote host - // we wanted to connect to. Disconnect it. - // XXX This is not valid. We cannot disconnect it. - NDB_CLOSE_SOCKET(clientSocket); - return false; - } else { - NDB_CLOSE_SOCKET(theSocket); - theSocket = clientSocket; - setSocketOptions(); - setSocketNonBlocking(theSocket); - return true; - } -} - -bool -TCP_Transporter::connectClient (struct timeval * timeout){ - - // Create the socket - theSocket = socket(AF_INET, SOCK_STREAM, 0); - if (theSocket == NDB_INVALID_SOCKET) { - reportThreadError(remoteNodeId, TE_COULD_NOT_CREATE_SOCKET); - return false; - } - - struct sockaddr_in server; - memset((void*)&server, 0, sizeof(server)); - server.sin_family = AF_INET; - server.sin_addr = remoteHostAddress; - server.sin_port = htons(port); - - struct sockaddr_in client; - memset((void*)&client, 0, sizeof(client)); - client.sin_family = AF_INET; - client.sin_addr = localHostAddress; - client.sin_port = 0; // Any port - - // Bind the socket - const int bindResult = bind(theSocket, (struct sockaddr *) &client, - sizeof(client)); - if (bindResult < 0) { - reportThreadError(remoteNodeId, TE_COULD_NOT_BIND_SOCKET); - NDB_CLOSE_SOCKET(theSocket); - theSocket = NDB_INVALID_SOCKET; - return false; - } - - const int connectRes = ::connect(theSocket, (struct sockaddr *) &server, - sizeof(server)); - if(connectRes == 0){ - setSocketOptions(); - setSocketNonBlocking(theSocket); - return true; - } - - NDB_CLOSE_SOCKET(theSocket); - theSocket = NDB_INVALID_SOCKET; - return false; -} - - - diff --git a/ndb/src/common/transporter/TCP_Transporter.hpp b/ndb/src/common/transporter/TCP_Transporter.hpp index 30b730a5b1c..958cfde03a1 100644 --- a/ndb/src/common/transporter/TCP_Transporter.hpp +++ b/ndb/src/common/transporter/TCP_Transporter.hpp @@ -14,24 +14,8 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -//**************************************************************************** -// -// AUTHOR -// Åsa Fransson -// -// NAME -// TCP_Transporter -// -// DESCRIPTION -// A TCP_Transporter instance is created when TCP/IP-communication -// shall be used (user specified). It handles connect, disconnect, -// send and receive. -// -// -// -//***************************************************************************/ -#ifndef TCP_Transporter_H -#define TCP_Transporter_H +#ifndef TCP_TRANSPORTER_HPP +#define TCP_TRANSPORTER_HPP #include "Transporter.hpp" #include "SendBuffer.hpp" @@ -61,11 +45,13 @@ class TCP_Transporter : public Transporter { friend class TransporterRegistry; private: // Initialize member variables - TCP_Transporter(int sendBufferSize, int maxReceiveSize, - int port, - const char *rHostName, + TCP_Transporter(TransporterRegistry&, + int sendBufferSize, int maxReceiveSize, const char *lHostName, - NodeId rHostId, NodeId lHostId, + const char *rHostName, + int r_port, + NodeId lHostId, + NodeId rHostId, int byteorder, bool compression, bool checksum, bool signalId, Uint32 reportFreq = 4096); @@ -121,12 +107,14 @@ protected: * A client connects to the remote server * A server accepts any new connections */ - bool connectImpl(Uint32 timeOutMillis); + virtual bool connect_server_impl(NDB_SOCKET_TYPE sockfd); + virtual bool connect_client_impl(NDB_SOCKET_TYPE sockfd); + bool connect_common(NDB_SOCKET_TYPE sockfd); /** * Disconnects a TCP/IP node. Empty send and receivebuffer. */ - void disconnectImpl(); + virtual void disconnectImpl(); private: /** @@ -134,22 +122,12 @@ private: */ SendBuffer m_sendBuffer; - const bool isServer; - const unsigned int port; - // Sending/Receiving socket used by both client and server NDB_SOCKET_TYPE theSocket; Uint32 maxReceiveSize; /** - * Remote host name/and address - */ - char remoteHostName[256]; - struct in_addr remoteHostAddress; - struct in_addr localHostAddress; - - /** * Socket options */ int sockOptRcvBufSize; @@ -164,43 +142,6 @@ private: bool sendIsPossible(struct timeval * timeout); /** - * startTCPServer - None blocking - * - * create a server socket - * bind - * listen - * - * Note: Does not call accept - */ - bool startTCPServer(); - - /** - * acceptClient - Blocking - * - * Accept a connection - * checks if "right" client has connected - * if so - * close server socket - * else - * close newly created socket and goto begin - */ - bool acceptClient(struct timeval * timeout); - - /** - * Creates a client socket - * - * Note does not call connect - */ - bool createClientSocket(); - - /** - * connectClient - Blocking - * - * connects to remote host - */ - bool connectClient(struct timeval * timeout); - - /** * Statistics */ Uint32 reportFreq; diff --git a/ndb/src/common/transporter/Transporter.cpp b/ndb/src/common/transporter/Transporter.cpp index 5ca523d5185..7a469252c00 100644 --- a/ndb/src/common/transporter/Transporter.cpp +++ b/ndb/src/common/transporter/Transporter.cpp @@ -15,132 +15,118 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include <TransporterRegistry.hpp> +#include <TransporterCallback.hpp> #include "Transporter.hpp" #include "TransporterInternalDefinitions.hpp" #include <NdbSleep.h> - -Transporter::Transporter(NodeId lNodeId, NodeId rNodeId, +#include <SocketAuthenticator.hpp> +#include <InputStream.hpp> +#include <OutputStream.hpp> + +Transporter::Transporter(TransporterRegistry &t_reg, + const char *lHostName, + const char *rHostName, + int r_port, + NodeId lNodeId, + NodeId rNodeId, int _byteorder, bool _compression, bool _checksum, bool _signalId) - : localNodeId(lNodeId), remoteNodeId(rNodeId), - m_packer(_signalId, _checksum) + : m_r_port(r_port), localNodeId(lNodeId), remoteNodeId(rNodeId), + isServer(lNodeId < rNodeId), + m_packer(_signalId, _checksum), + m_transporter_registry(t_reg) { + if (rHostName && strlen(rHostName) > 0){ + strncpy(remoteHostName, rHostName, sizeof(remoteHostName)); + Ndb_getInAddr(&remoteHostAddress, rHostName); + } + else + { + if (!isServer) { + ndbout << "Unable to setup transporter. Node " << rNodeId + << " must have hostname. Update configuration." << endl; + exit(-1); + } + remoteHostName[0]= 0; + } + strncpy(localHostName, lHostName, sizeof(localHostName)); + + if (strlen(lHostName) > 0) + Ndb_getInAddr(&localHostAddress, lHostName); + byteOrder = _byteorder; compressionUsed = _compression; checksumUsed = _checksum; signalIdUsed = _signalId; - _threadError = TE_NO_ERROR; + m_connected = false; + m_timeOutMillis = 1000; - _connecting = false; - _disconnecting = false; - _connected = false; - _timeOutMillis = 1000; - theThreadPtr = NULL; - theMutexPtr = NdbMutex_Create(); + if (isServer) + m_socket_client= 0; + else + m_socket_client= new SocketClient(remoteHostName, r_port, + new SocketAuthSimple("ndbd", "ndbd passwd")); } Transporter::~Transporter(){ - NdbMutex_Destroy(theMutexPtr); - - if(theThreadPtr != 0){ - void * retVal; - NdbThread_WaitFor(theThreadPtr, &retVal); - NdbThread_Destroy(&theThreadPtr); - } + if (m_socket_client) + delete m_socket_client; } -extern "C" -void * -runConnect_C(void * me) -{ - runConnect(me); - NdbThread_Exit(0); - return NULL; -} - -void * -runConnect(void * me){ - Transporter * t = (Transporter *) me; - - DEBUG("Connect thread to " << t->remoteNodeId << " started"); - - while(true){ - NdbMutex_Lock(t->theMutexPtr); - if(t->_disconnecting){ - t->_connecting = false; - NdbMutex_Unlock(t->theMutexPtr); - DEBUG("Connect Thread " << t->remoteNodeId << " stop due to disconnect"); - return 0; - } - NdbMutex_Unlock(t->theMutexPtr); - - bool res = t->connectImpl(t->_timeOutMillis); // 1000 ms - DEBUG("Waiting for " << t->remoteNodeId << "..."); - if(res){ - t->_connected = true; - t->_connecting = false; - t->_errorCount = 0; - t->_threadError = TE_NO_ERROR; - DEBUG("Connect Thread " << t->remoteNodeId << " stop due to connect"); - return 0; - } - } -} - -void -Transporter::doConnect() { +bool +Transporter::connect_server(NDB_SOCKET_TYPE sockfd) { + if(m_connected) + return true; // TODO assert(0); - NdbMutex_Lock(theMutexPtr); - if(_connecting || _disconnecting || _connected){ - NdbMutex_Unlock(theMutexPtr); - return; + bool res = connect_server_impl(sockfd); + if(res){ + m_connected = true; + m_errorCount = 0; } - - _connecting = true; - _threadError = TE_NO_ERROR; + return res; +} - // Start thread +bool +Transporter::connect_client() { + if(m_connected) + return true; + NDB_SOCKET_TYPE sockfd = m_socket_client->connect(); - char buf[16]; - snprintf(buf, sizeof(buf), "ndb_con_%d", remoteNodeId); - - if(theThreadPtr != 0){ - void * retVal; - NdbThread_WaitFor(theThreadPtr, &retVal); - NdbThread_Destroy(&theThreadPtr); + if (sockfd < 0) + return false; + + // send info about own id + SocketOutputStream s_output(sockfd); + s_output.println("%d", localNodeId); + // get remote id + int nodeId; + SocketInputStream s_input(sockfd); + char buf[256]; + if (s_input.gets(buf, 256) == 0) { + NDB_CLOSE_SOCKET(sockfd); + return false; } - - theThreadPtr = NdbThread_Create(runConnect_C, - (void**)this, - 32768, - buf, - NDB_THREAD_PRIO_LOW); - - NdbSleep_MilliSleep(100); // Let thread start - - NdbMutex_Unlock(theMutexPtr); + if (sscanf(buf, "%d", &nodeId) != 1) { + NDB_CLOSE_SOCKET(sockfd); + return false; + } + bool res = connect_client_impl(sockfd); + if(res){ + m_connected = true; + m_errorCount = 0; + } + return res; } void -Transporter::doDisconnect() { - - NdbMutex_Lock(theMutexPtr); - _disconnecting = true; - while(_connecting){ - DEBUG("Waiting for connect to finish..."); - - NdbMutex_Unlock(theMutexPtr); - NdbSleep_MilliSleep(500); - NdbMutex_Lock(theMutexPtr); - } - - _connected = false; - +Transporter::doDisconnect() { + + if(!m_connected) + return; //assert(0); TODO will fail + + m_connected= false; disconnectImpl(); - _threadError = TE_NO_ERROR; - _disconnecting = false; - - NdbMutex_Unlock(theMutexPtr); } diff --git a/ndb/src/common/transporter/Transporter.hpp b/ndb/src/common/transporter/Transporter.hpp index 43b26d45899..9a39f8788bc 100644 --- a/ndb/src/common/transporter/Transporter.hpp +++ b/ndb/src/common/transporter/Transporter.hpp @@ -19,6 +19,9 @@ #include <ndb_global.h> +#include <SocketClient.hpp> + +#include <TransporterRegistry.hpp> #include <TransporterCallback.hpp> #include "TransporterDefinitions.hpp" #include "Packer.hpp" @@ -40,8 +43,9 @@ public: * None blocking * Use isConnected() to check status */ - virtual void doConnect(); - + bool connect_client(); + bool connect_server(NDB_SOCKET_TYPE socket); + /** * Blocking */ @@ -60,14 +64,17 @@ public: */ NodeId getRemoteNodeId() const; - /** - * Set callback object + * Local (own) Node Id */ - void setCallbackObject(void * callback); + NodeId getLocalNodeId() const; protected: - Transporter(NodeId lNodeId, + Transporter(TransporterRegistry &, + const char *lHostName, + const char *rHostName, + int r_port, + NodeId lNodeId, NodeId rNodeId, int byteorder, bool compression, @@ -78,58 +85,59 @@ protected: * Blocking, for max timeOut milli seconds * Returns true if connect succeded */ - virtual bool connectImpl(Uint32 timeOut) = 0; + virtual bool connect_server_impl(NDB_SOCKET_TYPE sockfd) = 0; + virtual bool connect_client_impl(NDB_SOCKET_TYPE sockfd) = 0; /** * Blocking */ virtual void disconnectImpl() = 0; - const NodeId localNodeId; + /** + * Remote host name/and address + */ + char remoteHostName[256]; + char localHostName[256]; + struct in_addr remoteHostAddress; + struct in_addr localHostAddress; + + const unsigned int m_r_port; + const NodeId remoteNodeId; + const NodeId localNodeId; + const bool isServer; + unsigned createIndex; int byteOrder; bool compressionUsed; bool checksumUsed; bool signalIdUsed; - Packer m_packer; - + Packer m_packer; private: - /** - * Thread and mutex for connect - */ - NdbThread* theThreadPtr; - friend void* runConnect(void * me); + + SocketClient *m_socket_client; protected: - /** - * Error reporting from connect thread(s) - */ - void reportThreadError(NodeId nodeId, - TransporterError errorCode); Uint32 getErrorCount(); - TransporterError getThreadError(); - void resetThreadError(); - TransporterError _threadError; - Uint32 _timeOutMillis; - Uint32 _errorCount; - -protected: - NdbMutex* theMutexPtr; - bool _connected; // Are we connected - bool _connecting; // Connect thread is running - bool _disconnecting; // We are disconnecting - - void * callbackObj; + Uint32 m_errorCount; + Uint32 m_timeOutMillis; + +protected: + bool m_connected; // Are we connected + + TransporterRegistry &m_transporter_registry; + void *get_callback_obj() { return m_transporter_registry.callbackObj; }; + void report_disconnect(int err){m_transporter_registry.report_disconnect(remoteNodeId,err);}; + void report_error(enum TransporterError err){reportError(get_callback_obj(),remoteNodeId,err);}; }; inline bool Transporter::isConnected() const { - return _connected; + return m_connected; } inline @@ -138,42 +146,17 @@ Transporter::getRemoteNodeId() const { return remoteNodeId; } -inline -void -Transporter::reportThreadError(NodeId nodeId, TransporterError errorCode) -{ -#if 0 - ndbout_c("Transporter::reportThreadError (NodeId: %d, Error code: %d)", - nodeId, errorCode); -#endif - _threadError = errorCode; - _errorCount++; -} - inline -TransporterError -Transporter::getThreadError(){ - return _threadError; +NodeId +Transporter::getLocalNodeId() const { + return remoteNodeId; } inline Uint32 Transporter::getErrorCount() { - return _errorCount; -} - -inline -void -Transporter::resetThreadError() -{ - _threadError = TE_NO_ERROR; -} - -inline -void -Transporter::setCallbackObject(void * callback) { - callbackObj = callback; + return m_errorCount; } #endif // Define of Transporter_H diff --git a/ndb/src/common/transporter/TransporterRegistry.cpp b/ndb/src/common/transporter/TransporterRegistry.cpp index 3f98eeed89e..01f1f74f053 100644 --- a/ndb/src/common/transporter/TransporterRegistry.cpp +++ b/ndb/src/common/transporter/TransporterRegistry.cpp @@ -16,10 +16,11 @@ #include <ndb_global.h> -#include "TransporterRegistry.hpp" +#include <TransporterRegistry.hpp> #include "TransporterInternalDefinitions.hpp" #include "Transporter.hpp" +#include <SocketAuthenticator.hpp> #ifdef NDB_TCP_TRANSPORTER #include "TCP_Transporter.hpp" @@ -42,20 +43,67 @@ #include "NdbOut.hpp" #include <NdbSleep.h> #include <NdbTick.h> -#define STEPPING 1 +#include <InputStream.hpp> +#include <OutputStream.hpp> + +SocketServer::Session * TransporterService::newSession(NDB_SOCKET_TYPE sockfd) +{ + if (m_auth && !m_auth->server_authenticate(sockfd)){ + NDB_CLOSE_SOCKET(sockfd); + return 0; + } + + { + // read node id from client + int nodeId; + SocketInputStream s_input(sockfd); + char buf[256]; + if (s_input.gets(buf, 256) == 0) { + NDB_CLOSE_SOCKET(sockfd); + return 0; + } + if (sscanf(buf, "%d", &nodeId) != 1) { + NDB_CLOSE_SOCKET(sockfd); + return 0; + } + + //check that nodeid is valid and that there is an allocated transporter + if ( nodeId < 0 || nodeId >= m_transporter_registry->maxTransporters) { + NDB_CLOSE_SOCKET(sockfd); + return 0; + } + if (m_transporter_registry->theTransporters[nodeId] == 0) { + NDB_CLOSE_SOCKET(sockfd); + return 0; + } + + //check that the transporter should be connected + if (m_transporter_registry->performStates[nodeId] != TransporterRegistry::CONNECTING) { + NDB_CLOSE_SOCKET(sockfd); + return 0; + } + + Transporter *t= m_transporter_registry->theTransporters[nodeId]; + + // send info about own id (just as response to acknowledge connection) + SocketOutputStream s_output(sockfd); + s_output.println("%d", t->getLocalNodeId()); + + // setup transporter (transporter responsible for closing sockfd) + t->connect_server(sockfd); + } + + return 0; +} TransporterRegistry::TransporterRegistry(void * callback, unsigned _maxTransporters, unsigned sizeOfLongSignalMemory) { + m_transporter_service= 0; nodeIdSpecified = false; maxTransporters = _maxTransporters; sendCounter = 1; - m_ccCount = 0; - m_ccIndex = 0; - m_ccStep = STEPPING; - m_ccReady = false; - m_nTransportersPerformConnect=0; callbackObj=callback; @@ -82,7 +130,7 @@ TransporterRegistry::TransporterRegistry(void * callback, theSHMTransporters[i] = NULL; theOSETransporters[i] = NULL; theTransporters[i] = NULL; - performStates[i] = PerformNothing; + performStates[i] = DISCONNECTED; ioStates[i] = NoHalt; } theOSEReceiver = 0; @@ -152,15 +200,15 @@ TransporterRegistry::createTransporter(TCP_TransporterConfiguration *config) { if(theTransporters[config->remoteNodeId] != NULL) return false; - - - TCP_Transporter * t = new TCP_Transporter(config->sendBufferSize, - config->maxReceiveSize, - config->port, - config->remoteHostName, + + TCP_Transporter * t = new TCP_Transporter(*this, + config->sendBufferSize, + config->maxReceiveSize, config->localHostName, - config->remoteNodeId, + config->remoteHostName, + config->port, localNodeId, + config->remoteNodeId, config->byteOrder, config->compression, config->checksum, @@ -172,13 +220,11 @@ TransporterRegistry::createTransporter(TCP_TransporterConfiguration *config) { return false; } - t->setCallbackObject(callbackObj); - // Put the transporter in the transporter arrays theTCPTransporters[nTCPTransporters] = t; theTransporters[t->getRemoteNodeId()] = t; theTransporterTypes[t->getRemoteNodeId()] = tt_TCP_TRANSPORTER; - performStates[t->getRemoteNodeId()] = PerformNothing; + performStates[t->getRemoteNodeId()] = DISCONNECTED; nTransporters++; nTCPTransporters++; @@ -228,12 +274,11 @@ TransporterRegistry::createTransporter(OSE_TransporterConfiguration *conf) { delete t; return false; } - t->setCallbackObject(callbackObj); // Put the transporter in the transporter arrays theOSETransporters[nOSETransporters] = t; theTransporters[t->getRemoteNodeId()] = t; theTransporterTypes[t->getRemoteNodeId()] = tt_OSE_TRANSPORTER; - performStates[t->getRemoteNodeId()] = PerformNothing; + performStates[t->getRemoteNodeId()] = DISCONNECTED; nTransporters++; nOSETransporters++; @@ -279,12 +324,11 @@ TransporterRegistry::createTransporter(SCI_TransporterConfiguration *config) { delete t; return false; } - t->setCallbackObject(callbackObj); // Put the transporter in the transporter arrays theSCITransporters[nSCITransporters] = t; theTransporters[t->getRemoteNodeId()] = t; theTransporterTypes[t->getRemoteNodeId()] = tt_SCI_TRANSPORTER; - performStates[t->getRemoteNodeId()] = PerformNothing; + performStates[t->getRemoteNodeId()] = DISCONNECTED; nTransporters++; nSCITransporters++; @@ -307,13 +351,17 @@ TransporterRegistry::createTransporter(SHM_TransporterConfiguration *config) { if(theTransporters[config->remoteNodeId] != NULL) return false; - SHM_Transporter * t = new SHM_Transporter(config->localNodeId, + SHM_Transporter * t = new SHM_Transporter(*this, + "localhost", + "localhost", + config->port, + localNodeId, config->remoteNodeId, - config->shmKey, - config->shmSize, config->compression, config->checksum, - config->signalId + config->signalId, + config->shmKey, + config->shmSize ); if (t == NULL) return false; @@ -321,12 +369,11 @@ TransporterRegistry::createTransporter(SHM_TransporterConfiguration *config) { delete t; return false; } - t->setCallbackObject(callbackObj); // Put the transporter in the transporter arrays theSHMTransporters[nSHMTransporters] = t; theTransporters[t->getRemoteNodeId()] = t; theTransporterTypes[t->getRemoteNodeId()] = tt_SHM_TRANSPORTER; - performStates[t->getRemoteNodeId()] = PerformNothing; + performStates[t->getRemoteNodeId()] = DISCONNECTED; nTransporters++; nSHMTransporters++; @@ -781,7 +828,7 @@ TransporterRegistry::performReceive(){ TCP_Transporter *t = theTCPTransporters[i]; const NodeId nodeId = t->getRemoteNodeId(); const NDB_SOCKET_TYPE socket = t->getSocket(); - if(performStates[nodeId] == PerformIO){ + if(is_connected(nodeId)){ if(t->isConnected() && FD_ISSET(socket, &tcpReadset)) { const int receiveSize = t->doReceive(); if(receiveSize > 0){ @@ -804,7 +851,7 @@ TransporterRegistry::performReceive(){ checkJobBuffer(); SCI_Transporter *t = theSCITransporters[i]; const NodeId nodeId = t->getRemoteNodeId(); - if(performStates[nodeId] == PerformIO){ + if(is_connected(nodeId)){ if(t->isConnected() && t->checkConnected()){ Uint32 * readPtr, * eodPtr; t->getReceivePtr(&readPtr, &eodPtr); @@ -819,7 +866,7 @@ TransporterRegistry::performReceive(){ checkJobBuffer(); SHM_Transporter *t = theSHMTransporters[i]; const NodeId nodeId = t->getRemoteNodeId(); - if(performStates[nodeId] == PerformIO){ + if(is_connected(nodeId)){ if(t->isConnected() && t->checkConnected()){ Uint32 * readPtr, * eodPtr; t->getReceivePtr(&readPtr, &eodPtr); @@ -834,13 +881,13 @@ TransporterRegistry::performReceive(){ static int x = 0; void TransporterRegistry::performSend(){ - + int i; sendCounter = 1; #ifdef NDB_OSE_TRANSPORTER for (int i = 0; i < nOSETransporters; i++){ OSE_Transporter *t = theOSETransporters[i]; - if((performStates[t->getRemoteNodeId()] == PerformIO) && + if((is_connected(t->getRemoteNodeId()) && (t->isConnected())) { t->doSend(); }//if @@ -858,7 +905,7 @@ TransporterRegistry::performSend(){ FD_ZERO(&writeset); // Prepare for sending and receiving - for (int i = 0; i < nTCPTransporters; i++) { + for (i = 0; i < nTCPTransporters; i++) { TCP_Transporter * t = theTCPTransporters[i]; // If the transporter is connected @@ -883,11 +930,11 @@ TransporterRegistry::performSend(){ if (tmp == 0) { return; }//if - for (int i = 0; i < nTCPTransporters; i++) { + for (i = 0; i < nTCPTransporters; i++) { TCP_Transporter *t = theTCPTransporters[i]; const NodeId nodeId = t->getRemoteNodeId(); const int socket = t->getSocket(); - if(performStates[nodeId] == PerformIO){ + if(is_connected(nodeId)){ if(t->isConnected() && FD_ISSET(socket, &writeset)) { t->doSend(); }//if @@ -896,21 +943,21 @@ TransporterRegistry::performSend(){ } #endif #ifdef NDB_TCP_TRANSPORTER - for (int i = x; i < nTCPTransporters; i++) { + for (i = x; i < nTCPTransporters; i++) { TCP_Transporter *t = theTCPTransporters[i]; if (t && (t->hasDataToSend()) && (t->isConnected()) && - (performStates[t->getRemoteNodeId()] == PerformIO)) { + (is_connected(t->getRemoteNodeId()))) { t->doSend(); }//if }//for - for (int i = 0; i < x && i < nTCPTransporters; i++) { + for (i = 0; i < x && i < nTCPTransporters; i++) { TCP_Transporter *t = theTCPTransporters[i]; if (t && (t->hasDataToSend()) && (t->isConnected()) && - (performStates[t->getRemoteNodeId()] == PerformIO)) { + (is_connected(t->getRemoteNodeId()))) { t->doSend(); }//if }//for @@ -921,11 +968,11 @@ TransporterRegistry::performSend(){ #ifdef NDB_SCI_TRANSPORTER //scroll through the SCI transporters, // get each transporter, check if connected, send data - for (int i=0; i<nSCITransporters; i++) { + for (i=0; i<nSCITransporters; i++) { SCI_Transporter *t = theSCITransporters[i]; const NodeId nodeId = t->getRemoteNodeId(); - if(performStates[nodeId] == PerformIO){ + if(is_connected(nodeId)){ if(t->isConnected() && t->hasDataToSend()) { t->doSend(); } //if @@ -961,70 +1008,212 @@ TransporterRegistry::printState(){ } #endif -PerformState -TransporterRegistry::performState(NodeId nodeId) { - return performStates[nodeId]; +IOState +TransporterRegistry::ioState(NodeId nodeId) { + return ioStates[nodeId]; } -#ifdef DEBUG_TRANSPORTER -const char * -performStateString(PerformState state){ - switch(state){ - case PerformNothing: - return "PerformNothing"; - break; - case PerformIO: - return "PerformIO"; +void +TransporterRegistry::setIOState(NodeId nodeId, IOState state) { + DEBUG("TransporterRegistry::setIOState(" + << nodeId << ", " << state << ")"); + ioStates[nodeId] = state; +} + +static void * +run_start_clients_C(void * me) +{ + ((TransporterRegistry*) me)->start_clients_thread(); + NdbThread_Exit(0); + return me; +} + +// Run by kernel thread +void +TransporterRegistry::do_connect(NodeId node_id) +{ + PerformState &curr_state = performStates[node_id]; + switch(curr_state){ + case DISCONNECTED: break; - case PerformConnect: - return "PerformConnect"; + case CONNECTED: + return; + case CONNECTING: + return; + case DISCONNECTING: break; - case PerformDisconnect: - return "PerformDisconnect"; + } + curr_state= CONNECTING; +} +void +TransporterRegistry::do_disconnect(NodeId node_id) +{ + PerformState &curr_state = performStates[node_id]; + switch(curr_state){ + case DISCONNECTED: + return; + case CONNECTED: break; - case RemoveTransporter: - return "RemoveTransporter"; + case CONNECTING: break; + case DISCONNECTING: + return; } - return "Unknown"; + curr_state= DISCONNECTING; } -#endif void -TransporterRegistry::setPerformState(NodeId nodeId, PerformState state) { - DEBUG("TransporterRegistry::setPerformState(" - << nodeId << ", " << performStateString(state) << ")"); - - performStates[nodeId] = state; +TransporterRegistry::report_connect(NodeId node_id) +{ + performStates[node_id] = CONNECTED; + reportConnect(callbackObj, node_id); +} + +void +TransporterRegistry::report_disconnect(NodeId node_id, int errnum) +{ + performStates[node_id] = DISCONNECTED; + reportDisconnect(callbackObj, node_id, errnum); } void -TransporterRegistry::setPerformState(PerformState state) { - int count = 0; - int index = 0; - while(count < nTransporters){ - if(theTransporters[index] != 0){ - setPerformState(theTransporters[index]->getRemoteNodeId(), state); - count ++; +TransporterRegistry::update_connections() +{ + for (int i= 0, n= 0; n < nTransporters; i++){ + Transporter * t = theTransporters[i]; + if (!t) + continue; + n++; + + const NodeId nodeId = t->getRemoteNodeId(); + switch(performStates[nodeId]){ + case CONNECTED: + case DISCONNECTED: + break; + case CONNECTING: + if(t->isConnected()) + report_connect(nodeId); + break; + case DISCONNECTING: + if(!t->isConnected()) + report_disconnect(nodeId, 0); + break; } - index ++; } } -IOState -TransporterRegistry::ioState(NodeId nodeId) { - return ioStates[nodeId]; +// run as own thread +void +TransporterRegistry::start_clients_thread() +{ + while (m_run_start_clients_thread) { + NdbSleep_MilliSleep(100); + for (int i= 0, n= 0; n < nTransporters && m_run_start_clients_thread; i++){ + Transporter * t = theTransporters[i]; + if (!t) + continue; + n++; + + const NodeId nodeId = t->getRemoteNodeId(); + switch(performStates[nodeId]){ + case CONNECTING: + if(!t->isConnected() && !t->isServer) + t->connect_client(); + break; + case DISCONNECTING: + if(t->isConnected()) + t->doDisconnect(); + break; + default: + break; + } + } + } } -void -TransporterRegistry::setIOState(NodeId nodeId, IOState state) { - DEBUG("TransporterRegistry::setIOState(" - << nodeId << ", " << state << ")"); - ioStates[nodeId] = state; +bool +TransporterRegistry::start_clients() +{ + m_run_start_clients_thread= true; + m_start_clients_thread= NdbThread_Create(run_start_clients_C, + (void**)this, + 32768, + "ndb_start_clients", + NDB_THREAD_PRIO_LOW); + if (m_start_clients_thread == 0) { + m_run_start_clients_thread= false; + return false; + } + return true; +} + +bool +TransporterRegistry::stop_clients() +{ + if (m_start_clients_thread) { + m_run_start_clients_thread= false; + void* status; + int r= NdbThread_WaitFor(m_start_clients_thread, &status); + NdbThread_Destroy(&m_start_clients_thread); + } + return true; +} + +bool +TransporterRegistry::start_service(SocketServer& socket_server) +{ +#if 0 + for (int i= 0, n= 0; n < nTransporters; i++){ + Transporter * t = theTransporters[i]; + if (!t) + continue; + n++; + if (t->isServer) { + t->m_service = new TransporterService(new SocketAuthSimple("ndbd passwd")); + if(!socket_server.setup(t->m_service, t->m_r_port, 0)) + { + ndbout_c("Unable to setup transporter service port: %d!\n" + "Please check if the port is already used,\n" + "(perhaps a mgmtsrvrserver is already running)", + m_service_port); + delete t->m_service; + return false; + } + } + } +#endif + + if (m_service_port != 0) { + + m_transporter_service = new TransporterService(new SocketAuthSimple("ndbd", "ndbd passwd")); + + if (nodeIdSpecified != true) { + ndbout_c("TransporterRegistry::startReceiving: localNodeId not specified"); + return false; + } + + //m_interface_name = "ndbd"; + m_interface_name = 0; + + if(!socket_server.setup(m_transporter_service, m_service_port, m_interface_name)) + { + ndbout_c("Unable to setup transporter service port: %d!\n" + "Please check if the port is already used,\n" + "(perhaps a mgmtsrvrserver is already running)", + m_service_port); + delete m_transporter_service; + return false; + } + m_transporter_service->setTransporterRegistry(this); + } else + m_transporter_service= 0; + + return true; } void -TransporterRegistry::startReceiving(){ +TransporterRegistry::startReceiving() +{ #ifdef NDB_OSE_TRANSPORTER if(theOSEReceiver != NULL){ theOSEReceiver->createPhantom(); @@ -1081,99 +1270,6 @@ TransporterRegistry::stopSending(){ #endif } -/** - * The old implementation did not scale with a large - * number of nodes. (Watchdog killed NDB because - * it took too long time to allocated threads in - * doConnect. - * - * The new implementation only checks the connection - * for a number of transporters (STEPPING), until to - * the point where all transporters has executed - * doConnect once. After that, the behaviour is as - * in the old implemenation, i.e, checking the connection - * for all transporters. - * @todo: instead of STEPPING, maybe we should only - * allow checkConnections to execute for a certain - * time that somehow factors in heartbeat times and - * watchdog times. - * - */ - -void -TransporterRegistry::checkConnections(){ - if(m_ccStep > nTransporters) - m_ccStep = nTransporters; - - while(m_ccCount < m_ccStep){ - if(theTransporters[m_ccIndex] != 0){ - Transporter * t = theTransporters[m_ccIndex]; - const NodeId nodeId = t->getRemoteNodeId(); - if(t->getThreadError() != 0) { - reportError(callbackObj, nodeId, t->getThreadError()); - t->resetThreadError(); - } - - switch(performStates[nodeId]){ - case PerformConnect: - if(!t->isConnected()){ - t->doConnect(); - if(m_nTransportersPerformConnect!=nTransporters) - m_nTransportersPerformConnect++; - - } else { - performStates[nodeId] = PerformIO; - reportConnect(callbackObj, nodeId); - } - break; - case PerformDisconnect: - { - bool wasConnected = t->isConnected(); - t->doDisconnect(); - performStates[nodeId] = PerformNothing; - if(wasConnected){ - reportDisconnect(callbackObj, nodeId,0); - } - } - break; - case RemoveTransporter: - removeTransporter(nodeId); - break; - case PerformNothing: - case PerformIO: - break; - } - m_ccCount ++; - } - m_ccIndex ++; - } - - if(!m_ccReady) { - if(m_ccCount < nTransporters) { - if(nTransporters - m_ccStep < STEPPING) - m_ccStep += nTransporters-m_ccStep; - else - m_ccStep += STEPPING; - - // ndbout_c("count %d step %d ", m_ccCount, m_ccStep); - } - else { - m_ccCount = 0; - m_ccIndex = 0; - m_ccStep = STEPPING; - // ndbout_c("count %d step %d ", m_ccCount, m_ccStep); - } - } - if((nTransporters == m_nTransportersPerformConnect) || m_ccReady) { - m_ccReady = true; - m_ccCount = 0; - m_ccIndex = 0; - m_ccStep = nTransporters; - // ndbout_c("alla count %d step %d ", m_ccCount, m_ccStep); - } - -}//TransporterRegistry::checkConnections() - NdbOut & operator <<(NdbOut & out, SignalHeader & sh){ out << "-- Signal Header --" << endl; out << "theLength: " << sh.theLength << endl; diff --git a/ndb/src/common/util/BaseString.cpp b/ndb/src/common/util/BaseString.cpp index d15249adf72..8b7df485f77 100644 --- a/ndb/src/common/util/BaseString.cpp +++ b/ndb/src/common/util/BaseString.cpp @@ -412,3 +412,6 @@ int main() } #endif + +template class Vector<char *>; +template class Vector<BaseString>; diff --git a/ndb/src/common/util/ConfigValues.cpp b/ndb/src/common/util/ConfigValues.cpp index 7fc99bc526c..8a14882550c 100644 --- a/ndb/src/common/util/ConfigValues.cpp +++ b/ndb/src/common/util/ConfigValues.cpp @@ -105,19 +105,19 @@ ConfigValues::getByPos(Uint32 pos, Entry * result) const { Uint64 * ConfigValues::get64(Uint32 index) const { assert(index < m_int64Count); - const Uint32 * data = m_values + (m_size << 1); + const Uint32 * data = m_values + (m_size << 1); Uint64 * ptr = (Uint64*)data; - ptr += index; + ptr += index; return ptr; } char ** ConfigValues::getString(Uint32 index) const { assert(index < m_stringCount); - const Uint32 * data = m_values + (m_size << 1); - char * ptr = (char*)data; + const Uint32 * data = m_values + (m_size << 1); + char * ptr = (char*)data; ptr += m_dataSize; - ptr -= (index * sizeof(char *)); + ptr -= (index * sizeof(char *)); return (char**)ptr; } @@ -261,9 +261,9 @@ directory(Uint32 sz){ ConfigValuesFactory::ConfigValuesFactory(Uint32 keys, Uint32 data){ m_sectionCounter = (1 << KP_SECTION_SHIFT); m_freeKeys = directory(keys); - m_freeData = data; + m_freeData = (data + 7) & ~7; m_currentSection = 0; - m_cfg = create(m_freeKeys, data); + m_cfg = create(m_freeKeys, m_freeData); } ConfigValuesFactory::ConfigValuesFactory(ConfigValues * cfg){ @@ -316,7 +316,8 @@ ConfigValuesFactory::expand(Uint32 fk, Uint32 fs){ m_freeKeys = (m_freeKeys >= fk ? m_cfg->m_size : fk + m_cfg->m_size); m_freeData = (m_freeData >= fs ? m_cfg->m_dataSize : fs + m_cfg->m_dataSize); m_freeKeys = directory(m_freeKeys); - + m_freeData = (m_freeData + 7) & ~7; + ConfigValues * m_tmp = m_cfg; m_cfg = create(m_freeKeys, m_freeData); put(* m_tmp); @@ -333,6 +334,7 @@ ConfigValuesFactory::shrink(){ m_freeKeys = m_cfg->m_size - m_freeKeys; m_freeData = m_cfg->m_dataSize - m_freeData; m_freeKeys = directory(m_freeKeys); + m_freeData = (m_freeData + 7) & ~7; ConfigValues * m_tmp = m_cfg; m_cfg = create(m_freeKeys, m_freeData); @@ -462,7 +464,7 @@ ConfigValuesFactory::put(const ConfigValues::Entry & entry){ case ConfigValues::StringType:{ Uint32 index = m_cfg->m_stringCount++; m_cfg->m_values[pos+1] = index; - char ** ref = m_cfg->getString(index); + char ** ref = m_cfg->getString(index); * ref = strdup(entry.m_string ? entry.m_string : ""); m_freeKeys--; m_freeData -= sizeof(char *); @@ -578,11 +580,11 @@ ConfigValues::getPackedSize() const { Uint32 ConfigValues::pack(void * _dst, Uint32 _len) const { - + Uint32 i; char * dst = (char*)_dst; memcpy(dst, Magic, sizeof(Magic)); dst += sizeof(Magic); - for(Uint32 i = 0; i < 2 * m_size; i += 2){ + for(i = 0; i < 2 * m_size; i += 2){ Uint32 key = m_values[i]; Uint32 val = m_values[i+1]; if(key != CFV_KEY_FREE){ @@ -621,7 +623,7 @@ ConfigValues::pack(void * _dst, Uint32 _len) const { const Uint32 * sum = (Uint32*)_dst; const Uint32 len = ((Uint32*)dst) - sum; Uint32 chk = 0; - for(Uint32 i = 0; i<len; i++){ + for(i = 0; i<len; i++){ chk ^= htonl(sum[i]); } diff --git a/ndb/src/common/util/Makefile.am b/ndb/src/common/util/Makefile.am index 59d9775b8e3..678added01e 100644 --- a/ndb/src/common/util/Makefile.am +++ b/ndb/src/common/util/Makefile.am @@ -3,7 +3,8 @@ noinst_LTLIBRARIES = libgeneral.la libgeneral_la_SOURCES = \ File.cpp md5_hash.cpp Properties.cpp socket_io.cpp \ - SimpleProperties.cpp Parser.cpp InputStream.cpp SocketServer.cpp \ + SimpleProperties.cpp Parser.cpp InputStream.cpp \ + SocketServer.cpp SocketClient.cpp SocketAuthenticator.cpp\ OutputStream.cpp NdbOut.cpp BaseString.cpp Base64.cpp \ NdbSqlUtil.cpp new.cpp \ uucode.c random.c getarg.c version.c \ diff --git a/ndb/src/common/util/NdbSqlUtil.cpp b/ndb/src/common/util/NdbSqlUtil.cpp index e34d6d18539..9d05fc7fb02 100644 --- a/ndb/src/common/util/NdbSqlUtil.cpp +++ b/ndb/src/common/util/NdbSqlUtil.cpp @@ -98,11 +98,11 @@ NdbSqlUtil::m_typeList[] = { }, { Type::Mediumint, - NULL // cmpMediumint + cmpMediumint }, { Type::Mediumunsigned, - NULL // cmpMediumunsigned + cmpMediumunsigned }, { Type::Int, @@ -130,7 +130,7 @@ NdbSqlUtil::m_typeList[] = { }, { Type::Decimal, - NULL // cmpDecimal + NULL // cmpDecimal }, { Type::Char, @@ -142,11 +142,11 @@ NdbSqlUtil::m_typeList[] = { }, { Type::Binary, - NULL // cmpBinary + cmpBinary }, { Type::Varbinary, - NULL // cmpVarbinary + cmpVarbinary }, { Type::Datetime, @@ -154,15 +154,15 @@ NdbSqlUtil::m_typeList[] = { }, { Type::Timespec, - NULL // cmpTimespec + cmpTimespec }, { Type::Blob, - NULL // cmpDatetime + cmpBlob }, { - Type::Clob, - cmpClob + Type::Text, + cmpText } }; @@ -299,9 +299,9 @@ NdbSqlUtil::cmpBlob(const Uint32* p1, const Uint32* p2, Uint32 full, Uint32 size } int -NdbSqlUtil::cmpClob(const Uint32* p1, const Uint32* p2, Uint32 full, Uint32 size) +NdbSqlUtil::cmpText(const Uint32* p1, const Uint32* p2, Uint32 full, Uint32 size) { - return cmp(Type::Clob, p1, p2, full, size); + return cmp(Type::Text, p1, p2, full, size); } #ifdef NDB_SQL_UTIL_TEST diff --git a/ndb/src/common/util/Parser.cpp b/ndb/src/common/util/Parser.cpp index 2e8120f88ce..dea128ccf66 100644 --- a/ndb/src/common/util/Parser.cpp +++ b/ndb/src/common/util/Parser.cpp @@ -347,3 +347,4 @@ ParserImpl::checkMandatory(Context* ctx, const Properties* props){ return true; } +template class Vector<const ParserRow<ParserImpl::Dummy>*>; diff --git a/ndb/src/common/util/Properties.cpp b/ndb/src/common/util/Properties.cpp index 3e41056ac18..80fb0027830 100644 --- a/ndb/src/common/util/Properties.cpp +++ b/ndb/src/common/util/Properties.cpp @@ -56,7 +56,7 @@ class PropertiesImpl { PropertiesImpl(const PropertiesImpl &); // Not implemented PropertiesImpl& operator=(const PropertiesImpl&); // Not implemented public: - PropertiesImpl(Properties *); + PropertiesImpl(Properties *, bool case_insensitive); PropertiesImpl(Properties *, const PropertiesImpl &); ~PropertiesImpl(); @@ -69,6 +69,7 @@ public: bool m_insensitive; int (* compare)(const char *s1, const char *s2); + void setCaseInsensitiveNames(bool value); void grow(int sizeToAdd); PropertyImpl * get(const char * name) const; @@ -113,9 +114,9 @@ Property::~Property(){ /** * Methods for Properties */ -Properties::Properties(){ +Properties::Properties(bool case_insensitive){ parent = 0; - impl = new PropertiesImpl(this); + impl = new PropertiesImpl(this, case_insensitive); } Properties::Properties(const Properties & org){ @@ -124,7 +125,7 @@ Properties::Properties(const Properties & org){ } Properties::Properties(const Property * anArray, int arrayLen){ - impl = new PropertiesImpl(this); + impl = new PropertiesImpl(this, false); put(anArray, arrayLen); } @@ -169,6 +170,7 @@ put(PropertiesImpl * impl, const char * name, T value, bool replace){ return tmp->put(new PropertyImpl(short_name, value)); } + bool Properties::put(const char * name, Uint32 value, bool replace){ return ::put(impl, name, value, replace); @@ -478,13 +480,12 @@ Properties::unpack(const Uint32 * buf, Uint32 bufLen){ /** * Methods for PropertiesImpl */ -PropertiesImpl::PropertiesImpl(Properties * p){ +PropertiesImpl::PropertiesImpl(Properties * p, bool case_insensitive){ this->properties = p; items = 0; size = 25; content = new PropertyImpl * [size]; - this->m_insensitive = false; - this->compare = strcmp; + setCaseInsensitiveNames(case_insensitive); } PropertiesImpl::PropertiesImpl(Properties * p, const PropertiesImpl & org){ @@ -505,6 +506,15 @@ PropertiesImpl::~PropertiesImpl(){ delete [] content; } +void +PropertiesImpl::setCaseInsensitiveNames(bool value){ + m_insensitive = value; + if(value) + compare = strcasecmp; + else + compare = strcmp; +} + void PropertiesImpl::grow(int sizeToAdd){ PropertyImpl ** newContent = new PropertyImpl * [size + sizeToAdd]; @@ -522,9 +532,11 @@ PropertiesImpl::get(const char * name) const { return 0; } - for(unsigned int i = 0; i<tmp->items; i++) + for(unsigned int i = 0; i<tmp->items; i++) { if((* compare)(tmp->content[i]->name, short_name) == 0) return tmp->content[i]; + } + return 0; } @@ -1109,14 +1121,15 @@ Properties::getCopy(const char * name, Uint32 no, Properties ** value) const { void Properties::setCaseInsensitiveNames(bool value){ - impl->m_insensitive = value; - if(value) - impl->compare = strcasecmp; - else - impl->compare = strcmp; + impl->setCaseInsensitiveNames(value); } bool Properties::getCaseInsensitiveNames() const { return impl->m_insensitive; } + +template bool put(PropertiesImpl *, const char *, Uint32, bool); +template bool put(PropertiesImpl *, const char *, Uint64, bool); +template bool put(PropertiesImpl *, const char *, const char *, bool); +template bool put(PropertiesImpl *, const char *, const Properties*, bool); diff --git a/ndb/src/common/util/SocketAuthenticator.cpp b/ndb/src/common/util/SocketAuthenticator.cpp new file mode 100644 index 00000000000..aed4db39231 --- /dev/null +++ b/ndb/src/common/util/SocketAuthenticator.cpp @@ -0,0 +1,91 @@ +/* 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 */ + + +#include <ndb_global.h> + +#include <SocketClient.hpp> +#include <SocketAuthenticator.hpp> +#include <InputStream.hpp> +#include <OutputStream.hpp> +#include <NdbOut.hpp> + +SocketAuthSimple::SocketAuthSimple(const char *username, const char *passwd) { + if (username) + m_username= strdup(username); + else + m_username= 0; + if (passwd) + m_passwd= strdup(passwd); + else + m_passwd= 0; +} + +SocketAuthSimple::~SocketAuthSimple() +{ + if (m_passwd) + free((void*)m_passwd); + if (m_username) + free((void*)m_username); +} + +bool SocketAuthSimple::client_authenticate(int sockfd) +{ + SocketOutputStream s_output(sockfd); + SocketInputStream s_input(sockfd); + + if (m_username) + s_output.println("%s", m_username); + else + s_output.println(""); + + if (m_passwd) + s_output.println("%s", m_passwd); + else + s_output.println(""); + + char buf[16]; + if (s_input.gets(buf, 16) == 0) return false; + if (strncmp("ok", buf, 2) == 0) + return true; + + return false; +} + +bool SocketAuthSimple::server_authenticate(int sockfd) +{ + + SocketOutputStream s_output(sockfd); + SocketInputStream s_input(sockfd); + + char buf[256]; + + if (s_input.gets(buf, 256) == 0) return false; + buf[255]= 0; + if (m_username) + free((void*)m_username); + m_username= strdup(buf); + + if (s_input.gets(buf, 256) == 0) return false; + buf[255]= 0; + if (m_passwd) + free((void*)m_passwd); + m_passwd= strdup(buf); + + s_output.println("ok"); + + return true; +} diff --git a/ndb/src/common/util/SocketClient.cpp b/ndb/src/common/util/SocketClient.cpp new file mode 100644 index 00000000000..ec837babc24 --- /dev/null +++ b/ndb/src/common/util/SocketClient.cpp @@ -0,0 +1,92 @@ +/* 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 */ + + +#include <ndb_global.h> +#include <NdbOut.hpp> + +#include <SocketClient.hpp> +#include <SocketAuthenticator.hpp> + +SocketClient::SocketClient(const char *server_name, unsigned short port, SocketAuthenticator *sa) +{ + m_auth= sa; + m_port= port; + m_server_name= strdup(server_name); + m_sockfd= -1; +} + +SocketClient::~SocketClient() +{ + if (m_server_name) + free(m_server_name); + if (m_sockfd >= 0) + NDB_CLOSE_SOCKET(m_sockfd); + if (m_auth) + delete m_auth; +} + +bool +SocketClient::init() +{ + if (m_sockfd >= 0) + NDB_CLOSE_SOCKET(m_sockfd); + + memset(&m_servaddr, 0, sizeof(m_servaddr)); + m_servaddr.sin_family = AF_INET; + m_servaddr.sin_port = htons(m_port); + // Convert ip address presentation format to numeric format + if (Ndb_getInAddr(&m_servaddr.sin_addr, m_server_name)) + return false; + + m_sockfd= socket(AF_INET, SOCK_STREAM, 0); + if (m_sockfd == NDB_INVALID_SOCKET) { + return false; + } + + return true; +} + +NDB_SOCKET_TYPE +SocketClient::connect() +{ + if (m_sockfd < 0) + { + if (!init()) { + ndbout << "SocketClient::connect() failed " << m_server_name << " " << m_port << endl; + return -1; + } + } + const int r = ::connect(m_sockfd, (struct sockaddr*) &m_servaddr, sizeof(m_servaddr)); + if (r == -1) { + NDB_CLOSE_SOCKET(m_sockfd); + m_sockfd= -1; + return -1; + } + + if (m_auth) { + if (!m_auth->client_authenticate(m_sockfd)) + { + NDB_CLOSE_SOCKET(m_sockfd); + m_sockfd= -1; + return -1; + } + } + NDB_SOCKET_TYPE sockfd= m_sockfd; + m_sockfd= -1; + + return sockfd; +} diff --git a/ndb/src/common/util/SocketServer.cpp b/ndb/src/common/util/SocketServer.cpp index a0ec0aaa676..0cc06a54496 100644 --- a/ndb/src/common/util/SocketServer.cpp +++ b/ndb/src/common/util/SocketServer.cpp @@ -17,7 +17,7 @@ #include <ndb_global.h> -#include "SocketServer.hpp" +#include <SocketServer.hpp> #include <NdbTCP.h> #include <NdbOut.hpp> @@ -36,10 +36,11 @@ SocketServer::SocketServer(int maxSessions) : } SocketServer::~SocketServer() { - for(unsigned i = 0; i<m_sessions.size(); i++){ + unsigned i; + for(i = 0; i<m_sessions.size(); i++){ delete m_sessions[i].m_session; } - for(unsigned i = 0; i<m_services.size(); i++){ + for(i = 0; i<m_services.size(); i++){ delete m_services[i].m_service; } } @@ -146,7 +147,6 @@ SocketServer::doAccept(){ ServiceInstance & si = m_services[i]; if(FD_ISSET(si.m_socket, &readSet)){ - NDB_SOCKET_TYPE childSock = accept(si.m_socket, 0, 0); if(childSock == NDB_INVALID_SOCKET){ continue; @@ -265,10 +265,11 @@ SocketServer::checkSessions(){ void SocketServer::stopSessions(bool wait){ - for(int i = m_sessions.size() - 1; i>=0; i--) + int i; + for(i = m_sessions.size() - 1; i>=0; i--) m_sessions[i].m_session->m_stop = true; - for(int i = m_services.size() - 1; i>=0; i--) + for(i = m_services.size() - 1; i>=0; i--) m_services[i].m_service->stopSessions(); if(wait){ @@ -303,3 +304,6 @@ sessionThread_C(void* _sc){ NdbThread_Exit(0); return 0; } + +template class MutexVector<SocketServer::ServiceInstance>; +template class MutexVector<SocketServer::SessionInstance>; diff --git a/ndb/src/common/util/socket_io.cpp b/ndb/src/common/util/socket_io.cpp index 97bb4863a67..b2f4ef91031 100644 --- a/ndb/src/common/util/socket_io.cpp +++ b/ndb/src/common/util/socket_io.cpp @@ -93,8 +93,8 @@ readln_socket(NDB_SOCKET_TYPE socket, int timeout_millis, FD_ZERO(&readset); FD_SET(socket, &readset); - timeout.tv_sec = 1; - timeout.tv_usec = 0; // 1 s + timeout.tv_sec = (timeout_millis / 1000); + timeout.tv_usec = (timeout_millis % 1000) * 1000; const int selectRes = select(socket + 1, &readset, 0, 0, &timeout); if(selectRes != 1){ return -1; diff --git a/ndb/src/cw/cpcd/APIService.cpp b/ndb/src/cw/cpcd/APIService.cpp index caf19ddba0e..46b043c7004 100644 --- a/ndb/src/cw/cpcd/APIService.cpp +++ b/ndb/src/cw/cpcd/APIService.cpp @@ -382,3 +382,5 @@ CPCDAPISession::listProcesses(Parser_t::Context & /* unused */, m_cpcd.m_processes.unlock(); } + +template class Vector<ParserRow<CPCDAPISession> const*>; diff --git a/ndb/src/cw/cpcd/CPCD.cpp b/ndb/src/cw/cpcd/CPCD.cpp index f2878b7dea1..44db10422b9 100644 --- a/ndb/src/cw/cpcd/CPCD.cpp +++ b/ndb/src/cw/cpcd/CPCD.cpp @@ -351,8 +351,9 @@ CPCD::loadProcessList(){ sess.loadFile(); loadingProcessList = false; + size_t i; Vector<int> temporary; - for(size_t i = 0; i<m_processes.size(); i++){ + for(i = 0; i<m_processes.size(); i++){ Process * proc = m_processes[i]; proc->readPid(); if(proc->m_processType == TEMPORARY){ @@ -360,7 +361,7 @@ CPCD::loadProcessList(){ } } - for(size_t i = 0; i<temporary.size(); i++){ + for(i = 0; i<temporary.size(); i++){ RequestStatus rs; undefineProcess(&rs, temporary[i]); } @@ -430,3 +431,5 @@ CPCD::report(int id, CPCEvent::EventType t){ } m_subscribers.unlock(); } + +template class MutexVector<EventSubscriber*>; diff --git a/ndb/src/cw/cpcd/Makefile.am b/ndb/src/cw/cpcd/Makefile.am index 6345bae9bbe..1f7b0d88448 100644 --- a/ndb/src/cw/cpcd/Makefile.am +++ b/ndb/src/cw/cpcd/Makefile.am @@ -1,5 +1,5 @@ -ndbtools_PROGRAMS = ndb_cpcd +ndbbin_PROGRAMS = ndb_cpcd ndb_cpcd_SOURCES = main.cpp CPCD.cpp Process.cpp APIService.cpp Monitor.cpp common.cpp diff --git a/ndb/src/cw/cpcd/Monitor.cpp b/ndb/src/cw/cpcd/Monitor.cpp index 2935cd0a648..141de926d4d 100644 --- a/ndb/src/cw/cpcd/Monitor.cpp +++ b/ndb/src/cw/cpcd/Monitor.cpp @@ -75,3 +75,5 @@ void CPCD::Monitor::signal() { NdbCondition_Signal(m_changeCondition); } + +template class MutexVector<CPCD::Process*>; diff --git a/ndb/src/cw/cpcd/Process.cpp b/ndb/src/cw/cpcd/Process.cpp index 74426306a88..0a986f63fda 100644 --- a/ndb/src/cw/cpcd/Process.cpp +++ b/ndb/src/cw/cpcd/Process.cpp @@ -15,8 +15,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include <ndb_global.h> -#include <signal.h> - #include <BaseString.hpp> #include <InputStream.hpp> @@ -209,54 +207,50 @@ int set_ulimit(const BaseString & pair){ #ifdef HAVE_GETRLIMIT errno = 0; - do { - Vector<BaseString> list; - pair.split(list, ":"); - if(list.size() != 2){ - break; - } - - int res; - rlim_t value = RLIM_INFINITY; - if(!(list[1].trim() == "unlimited")){ - value = atoi(list[1].c_str()); - } - - struct rlimit rlp; + Vector<BaseString> list; + pair.split(list, ":"); + if(list.size() != 2){ + logger.error("Unable to process ulimit: split >%s< list.size()=%d", + pair.c_str(), list.size()); + return -1; + } + + int res; + rlim_t value = RLIM_INFINITY; + if(!(list[1].trim() == "unlimited")){ + value = atoi(list[1].c_str()); + } + + struct rlimit rlp; #define _RLIMIT_FIX(x) { res = getrlimit(x,&rlp); if(!res){ rlp.rlim_cur = value; res = setrlimit(x, &rlp); }} - - if(list[0].trim() == "c"){ - _RLIMIT_FIX(RLIMIT_CORE); - } else if(list[0] == "d"){ - _RLIMIT_FIX(RLIMIT_DATA); - } else if(list[0] == "f"){ - _RLIMIT_FIX(RLIMIT_FSIZE); - } else if(list[0] == "n"){ - _RLIMIT_FIX(RLIMIT_NOFILE); - } else if(list[0] == "s"){ - _RLIMIT_FIX(RLIMIT_STACK); - } else if(list[0] == "t"){ - _RLIMIT_FIX(RLIMIT_CPU); - } else { - errno = EINVAL; - break; - } - if(!res) - break; - - return 0; - } while(false); - logger.error("Unable to process ulimit: %s(%s)", - pair.c_str(), strerror(errno)); - return -1; -#else - return 0; // Maybe it's ok anyway... + + if(list[0].trim() == "c"){ + _RLIMIT_FIX(RLIMIT_CORE); + } else if(list[0] == "d"){ + _RLIMIT_FIX(RLIMIT_DATA); + } else if(list[0] == "f"){ + _RLIMIT_FIX(RLIMIT_FSIZE); + } else if(list[0] == "n"){ + _RLIMIT_FIX(RLIMIT_NOFILE); + } else if(list[0] == "s"){ + _RLIMIT_FIX(RLIMIT_STACK); + } else if(list[0] == "t"){ + _RLIMIT_FIX(RLIMIT_CPU); + } else { + errno = EINVAL; + } + if(res){ + logger.error("Unable to process ulimit: %s res=%d error=%d(%s)", + pair.c_str(), res, errno, strerror(errno)); + return -1; + } #endif + return 0; } void CPCD::Process::do_exec() { - + size_t i; setup_environment(m_env.c_str()); char **argv = BaseString::argify(m_path.c_str(), m_args.c_str()); @@ -272,7 +266,7 @@ CPCD::Process::do_exec() { Vector<BaseString> ulimit; m_ulimit.split(ulimit); - for(size_t i = 0; i<ulimit.size(); i++){ + for(i = 0; i<ulimit.size(); i++){ if(ulimit[i].trim().length() > 0 && set_ulimit(ulimit[i]) != 0){ _exit(1); } @@ -286,7 +280,7 @@ CPCD::Process::do_exec() { BaseString * redirects[] = { &m_stdin, &m_stdout, &m_stderr }; int fds[3]; - for(int i = 0; i<3; i++){ + for(i = 0; i<3; i++){ if(redirects[i]->empty()){ #ifndef DEBUG dup2(fd, i); @@ -319,7 +313,7 @@ CPCD::Process::do_exec() { } /* Close all filedescriptors */ - for(int i = STDERR_FILENO+1; i < getdtablesize(); i++) + for(i = STDERR_FILENO+1; i < getdtablesize(); i++) close(i); execv(m_path.c_str(), argv); diff --git a/ndb/src/cw/cpcd/main.cpp b/ndb/src/cw/cpcd/main.cpp index 11f6238d5f7..913c31de1f7 100644 --- a/ndb/src/cw/cpcd/main.cpp +++ b/ndb/src/cw/cpcd/main.cpp @@ -15,7 +15,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include <ndb_global.h> /* Needed for mkdir(2) */ -#include <signal.h> #include "CPCD.hpp" #include "APIService.hpp" diff --git a/ndb/src/kernel/Makefile.am b/ndb/src/kernel/Makefile.am index b2aa5f2e074..60284f6a369 100644 --- a/ndb/src/kernel/Makefile.am +++ b/ndb/src/kernel/Makefile.am @@ -4,7 +4,7 @@ include $(top_srcdir)/ndb/config/common.mk.am ndbbin_PROGRAMS = ndbd -ndbd_SOURCES = Main.cpp SimBlockList.cpp +ndbd_SOURCES = main.cpp SimBlockList.cpp include $(top_srcdir)/ndb/config/type_kernel.mk.am diff --git a/ndb/src/kernel/blocks/ERROR_codes.txt b/ndb/src/kernel/blocks/ERROR_codes.txt index 92dbfd067f7..af575de4f62 100644 --- a/ndb/src/kernel/blocks/ERROR_codes.txt +++ b/ndb/src/kernel/blocks/ERROR_codes.txt @@ -3,7 +3,7 @@ Next NDBCNTR 1000 Next NDBFS 2000 Next DBACC 3001 Next DBTUP 4007 -Next DBLQH 5036 +Next DBLQH 5040 Next DBDICT 6006 Next DBDIH 7173 Next DBTC 8035 @@ -190,6 +190,10 @@ Delay execution of ABORTREQ signal 2 seconds to generate time-out. 5035: Delay ACC_CONTOPCONT +5038: Drop LQHKEYREQ + set 5039 +5039: Drop ABORT + set 5003 + + ERROR CODES FOR TESTING TIME-OUT HANDLING IN DBTC ------------------------------------------------- 8040: diff --git a/ndb/src/kernel/blocks/backup/Backup.cpp b/ndb/src/kernel/blocks/backup/Backup.cpp index 4342a9d6d94..52a543dbcdc 100644 --- a/ndb/src/kernel/blocks/backup/Backup.cpp +++ b/ndb/src/kernel/blocks/backup/Backup.cpp @@ -3332,7 +3332,8 @@ Backup::execBACKUP_FRAGMENT_REQ(Signal* signal) req->transId1 = 0; req->transId2 = (BACKUP << 20) + (getOwnNodeId() << 8); - for(unsigned int i = 0; i<parallelism; i++) { + Uint32 i; + for(i = 0; i<parallelism; i++) { jam(); req->clientOpPtr[i] = filePtr.i; }//for @@ -3350,7 +3351,7 @@ Backup::execBACKUP_FRAGMENT_REQ(Signal* signal) signal->theData[7] = 0; Uint32 dataPos = 8; - for(Uint32 i = 0; i<table.noOfAttributes; i++) { + for(i = 0; i<table.noOfAttributes; i++) { jam(); AttributePtr attr; table.attributes.getPtr(attr, i); diff --git a/ndb/src/kernel/blocks/backup/Backup.hpp b/ndb/src/kernel/blocks/backup/Backup.hpp index 77669e759d3..1e2100251be 100644 --- a/ndb/src/kernel/blocks/backup/Backup.hpp +++ b/ndb/src/kernel/blocks/backup/Backup.hpp @@ -696,6 +696,7 @@ Uint32 * Backup::OperationRecord::newVariableKey(Uint32 sz){ attrLeft--; attrSzLeft = 0; + attrSzTotal += sz; dst = &dst_VariableData->Data[0]; dst_VariableData->Sz = htonl(sz); @@ -712,7 +713,7 @@ Backup::OperationRecord::finished(){ return false; } - attrLen[opNoDone] = attrSzTotal; + attrLen[opNoDone] = attrSzTotal + sz_FixedKeys; opNoDone++; scanStop = dst = (Uint32 *)dst_VariableData; diff --git a/ndb/src/kernel/blocks/backup/BackupInit.cpp b/ndb/src/kernel/blocks/backup/BackupInit.cpp index 36ce1857144..d8cbb36df62 100644 --- a/ndb/src/kernel/blocks/backup/BackupInit.cpp +++ b/ndb/src/kernel/blocks/backup/BackupInit.cpp @@ -213,3 +213,6 @@ Backup::~Backup() BLOCK_FUNCTIONS(Backup); +template class ArrayPool<Backup::Page32>; +template class ArrayPool<Backup::Attribute>; +template class ArrayPool<Backup::Fragment>; diff --git a/ndb/src/kernel/blocks/backup/restore/Restore.cpp b/ndb/src/kernel/blocks/backup/restore/Restore.cpp index 24d2cfbfe35..f0ca54884be 100644 --- a/ndb/src/kernel/blocks/backup/restore/Restore.cpp +++ b/ndb/src/kernel/blocks/backup/restore/Restore.cpp @@ -34,6 +34,7 @@ Uint64 Twiddle64(Uint64 in); // Byte shift 64-bit data bool BackupFile::Twiddle(const AttributeDesc* attr_desc, AttributeData* attr_data, Uint32 arraySize){ + Uint32 i; if(m_hostByteOrder) return true; @@ -47,17 +48,17 @@ BackupFile::Twiddle(const AttributeDesc* attr_desc, AttributeData* attr_data, Ui return true; case 16: - for(unsigned i = 0; i<arraySize; i++){ + for(i = 0; i<arraySize; i++){ attr_data->u_int16_value[i] = Twiddle16(attr_data->u_int16_value[i]); } return true; case 32: - for(unsigned i = 0; i<arraySize; i++){ + for(i = 0; i<arraySize; i++){ attr_data->u_int32_value[i] = Twiddle32(attr_data->u_int32_value[i]); } return true; case 64: - for(unsigned i = 0; i<arraySize; i++){ + for(i = 0; i<arraySize; i++){ attr_data->u_int64_value[i] = Twiddle64(attr_data->u_int64_value[i]); } return true; @@ -333,8 +334,8 @@ RestoreDataIterator::getNextTuple(int & res) Uint32 *buf_ptr = (Uint32*)_buf_ptr, *ptr = buf_ptr; ptr += m_currentTable->m_nullBitmaskSize; - - for(Uint32 i= 0; i < m_currentTable->m_fixedKeys.size(); i++){ + Uint32 i; + for(i= 0; i < m_currentTable->m_fixedKeys.size(); i++){ assert(ptr < buf_ptr + dataLength); const Uint32 attrId = m_currentTable->m_fixedKeys[i]->attrId; @@ -355,7 +356,7 @@ RestoreDataIterator::getNextTuple(int & res) ptr += sz; } - for(Uint32 i = 0; i < m_currentTable->m_fixedAttribs.size(); i++){ + for(i = 0; i < m_currentTable->m_fixedAttribs.size(); i++){ assert(ptr < buf_ptr + dataLength); const Uint32 attrId = m_currentTable->m_fixedAttribs[i]->attrId; @@ -377,7 +378,7 @@ RestoreDataIterator::getNextTuple(int & res) ptr += sz; } - for(Uint32 i = 0; i < m_currentTable->m_variableAttribs.size(); i++){ + for(i = 0; i < m_currentTable->m_variableAttribs.size(); i++){ const Uint32 attrId = m_currentTable->m_variableAttribs[i]->attrId; AttributeData * attr_data = m_tuple.getData(attrId); @@ -936,3 +937,8 @@ operator<<(NdbOut& ndbout, const TableS & table){ } // for return ndbout; } + +template class Vector<TableS*>; +template class Vector<AttributeS*>; +template class Vector<AttributeDesc*>; + diff --git a/ndb/src/kernel/blocks/backup/restore/Restore.hpp b/ndb/src/kernel/blocks/backup/restore/Restore.hpp index e9149e38e44..5a705740c69 100644 --- a/ndb/src/kernel/blocks/backup/restore/Restore.hpp +++ b/ndb/src/kernel/blocks/backup/restore/Restore.hpp @@ -301,9 +301,10 @@ public: } ~LogEntry() { - for(Uint32 i= 0; i< m_values.size(); i++) + Uint32 i; + for(i= 0; i< m_values.size(); i++) delete m_values[i]; - for(Uint32 i= 0; i< m_values_e.size(); i++) + for(i= 0; i< m_values_e.size(); i++) delete m_values_e[i]; } Uint32 size() const { return m_values.size(); } diff --git a/ndb/src/kernel/blocks/backup/restore/main.cpp b/ndb/src/kernel/blocks/backup/restore/main.cpp index 99deeb3115c..23805173484 100644 --- a/ndb/src/kernel/blocks/backup/restore/main.cpp +++ b/ndb/src/kernel/blocks/backup/restore/main.cpp @@ -250,8 +250,8 @@ main(int argc, const char** argv) return -1; } - - for(Uint32 i= 0; i < g_consumers.size(); i++) + Uint32 i; + for(i= 0; i < g_consumers.size(); i++) { if (!g_consumers[i]->init()) { @@ -261,7 +261,7 @@ main(int argc, const char** argv) } - for(Uint32 i = 0; i<metaData.getNoOfTables(); i++) + for(i = 0; i<metaData.getNoOfTables(); i++) { if (checkSysTable(metaData[i]->getTableName())) { @@ -345,7 +345,7 @@ main(int argc, const char** argv) return -1; } logIter.validateFooter(); //not implemented - for (Uint32 i= 0; i < g_consumers.size(); i++) + for (i= 0; i < g_consumers.size(); i++) g_consumers[i]->endOfLogEntrys(); } } @@ -353,3 +353,4 @@ main(int argc, const char** argv) return 1; } // main +template class Vector<BackupConsumer*>; diff --git a/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp b/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp index 694007c8508..0f25391fccb 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() @@ -360,7 +362,7 @@ void Cmvmi::execCLOSE_COMREQ(Signal* signal) sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB); globalTransporterRegistry.setIOState(i, HaltIO); - globalTransporterRegistry.setPerformState(i, PerformDisconnect); + globalTransporterRegistry.do_disconnect(i); /** * Cancel possible event subscription @@ -388,7 +390,7 @@ void Cmvmi::execOPEN_COMREQ(Signal* signal) const Uint32 len = signal->getLength(); if(len == 2){ - globalTransporterRegistry.setPerformState(tStartingNode, PerformConnect); + globalTransporterRegistry.do_connect(tStartingNode); globalTransporterRegistry.setIOState(tStartingNode, HaltIO); //----------------------------------------------------- @@ -403,7 +405,7 @@ void Cmvmi::execOPEN_COMREQ(Signal* signal) jam(); if (i != getOwnNodeId() && getNodeInfo(i).m_type == tData2){ jam(); - globalTransporterRegistry.setPerformState(i, PerformConnect); + globalTransporterRegistry.do_connect(i); globalTransporterRegistry.setIOState(i, HaltIO); signal->theData[0] = EventReport::CommunicationOpened; @@ -454,34 +456,21 @@ void Cmvmi::execDISCONNECT_REP(Signal *signal) const NodeInfo::NodeType type = getNodeInfo(hostId).getType(); ndbrequire(type != NodeInfo::INVALID); - if (globalTransporterRegistry.performState(hostId) != PerformDisconnect) { + if(type == NodeInfo::DB || globalData.theStartLevel == NodeState::SL_STARTED){ jam(); - - // ------------------------------------------------------------------- - // We do not report the disconnection when disconnection is already ongoing. - // This reporting should be looked into but this secures that we avoid - // crashes due to too quick re-reporting of disconnection. - // ------------------------------------------------------------------- - if(type == NodeInfo::DB || globalData.theStartLevel == NodeState::SL_STARTED){ - jam(); - DisconnectRep * const rep = (DisconnectRep *)&signal->theData[0]; - rep->nodeId = hostId; - rep->err = errNo; - sendSignal(QMGR_REF, GSN_DISCONNECT_REP, signal, - DisconnectRep::SignalLength, JBA); - globalTransporterRegistry.setPerformState(hostId, PerformDisconnect); - } else if(globalData.theStartLevel == NodeState::SL_CMVMI || - globalData.theStartLevel == NodeState::SL_STARTING) { - /** - * Someone disconnected during cmvmi period - */ - if(type == NodeInfo::MGM){ - jam(); - globalTransporterRegistry.setPerformState(hostId, PerformConnect); - } else { - globalTransporterRegistry.setPerformState(hostId, PerformDisconnect); - } - } + DisconnectRep * const rep = (DisconnectRep *)&signal->theData[0]; + rep->nodeId = hostId; + rep->err = errNo; + sendSignal(QMGR_REF, GSN_DISCONNECT_REP, signal, + DisconnectRep::SignalLength, JBA); + } else if((globalData.theStartLevel == NodeState::SL_CMVMI || + globalData.theStartLevel == NodeState::SL_STARTING) + && type == NodeInfo::MGM) { + /** + * Someone disconnected during cmvmi period + */ + jam(); + globalTransporterRegistry.do_connect(hostId); } signal->theData[0] = EventReport::Disconnected; @@ -491,7 +480,6 @@ void Cmvmi::execDISCONNECT_REP(Signal *signal) void Cmvmi::execCONNECT_REP(Signal *signal){ const Uint32 hostId = signal->theData[0]; - jamEntry(); const NodeInfo::NodeType type = (NodeInfo::NodeType)getNodeInfo(hostId).m_type; @@ -520,7 +508,8 @@ void Cmvmi::execCONNECT_REP(Signal *signal){ /** * Dont allow api nodes to connect */ - globalTransporterRegistry.setPerformState(hostId, PerformDisconnect); + abort(); + globalTransporterRegistry.do_disconnect(hostId); } } @@ -754,8 +743,8 @@ Cmvmi::execSTART_ORD(Signal* signal) { */ for(unsigned int i = 1; i < MAX_NODES; i++ ){ if (getNodeInfo(i).m_type == NodeInfo::MGM){ - if(globalTransporterRegistry.performState(i) != PerformIO){ - globalTransporterRegistry.setPerformState(i, PerformConnect); + if(!globalTransporterRegistry.is_connected(i)){ + globalTransporterRegistry.do_connect(i); globalTransporterRegistry.setIOState(i, NoHalt); } } @@ -781,7 +770,7 @@ Cmvmi::execSTART_ORD(Signal* signal) { // without any connected nodes. for(unsigned int i = 1; i < MAX_NODES; i++ ){ if (i != getOwnNodeId() && getNodeInfo(i).m_type != NodeInfo::MGM){ - globalTransporterRegistry.setPerformState(i, PerformDisconnect); + globalTransporterRegistry.do_disconnect(i); globalTransporterRegistry.setIOState(i, HaltIO); } } @@ -1060,29 +1049,10 @@ Cmvmi::execDUMP_STATE_ORD(Signal* signal) if(nodeTypeStr == 0) continue; - const char* actionStr = ""; - switch (globalTransporterRegistry.performState(i)){ - case PerformNothing: - actionStr = "does nothing"; - break; - case PerformIO: - actionStr = "is connected"; - break; - case PerformConnect: - actionStr = "is trying to connect"; - break; - case PerformDisconnect: - actionStr = "is trying to disconnect"; - break; - case RemoveTransporter: - actionStr = "will be removed"; - break; - } - infoEvent("Connection to %d (%s) %s", i, nodeTypeStr, - actionStr); + globalTransporterRegistry.getPerformStateString(i)); } } @@ -1100,14 +1070,15 @@ Cmvmi::execDUMP_STATE_ORD(Signal* signal) } if (dumpState->args[0] == DumpStateOrd::CmvmiTestLongSigWithDelay) { + unsigned i; Uint32 loopCount = dumpState->args[1]; const unsigned len0 = 11; const unsigned len1 = 123; Uint32 sec0[len0]; Uint32 sec1[len1]; - for (unsigned i = 0; i < len0; i++) + for (i = 0; i < len0; i++) sec0[i] = i; - for (unsigned i = 0; i < len1; i++) + for (i = 0; i < len1; i++) sec1[i] = 16 * i; Uint32* sig = signal->getDataPtrSend(); sig[0] = reference(); @@ -1160,6 +1131,7 @@ static LinearSectionPtr g_test[3]; void Cmvmi::execTESTSIG(Signal* signal){ + Uint32 i; /** * Test of SafeCounter */ @@ -1184,14 +1156,14 @@ Cmvmi::execTESTSIG(Signal* signal){ getOwnNodeId(), true); ndbout_c("-- Fixed section --"); - for(Uint32 i = 0; i<signal->length(); i++){ + for(i = 0; i<signal->length(); i++){ fprintf(stdout, "H'0x%.8x ", signal->theData[i]); if(((i + 1) % 6) == 0) fprintf(stdout, "\n"); } fprintf(stdout, "\n"); - for(Uint32 i = 0; i<signal->header.m_noOfSections; i++){ + for(i = 0; i<signal->header.m_noOfSections; i++){ SegmentedSectionPtr ptr; ndbout_c("-- Section %d --", i); signal->getSection(ptr, i); @@ -1204,7 +1176,7 @@ Cmvmi::execTESTSIG(Signal* signal){ /** * Validate length:s */ - for(Uint32 i = 0; i<signal->header.m_noOfSections; i++){ + for(i = 0; i<signal->header.m_noOfSections; i++){ SegmentedSectionPtr ptr; signal->getSection(ptr, i); ndbrequire(ptr.p != 0); @@ -1249,7 +1221,7 @@ Cmvmi::execTESTSIG(Signal* signal){ case 4:{ LinearSectionPtr ptr[3]; const Uint32 secs = signal->getNoOfSections(); - for(Uint32 i = 0; i<secs; i++){ + for(i = 0; i<secs; i++){ SegmentedSectionPtr sptr; signal->getSection(sptr, i); ptr[i].sz = sptr.sz; @@ -1298,7 +1270,7 @@ Cmvmi::execTESTSIG(Signal* signal){ case 8:{ LinearSectionPtr ptr[3]; const Uint32 secs = signal->getNoOfSections(); - for(Uint32 i = 0; i<secs; i++){ + for(i = 0; i<secs; i++){ SegmentedSectionPtr sptr; signal->getSection(sptr, i); ptr[i].sz = sptr.sz; @@ -1332,7 +1304,7 @@ Cmvmi::execTESTSIG(Signal* signal){ sendNextLinearFragment(signal, fragSend); } - for(Uint32 i = 0; i<secs; i++){ + for(i = 0; i<secs; i++){ delete[] ptr[i].p; } break; @@ -1364,7 +1336,7 @@ Cmvmi::execTESTSIG(Signal* signal){ const Uint32 secs = signal->getNoOfSections(); memset(g_test, 0, sizeof(g_test)); - for(Uint32 i = 0; i<secs; i++){ + for(i = 0; i<secs; i++){ SegmentedSectionPtr sptr; signal->getSection(sptr, i); g_test[i].sz = sptr.sz; @@ -1408,7 +1380,7 @@ Cmvmi::execTESTSIG(Signal* signal){ case 14:{ Uint32 count = signal->theData[8]; signal->theData[10] = count * rg.m_nodes.count(); - for(Uint32 i = 0; i<count; i++){ + for(i = 0; i<count; i++){ sendSignal(rg, GSN_TESTSIG, signal, signal->length(), JBB); } return; diff --git a/ndb/src/kernel/blocks/dbacc/Dbacc.hpp b/ndb/src/kernel/blocks/dbacc/Dbacc.hpp index 6ba2d083e58..cc3e646f219 100644 --- a/ndb/src/kernel/blocks/dbacc/Dbacc.hpp +++ b/ndb/src/kernel/blocks/dbacc/Dbacc.hpp @@ -218,6 +218,7 @@ ndbout << "Ptr: " << ptr.p->word32 << " \tIndex: " << tmp_string << " \tValue: " #define ZREL_FRAG 6 #define ZREL_DIR 7 #define ZREPORT_MEMORY_USAGE 8 +#define ZLCP_OP_WRITE_RT_BREAK 9 /* ------------------------------------------------------------------------- */ /* ERROR CODES */ @@ -1190,6 +1191,8 @@ private: void zpagesize_error(const char* where); void reportMemoryUsage(Signal* signal, int gth); + void lcp_write_op_to_undolog(Signal* signal); + void reenable_expand_after_redo_log_exection_complete(Signal*); // Initialisation @@ -1559,7 +1562,7 @@ private: Uint32 cexcPrevforward; Uint32 clocalkey[32]; Uint32 ckeys[2048]; - + Uint32 c_errorInsert3000_TableId; Uint32 cSrUndoRecords[5]; }; diff --git a/ndb/src/kernel/blocks/dbacc/DbaccInit.cpp b/ndb/src/kernel/blocks/dbacc/DbaccInit.cpp index 90e914987c3..b22fd6ce641 100644 --- a/ndb/src/kernel/blocks/dbacc/DbaccInit.cpp +++ b/ndb/src/kernel/blocks/dbacc/DbaccInit.cpp @@ -94,7 +94,8 @@ void Dbacc::initRecords() page8 = (Page8*)allocRecord("Page8", sizeof(Page8), - cpagesize); + cpagesize, + false); rootfragmentrec = (Rootfragmentrec*)allocRecord("Rootfragmentrec", sizeof(Rootfragmentrec), @@ -114,7 +115,8 @@ void Dbacc::initRecords() undopage = (Undopage*)allocRecord("Undopage", sizeof(Undopage), - cundopagesize); + cundopagesize, + false); // Initialize BAT for interface to file system diff --git a/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp b/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp index 933ee2cf8e1..9cfac0ad2a2 100644 --- a/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp +++ b/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp @@ -46,13 +46,17 @@ Dbacc::remainingUndoPages(){ ndbrequire(HeadPage>=TailPage); Uint32 UsedPages = HeadPage - TailPage; - Uint32 Remaining = cundopagesize - UsedPages; + Int32 Remaining = cundopagesize - UsedPages; // There can not be more than cundopagesize remaining - ndbrequire(Remaining<=cundopagesize); - + if (Remaining <= 0){ + // No more undolog, crash node + progError(__LINE__, + ERR_NO_MORE_UNDOLOG, + "There are more than 1Mbyte undolog writes outstanding"); + } return Remaining; -}//Dbacc::remainingUndoPages() +} void Dbacc::updateLastUndoPageIdWritten(Signal* signal, Uint32 aNewValue){ @@ -193,6 +197,17 @@ void Dbacc::execCONTINUEB(Signal* signal) return; } + case ZLCP_OP_WRITE_RT_BREAK: + { + operationRecPtr.i= signal->theData[1]; + fragrecptr.i= signal->theData[2]; + lcpConnectptr.i= signal->theData[3]; + ptrCheckGuard(operationRecPtr, coprecsize, operationrec); + ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec); + ptrCheckGuard(lcpConnectptr, clcpConnectsize, lcpConnectrec); + lcp_write_op_to_undolog(signal); + return; + } default: ndbrequire(false); break; @@ -742,6 +757,7 @@ void Dbacc::initialiseDirRec(Signal* signal) DirectoryarrayPtr idrDirptr; ndbrequire(cdirarraysize > 0); for (idrDirptr.i = 0; idrDirptr.i < cdirarraysize; idrDirptr.i++) { + refresh_watch_dog(); ptrAss(idrDirptr, directoryarray); for (Uint32 i = 0; i <= 255; i++) { idrDirptr.p->pagep[i] = RNIL; @@ -761,6 +777,7 @@ void Dbacc::initialiseDirRangeRec(Signal* signal) ndbrequire(cdirrangesize > 0); for (idrDirRangePtr.i = 0; idrDirRangePtr.i < cdirrangesize; idrDirRangePtr.i++) { + refresh_watch_dog(); ptrAss(idrDirRangePtr, dirRange); idrDirRangePtr.p->dirArray[0] = idrDirRangePtr.i + 1; for (Uint32 i = 1; i < 256; i++) { @@ -783,6 +800,7 @@ void Dbacc::initialiseFragRec(Signal* signal) ndbrequire(cfragmentsize > 0); for (regFragPtr.i = 0; regFragPtr.i < cfragmentsize; regFragPtr.i++) { jam(); + refresh_watch_dog(); ptrAss(regFragPtr, fragmentrec); initFragGeneral(regFragPtr); regFragPtr.p->nextfreefrag = regFragPtr.i + 1; @@ -861,6 +879,7 @@ void Dbacc::initialiseOperationRec(Signal* signal) { ndbrequire(coprecsize > 0); for (operationRecPtr.i = 0; operationRecPtr.i < coprecsize; operationRecPtr.i++) { + refresh_watch_dog(); ptrAss(operationRecPtr, operationrec); operationRecPtr.p->transactionstate = IDLE; operationRecPtr.p->operation = ZUNDEFINED_OP; @@ -883,6 +902,7 @@ void Dbacc::initialiseOverflowRec(Signal* signal) ndbrequire(coverflowrecsize > 0); for (iorOverflowRecPtr.i = 0; iorOverflowRecPtr.i < coverflowrecsize; iorOverflowRecPtr.i++) { + refresh_watch_dog(); ptrAss(iorOverflowRecPtr, overflowRecord); iorOverflowRecPtr.p->nextfreeoverrec = iorOverflowRecPtr.i + 1; }//for @@ -943,6 +963,7 @@ void Dbacc::initialiseRootfragRec(Signal* signal) { ndbrequire(crootfragmentsize > 0); for (rootfragrecptr.i = 0; rootfragrecptr.i < crootfragmentsize; rootfragrecptr.i++) { + refresh_watch_dog(); ptrAss(rootfragrecptr, rootfragmentrec); rootfragrecptr.p->nextroot = rootfragrecptr.i + 1; rootfragrecptr.p->fragmentptr[0] = RNIL; @@ -998,6 +1019,7 @@ void Dbacc::initialiseTableRec(Signal* signal) { ndbrequire(ctablesize > 0); for (tabptr.i = 0; tabptr.i < ctablesize; tabptr.i++) { + refresh_watch_dog(); ptrAss(tabptr, tabrec); for (Uint32 i = 0; i < NO_OF_FRAG_PER_NODE; i++) { tabptr.p->fragholder[i] = RNIL; @@ -2324,13 +2346,14 @@ void Dbacc::execACC_COMMITREQ(Signal* signal) fragrecptr.p->slack += operationRecPtr.p->insertDeleteLen; if (fragrecptr.p->slack > fragrecptr.p->slackCheck) { /* TIME FOR JOIN BUCKETS PROCESS */ if (fragrecptr.p->expandCounter > 0) { - if (fragrecptr.p->expandFlag == 0) { + if (fragrecptr.p->expandFlag < 2) { jam(); - fragrecptr.p->expandFlag = 1; signal->theData[0] = fragrecptr.i; signal->theData[1] = fragrecptr.p->p; signal->theData[2] = fragrecptr.p->maxp; - sendSignal(cownBlockref, GSN_SHRINKCHECK2, signal, 3, JBB); + signal->theData[3] = fragrecptr.p->expandFlag; + fragrecptr.p->expandFlag = 2; + sendSignal(cownBlockref, GSN_SHRINKCHECK2, signal, 4, JBB); }//if }//if }//if @@ -2344,7 +2367,7 @@ void Dbacc::execACC_COMMITREQ(Signal* signal) if (fragrecptr.p->slack >= (Uint32)(1 << 31)) { /* IT MEANS THAT IF SLACK < ZERO */ if (fragrecptr.p->expandFlag == 0) { jam(); - fragrecptr.p->expandFlag = 1; + fragrecptr.p->expandFlag = 2; signal->theData[0] = fragrecptr.i; signal->theData[1] = fragrecptr.p->p; signal->theData[2] = fragrecptr.p->maxp; @@ -6316,9 +6339,16 @@ Uint32 Dbacc::checkScanExpand(Signal* signal) void Dbacc::execEXPANDCHECK2(Signal* signal) { + jamEntry(); + + if(refToBlock(signal->getSendersBlockRef()) == DBLQH){ + jam(); + reenable_expand_after_redo_log_exection_complete(signal); + return; + } + DirectoryarrayPtr newDirptr; - jamEntry(); fragrecptr.i = signal->theData[0]; tresult = 0; /* 0= FALSE,1= TRUE,> ZLIMIT_OF_ERROR =ERRORCODE */ Uint32 tmp = 1; @@ -6375,6 +6405,7 @@ void Dbacc::execEXPANDCHECK2(Signal* signal) return; }//if }//if + /*--------------------------------------------------------------------------*/ /* WE START BY FINDING THE PAGE, THE PAGE INDEX AND THE PAGE DIRECTORY*/ /* OF THE NEW BUCKET WHICH SHALL RECEIVE THE ELEMENT WHICH HAVE A 1 IN*/ @@ -6428,6 +6459,7 @@ void Dbacc::execEXPANDCHECK2(Signal* signal) } else { ptrCheckGuard(expPageptr, cpagesize, page8); }//if + fragrecptr.p->expReceivePageptr = expPageptr.i; fragrecptr.p->expReceiveIndex = texpReceivedBucket & ((1 << fragrecptr.p->k) - 1); /*--------------------------------------------------------------------------*/ @@ -6455,7 +6487,7 @@ void Dbacc::execEXPANDCHECK2(Signal* signal) endofexpLab(signal); return; }//Dbacc::execEXPANDCHECK2() - + void Dbacc::endofexpLab(Signal* signal) { fragrecptr.p->p++; @@ -6478,7 +6510,7 @@ void Dbacc::endofexpLab(Signal* signal) /* IT IS STILL NECESSARY TO EXPAND THE FRAGMENT EVEN MORE. START IT FROM HERE */ /* WITHOUT WAITING FOR NEXT COMMIT ON THE FRAGMENT. */ /* --------------------------------------------------------------------------------- */ - fragrecptr.p->expandFlag = 1; + fragrecptr.p->expandFlag = 2; signal->theData[0] = fragrecptr.i; signal->theData[1] = fragrecptr.p->p; signal->theData[2] = fragrecptr.p->maxp; @@ -6487,6 +6519,47 @@ void Dbacc::endofexpLab(Signal* signal) return; }//Dbacc::endofexpLab() +void Dbacc::reenable_expand_after_redo_log_exection_complete(Signal* signal){ + + tabptr.i = signal->theData[0]; + Uint32 fragId = signal->theData[1]; + + ptrCheckGuard(tabptr, ctablesize, tabrec); + ndbrequire(getrootfragmentrec(signal, rootfragrecptr, fragId)); +#if 0 + ndbout_c("reenable expand check for table %d fragment: %d", + tabptr.i, fragId); +#endif + + for (Uint32 i = 0; i < 2; i++) { + fragrecptr.i = rootfragrecptr.p->fragmentptr[i]; + ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec); + switch(fragrecptr.p->expandFlag){ + case 0: + /** + * Hmm... this means that it's alreay has been reenabled... + */ + ndbassert(false); + continue; + case 1: + /** + * Nothing is going on start expand check + */ + case 2: + /** + * A shrink is running, do expand check anyway + * (to reset expandFlag) + */ + fragrecptr.p->expandFlag = 2; + signal->theData[0] = fragrecptr.i; + signal->theData[1] = fragrecptr.p->p; + signal->theData[2] = fragrecptr.p->maxp; + sendSignal(cownBlockref, GSN_EXPANDCHECK2, signal, 3, JBB); + break; + } + } +} + void Dbacc::execDEBUG_SIG(Signal* signal) { jamEntry(); @@ -6882,9 +6955,10 @@ void Dbacc::execSHRINKCHECK2(Signal* signal) jamEntry(); fragrecptr.i = signal->theData[0]; - tresult = 0; /* 0= FALSE,1= TRUE,> ZLIMIT_OF_ERROR =ERRORCODE */ + Uint32 oldFlag = signal->theData[3]; ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec); - fragrecptr.p->expandFlag = 0; + fragrecptr.p->expandFlag = oldFlag; + tresult = 0; /* 0= FALSE,1= TRUE,> ZLIMIT_OF_ERROR =ERRORCODE */ if (fragrecptr.p->slack <= fragrecptr.p->slackCheck) { jam(); /* TIME FOR JOIN BUCKETS PROCESS */ @@ -6965,6 +7039,7 @@ void Dbacc::execSHRINKCHECK2(Signal* signal) jam(); fragrecptr.p->p--; }//if + /*--------------------------------------------------------------------------*/ /* WE START BY FINDING THE NECESSARY INFORMATION OF THE BUCKET TO BE */ /* REMOVED WHICH WILL SEND ITS ELEMENTS TO THE RECEIVING BUCKET. */ @@ -7157,11 +7232,13 @@ void Dbacc::endofshrinkbucketLab(Signal* signal) /* SHRINKING BELOW 2^K - 1 (NOW 63). THIS WAS A BUG THAT */ /* WAS REMOVED 2000-05-12. */ /*--------------------------------------------------------------*/ - fragrecptr.p->expandFlag = 1; signal->theData[0] = fragrecptr.i; signal->theData[1] = fragrecptr.p->p; signal->theData[2] = fragrecptr.p->maxp; - sendSignal(cownBlockref, GSN_SHRINKCHECK2, signal, 3, JBB); + signal->theData[3] = fragrecptr.p->expandFlag; + ndbrequire(fragrecptr.p->expandFlag < 2); + fragrecptr.p->expandFlag = 2; + sendSignal(cownBlockref, GSN_SHRINKCHECK2, signal, 4, JBB); }//if }//if }//if @@ -7697,32 +7774,70 @@ void Dbacc::execACC_LCPREQ(Signal* signal) fragrecptr.p->lcpMaxOverDirIndex = fragrecptr.p->lastOverIndex; fragrecptr.p->createLcp = ZTRUE; operationRecPtr.i = fragrecptr.p->lockOwnersList; - while (operationRecPtr.i != RNIL) { + lcp_write_op_to_undolog(signal); +} + +void +Dbacc::lcp_write_op_to_undolog(Signal* signal) +{ + bool delay_continueb= false; + Uint32 i, j; + for (i= 0; i < 16; i++) { jam(); - ptrCheckGuard(operationRecPtr, coprecsize, operationrec); + if (remainingUndoPages() <= ZMIN_UNDO_PAGES_AT_COMMIT) { + jam(); + delay_continueb= true; + break; + } + for (j= 0; j < 32; j++) { + if (operationRecPtr.i == RNIL) { + jam(); + break; + } + jam(); + ptrCheckGuard(operationRecPtr, coprecsize, operationrec); - if ((operationRecPtr.p->operation == ZINSERT) || - (operationRecPtr.p->elementIsDisappeared == ZTRUE)){ + if ((operationRecPtr.p->operation == ZINSERT) || + (operationRecPtr.p->elementIsDisappeared == ZTRUE)){ /******************************************************************* * Only log inserts and elements that are marked as dissapeared. * All other operations update the element header and that is handled * when pages are written to disk ********************************************************************/ - undopageptr.i = (cundoposition>>ZUNDOPAGEINDEXBITS) & (cundopagesize-1); - ptrAss(undopageptr, undopage); - theadundoindex = cundoposition & ZUNDOPAGEINDEX_MASK; - tundoindex = theadundoindex + ZUNDOHEADSIZE; - - writeUndoOpInfo(signal);/* THE INFORMATION ABOUT ELEMENT HEADER, STORED*/ - /* IN OP REC, IS WRITTEN AT UNDO PAGES */ - cundoElemIndex = 0;/* DEFAULT VALUE USED BY WRITE_UNDO_HEADER SUBROTINE */ - writeUndoHeader(signal, RNIL, UndoHeader::ZOP_INFO); /* WRITE THE HEAD OF THE UNDO ELEMENT */ - checkUndoPages(signal); /* SEND UNDO PAGE TO DISK WHEN A GROUP OF */ - /* UNDO PAGES,CURRENTLY 8, IS FILLED */ - }//if + undopageptr.i = (cundoposition>>ZUNDOPAGEINDEXBITS) & (cundopagesize-1); + ptrAss(undopageptr, undopage); + theadundoindex = cundoposition & ZUNDOPAGEINDEX_MASK; + tundoindex = theadundoindex + ZUNDOHEADSIZE; - operationRecPtr.i = operationRecPtr.p->nextLockOwnerOp; - }//while + writeUndoOpInfo(signal);/* THE INFORMATION ABOUT ELEMENT HEADER, STORED*/ + /* IN OP REC, IS WRITTEN AT UNDO PAGES */ + cundoElemIndex = 0;/* DEFAULT VALUE USED BY WRITE_UNDO_HEADER SUBROTINE */ + writeUndoHeader(signal, RNIL, UndoHeader::ZOP_INFO); /* WRITE THE HEAD OF THE UNDO ELEMENT */ + checkUndoPages(signal); /* SEND UNDO PAGE TO DISK WHEN A GROUP OF */ + /* UNDO PAGES,CURRENTLY 8, IS FILLED */ + } + operationRecPtr.i = operationRecPtr.p->nextLockOwnerOp; + } + if (operationRecPtr.i == RNIL) { + jam(); + break; + } + } + if (operationRecPtr.i != RNIL) { + jam(); + signal->theData[0]= ZLCP_OP_WRITE_RT_BREAK; + signal->theData[1]= operationRecPtr.i; + signal->theData[2]= fragrecptr.i; + signal->theData[3]= lcpConnectptr.i; + if (delay_continueb) { + jam(); + sendSignalWithDelay(cownBlockref, GSN_CONTINUEB, signal, 10, 4); + } else { + jam(); + sendSignal(cownBlockref, GSN_CONTINUEB, signal, 4, JBB); + } + return; + } signal->theData[0] = fragrecptr.p->lcpLqhPtr; sendSignal(lcpConnectptr.p->lcpUserblockref, GSN_ACC_LCPSTARTED, @@ -7735,8 +7850,7 @@ void Dbacc::execACC_LCPREQ(Signal* signal) signal->theData[0] = lcpConnectptr.i; signal->theData[1] = fragrecptr.i; sendSignal(cownBlockref, GSN_ACC_SAVE_PAGES, signal, 2, JBB); - return; -}//Dbacc::execACC_LCPREQ() +} /* ******************--------------------------------------------------------------- */ /* ACC_SAVE_PAGES A GROUP OF PAGES IS ALLOCATED. THE PAGES AND OVERFLOW */ @@ -8595,12 +8709,6 @@ void Dbacc::checkUndoPages(Signal* signal) * RECORDS IN */ Uint16 nextUndoPageId = tundoPageId + 1; - if (nextUndoPageId > (clastUndoPageIdWritten + cundopagesize)){ - // No more undolog, crash node - progError(__LINE__, - ERR_NO_MORE_UNDOLOG, - "There are more than 1Mbyte undolog writes outstanding"); - } updateUndoPositionPage(signal, nextUndoPageId << ZUNDOPAGEINDEXBITS); if ((tundoPageId & (ZWRITE_UNDOPAGESIZE - 1)) == (ZWRITE_UNDOPAGESIZE - 1)) { @@ -9146,7 +9254,14 @@ void Dbacc::initFragAdd(Signal* signal, ndbrequire(req->kValue == 6); regFragPtr.p->k = req->kValue; /* TK_SIZE = 6 IN THIS VERSION */ regFragPtr.p->expandCounter = 0; - regFragPtr.p->expandFlag = 0; + + /** + * Only allow shrink during SR + * - to make sure we don't run out of pages during REDO log execution + * + * Is later restored to 0 by LQH at end of REDO log execution + */ + regFragPtr.p->expandFlag = (getNodeState().getSystemRestartInProgress()?1:0); regFragPtr.p->p = 0; regFragPtr.p->maxp = (1 << req->kValue) - 1; regFragPtr.p->minloadfactor = minLoadFactor; @@ -9199,8 +9314,8 @@ void Dbacc::initFragGeneral(FragmentrecPtr regFragPtr) for (Uint32 i = 0; i < ZWRITEPAGESIZE; i++) { regFragPtr.p->datapages[i] = RNIL; }//for - for (Uint32 i = 0; i < 4; i++) { - regFragPtr.p->longKeyPageArray[i] = RNIL; + for (Uint32 j = 0; j < 4; j++) { + regFragPtr.p->longKeyPageArray[j] = RNIL; }//for }//Dbacc::initFragGeneral() diff --git a/ndb/src/kernel/blocks/dbdict/Dbdict.cpp b/ndb/src/kernel/blocks/dbdict/Dbdict.cpp index 2ef9e721e22..7126842459e 100644 --- a/ndb/src/kernel/blocks/dbdict/Dbdict.cpp +++ b/ndb/src/kernel/blocks/dbdict/Dbdict.cpp @@ -75,7 +75,6 @@ #include <signaldata/AlterTab.hpp> #include <signaldata/CreateFragmentation.hpp> #include <signaldata/CreateTab.hpp> -#include "../dbtc/Dbtc.hpp" #include <NdbSleep.h> #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; @@ -1313,6 +1313,7 @@ void Dbdict::initTableRecords() TableRecordPtr tablePtr; while (1) { jam(); + refresh_watch_dog(); c_tableRecordPool.seize(tablePtr); if (tablePtr.i == RNIL) { jam(); @@ -1373,6 +1374,7 @@ void Dbdict::initTriggerRecords() TriggerRecordPtr triggerPtr; while (1) { jam(); + refresh_watch_dog(); c_triggerRecordPool.seize(triggerPtr); if (triggerPtr.i == RNIL) { jam(); @@ -3599,30 +3601,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); + /** + * 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; + /** - * Update table version + * Pack */ - tabPtr.p->tableVersion = tabEntry->m_tableVersion + 1; - SimplePropertiesSectionWriter w(getSectionSegmentPool()); packTableIntoPagesImpl(w, tabPtr); SegmentedSectionPtr spDataPtr; w.getPtr(spDataPtr); - + signal->setSection(spDataPtr, CreateTabReq::DICT_TAB_INFO); signal->setSection(fragDataPtr, CreateTabReq::FRAGMENTATION); @@ -3749,6 +3758,10 @@ Dbdict::createTab_reply(Signal* signal, ref->senderRef = reference(); ref->senderData = createTabPtr.p->m_senderData; ref->errorCode = createTabPtr.p->m_errorCode; + ref->masterNodeId = c_masterNodeId; + ref->status = 0; + ref->errorKey = 0; + ref->errorLine = 0; //@todo check api failed sendSignal(createTabPtr.p->m_senderRef, GSN_CREATE_TABLE_REF, signal, @@ -4252,7 +4265,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 +4652,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 +5096,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 +5140,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); } @@ -5619,7 +5660,7 @@ void Dbdict::execGET_TABINFOREQ(Signal* signal) signal->getSection(ssPtr,GetTabInfoReq::TABLE_NAME); SimplePropertiesSectionReader r0(ssPtr, getSectionSegmentPool()); r0.reset(); // undo implicit first() - if(r0.getWords((Uint32*)tableName, len)) + if(r0.getWords((Uint32*)tableName, ((len + 3)/4))) memcpy(keyRecord.tableName, tableName, len); else { jam(); @@ -5734,6 +5775,7 @@ void Dbdict::execLIST_TABLES_REQ(Signal* signal) { jamEntry(); + Uint32 i; ListTablesReq * req = (ListTablesReq*)signal->getDataPtr(); Uint32 senderRef = req->senderRef; Uint32 senderData = req->senderData; @@ -5747,7 +5789,7 @@ Dbdict::execLIST_TABLES_REQ(Signal* signal) conf->senderData = senderData; conf->counter = 0; Uint32 pos = 0; - for (Uint32 i = 0; i < c_tableRecordPool.getSize(); i++) { + for (i = 0; i < c_tableRecordPool.getSize(); i++) { TableRecordPtr tablePtr; c_tableRecordPool.getPtr(tablePtr, i); // filter @@ -5827,12 +5869,12 @@ Dbdict::execLIST_TABLES_REQ(Signal* signal) conf->counter++; pos = 0; } - Uint32 i = 0; - while (i < size) { + Uint32 k = 0; + while (k < size) { char* p = (char*)&conf->tableData[pos]; for (Uint32 j = 0; j < 4; j++) { - if (i < size) - *p++ = tablePtr.p->tableName[i++]; + if (k < size) + *p++ = tablePtr.p->tableName[k++]; else *p++ = 0; } @@ -5846,7 +5888,7 @@ Dbdict::execLIST_TABLES_REQ(Signal* signal) } } // XXX merge with above somehow - for (Uint32 i = 0; i < c_triggerRecordPool.getSize(); i++) { + for (i = 0; i < c_triggerRecordPool.getSize(); i++) { if (reqListIndexes) break; TriggerRecordPtr triggerPtr; @@ -5890,12 +5932,12 @@ Dbdict::execLIST_TABLES_REQ(Signal* signal) conf->counter++; pos = 0; } - Uint32 i = 0; - while (i < size) { + Uint32 k = 0; + while (k < size) { char* p = (char*)&conf->tableData[pos]; for (Uint32 j = 0; j < 4; j++) { - if (i < size) - *p++ = triggerPtr.p->triggerName[i++]; + if (k < size) + *p++ = triggerPtr.p->triggerName[k++]; else *p++ = 0; } @@ -6132,6 +6174,7 @@ Dbdict::createIndex_slavePrepare(Signal* signal, OpCreateIndexPtr opPtr) void Dbdict::createIndex_toCreateTable(Signal* signal, OpCreateIndexPtr opPtr) { + Uint32 k; jam(); const CreateIndxReq* const req = &opPtr.p->m_request; // signal data writer @@ -6201,7 +6244,7 @@ Dbdict::createIndex_toCreateTable(Signal* signal, OpCreateIndexPtr opPtr) } // hash index attributes must currently be in table order Uint32 prevAttrId = RNIL; - for (Uint32 k = 0; k < opPtr.p->m_attrList.sz; k++) { + for (k = 0; k < opPtr.p->m_attrList.sz; k++) { jam(); bool found = false; for (Uint32 tAttr = tablePtr.p->firstAttribute; tAttr != RNIL; ) { @@ -6212,16 +6255,6 @@ Dbdict::createIndex_toCreateTable(Signal* signal, OpCreateIndexPtr opPtr) jam(); found = true; const Uint32 a = aRec->attributeDescriptor; - bool isNullable = AttributeDescriptor::getNullable(a); - // We do not allow more than one NULLable attribute for hash index - if (isNullable && - indexPtr.p->isHashIndex() && - (opPtr.p->m_attrList.sz > 1)) { - jam(); - opPtr.p->m_errorCode = CreateIndxRef::AttributeNullable; - opPtr.p->m_errorLine = __LINE__; - return; - } if (indexPtr.p->isHashIndex()) { const Uint32 s1 = AttributeDescriptor::getSize(a); const Uint32 s2 = AttributeDescriptor::getArraySize(a); @@ -6261,7 +6294,7 @@ Dbdict::createIndex_toCreateTable(Signal* signal, OpCreateIndexPtr opPtr) // write index key attributes AttributeRecordPtr aRecPtr; c_attributeRecordPool.getPtr(aRecPtr, tablePtr.p->firstAttribute); - for (Uint32 k = 0; k < opPtr.p->m_attrList.sz; k++) { + for (k = 0; k < opPtr.p->m_attrList.sz; k++) { jam(); for (Uint32 tAttr = tablePtr.p->firstAttribute; tAttr != RNIL; ) { AttributeRecord* aRec = c_attributeRecordPool.getPtr(tAttr); 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<TableRecord> TableRecordPtr; diff --git a/ndb/src/kernel/blocks/dbdih/Dbdih.hpp b/ndb/src/kernel/blocks/dbdih/Dbdih.hpp index e029af70574..14fa262f871 100644 --- a/ndb/src/kernel/blocks/dbdih/Dbdih.hpp +++ b/ndb/src/kernel/blocks/dbdih/Dbdih.hpp @@ -269,7 +269,7 @@ public: }; struct NodeRecord { - NodeRecord() { m_nodefailSteps.clear();} + NodeRecord(); enum NodeStatus { NOT_IN_CLUSTER = 0, @@ -943,6 +943,7 @@ private: void ndbStartReqLab(Signal *, BlockReference ref); void nodeRestartStartRecConfLab(Signal *); void dihCopyCompletedLab(Signal *); + void release_connect(ConnectRecordPtr ptr); void copyTableNode(Signal *, CopyTableNode* ctn, NodeRecordPtr regNodePtr); @@ -1127,7 +1128,6 @@ private: void setAllowNodeStart(Uint32 nodeId, bool newState); bool getNodeCopyCompleted(Uint32 nodeId); void setNodeCopyCompleted(Uint32 nodeId, bool newState); - void initNodeState(NodeRecordPtr regNodePtr); bool checkNodeAlive(Uint32 nodeId); // Initialisation diff --git a/ndb/src/kernel/blocks/dbdih/DbdihInit.cpp b/ndb/src/kernel/blocks/dbdih/DbdihInit.cpp index df47237ae59..7ca45ef4b43 100644 --- a/ndb/src/kernel/blocks/dbdih/DbdihInit.cpp +++ b/ndb/src/kernel/blocks/dbdih/DbdihInit.cpp @@ -50,17 +50,18 @@ void Dbdih::initData() nodeRecord = (NodeRecord*) allocRecord("NodeRecord", sizeof(NodeRecord), MAX_NDB_NODES); - for(Uint32 i = 0; i<MAX_NDB_NODES; i++){ + Uint32 i; + for(i = 0; i<MAX_NDB_NODES; i++){ new (&nodeRecord[i]) NodeRecord(); } takeOverRecord = (TakeOverRecord*)allocRecord("TakeOverRecord", sizeof(TakeOverRecord), MAX_NDB_NODES); - for(Uint32 i = 0; i<MAX_NDB_NODES; i++) + for(i = 0; i<MAX_NDB_NODES; i++) new (&takeOverRecord[i]) TakeOverRecord(); - for(Uint32 i = 0; i<MAX_NDB_NODES; i++) + for(i = 0; i<MAX_NDB_NODES; i++) new (&takeOverRecord[i]) TakeOverRecord(); waitGCPProxyPool.setSize(ZPROXY_FILE_SIZE); @@ -254,6 +255,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..0a8abe59aed 100644 --- a/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp +++ b/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp @@ -1401,6 +1401,7 @@ void Dbdih::ndbStartReqLab(Signal* signal, BlockReference ref) void Dbdih::execREAD_NODESCONF(Signal* signal) { + unsigned i; ReadNodesConf * const readNodes = (ReadNodesConf *)&signal->theData[0]; jamEntry(); Uint32 nodeArray[MAX_NDB_NODES]; @@ -1408,9 +1409,10 @@ void Dbdih::execREAD_NODESCONF(Signal* signal) csystemnodes = readNodes->noOfNodes; cmasterNodeId = readNodes->masterNodeId; int index = 0; - for (unsigned i = 1; i < MAX_NDB_NODES; i++){ + NdbNodeBitmask tmp; tmp.assign(2, readNodes->allNodes); + for (i = 1; i < MAX_NDB_NODES; i++){ jam(); - if(NodeBitmask::get(readNodes->allNodes, i)){ + if(tmp.get(i)){ jam(); nodeArray[index] = i; if(NodeBitmask::get(readNodes->inactiveNodes, i) == false){ @@ -1420,6 +1422,32 @@ void Dbdih::execREAD_NODESCONF(Signal* signal) index++; }//if }//for + + if(cstarttype == NodeState::ST_SYSTEM_RESTART || + cstarttype == NodeState::ST_NODE_RESTART){ + + for(i = 1; i<MAX_NDB_NODES; i++){ + const Uint32 stat = Sysfile::getNodeStatus(i, SYSFILE->nodeStatus); + if(stat == Sysfile::NS_NotDefined && !tmp.get(i)){ + jam(); + continue; + } + + if(tmp.get(i) && stat != Sysfile::NS_NotDefined){ + jam(); + continue; + } + char buf[255]; + snprintf(buf, sizeof(buf), + "Illegal configuration change." + " Initial start needs to be performed " + " when changing no of storage nodes (node %d)", i); + progError(__LINE__, + ERR_INVALID_CONFIG, + buf); + } + } + ndbrequire(csystemnodes >= 1 && csystemnodes < MAX_NDB_NODES); if (cstarttype == NodeState::ST_INITIAL_START) { jam(); @@ -1534,11 +1562,12 @@ void Dbdih::execSTART_MECONF(Signal* signal) StartMeConf * const startMe = (StartMeConf *)&signal->theData[0]; Uint32 nodeId = startMe->startingNodeId; const Uint32 startWord = startMe->startWord; + Uint32 i; CRASH_INSERTION(7130); ndbrequire(nodeId == cownNodeId); arrGuard(startWord + StartMeConf::DATA_SIZE, sizeof(cdata)/4); - for(Uint32 i = 0; i < StartMeConf::DATA_SIZE; i++) + for(i = 0; i < StartMeConf::DATA_SIZE; i++) cdata[startWord+i] = startMe->data[i]; if(startWord + StartMeConf::DATA_SIZE < Sysfile::SYSFILE_SIZE32){ @@ -1556,12 +1585,12 @@ void Dbdih::execSTART_MECONF(Signal* signal) * But dont copy lastCompletedGCI:s */ Uint32 tempGCP[MAX_NDB_NODES]; - for(Uint32 i = 0; i < MAX_NDB_NODES; i++) + for(i = 0; i < MAX_NDB_NODES; i++) tempGCP[i] = SYSFILE->lastCompletedGCI[i]; - for(Uint32 i = 0; i < Sysfile::SYSFILE_SIZE32; i++) + for(i = 0; i < Sysfile::SYSFILE_SIZE32; i++) sysfileData[i] = cdata[i]; - for(Uint32 i = 0; i < MAX_NDB_NODES; i++) + for(i = 0; i < MAX_NDB_NODES; i++) SYSFILE->lastCompletedGCI[i] = tempGCP[i]; setNodeActiveStatus(); @@ -1981,9 +2010,11 @@ void Dbdih::execSTART_INFOREQ(Signal* signal) (ERROR_INSERTED(7124))) { jam(); StartInfoRef *const ref =(StartInfoRef*)&signal->theData[0]; + ref->startingNodeId = startNode; ref->sendingNodeId = cownNodeId; ref->errorCode = ZNODE_START_DISALLOWED_ERROR; - sendSignal(cmasterdihref, GSN_START_INFOREF, signal, 2, JBB); + sendSignal(cmasterdihref, GSN_START_INFOREF, signal, + StartInfoRef::SignalLength, JBB); return; }//if setNodeStatus(startNode, NodeRecord::STARTING); @@ -2053,7 +2084,7 @@ void Dbdih::execINCL_NODEREQ(Signal* signal) Sysfile::ActiveStatus TsaveState = nodePtr.p->activeStatus; Uint32 TnodeGroup = nodePtr.p->nodeGroup; - initNodeState(nodePtr); + new (nodePtr.p) NodeRecord(); nodePtr.p->nodeGroup = TnodeGroup; nodePtr.p->activeStatus = TsaveState; nodePtr.p->nodeStatus = NodeRecord::ALIVE; @@ -3448,10 +3479,37 @@ void Dbdih::selectMasterCandidateAndSend(Signal* signal) }//if }//for ndbrequire(masterCandidateId != 0); + setNodeGroups(); signal->theData[0] = masterCandidateId; signal->theData[1] = gci; sendSignal(cntrlblockref, GSN_DIH_RESTARTCONF, signal, 2, JBB); - setNodeGroups(); + + Uint32 node_groups[MAX_NDB_NODES]; + memset(node_groups, 0, sizeof(node_groups)); + for (nodePtr.i = 1; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) { + jam(); + const Uint32 ng = Sysfile::getNodeGroup(nodePtr.i, SYSFILE->nodeGroups); + if(ng != NO_NODE_GROUP_ID){ + ndbrequire(ng < MAX_NDB_NODES); + node_groups[ng]++; + } + } + + for (nodePtr.i = 0; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) { + jam(); + Uint32 count = node_groups[nodePtr.i]; + if(count != 0 && count != cnoReplicas){ + char buf[255]; + snprintf(buf, sizeof(buf), + "Illegal configuration change." + " Initial start needs to be performed " + " when changing no of replicas (%d != %d)", + node_groups[nodePtr.i], cnoReplicas); + progError(__LINE__, + ERR_INVALID_CONFIG, + buf); + } + } }//Dbdih::selectMasterCandidate() /* ------------------------------------------------------------------------- */ @@ -3599,6 +3657,7 @@ void Dbdih::writeInitGcpLab(Signal* signal, FileRecordPtr filePtr) /*---------------------------------------------------------------------------*/ void Dbdih::execNODE_FAILREP(Signal* signal) { + Uint32 i; Uint32 failedNodes[MAX_NDB_NODES]; jamEntry(); NodeFailRep * const nodeFail = (NodeFailRep *)&signal->theData[0]; @@ -3611,7 +3670,7 @@ void Dbdih::execNODE_FAILREP(Signal* signal) // The first step is to convert from a bit mask to an array of failed nodes. /*-------------------------------------------------------------------------*/ Uint32 index = 0; - for (Uint32 i = 1; i < MAX_NDB_NODES; i++) { + for (i = 1; i < MAX_NDB_NODES; i++) { jam(); if(NodeBitmask::get(nodeFail->theNodes, i)){ jam(); @@ -3629,7 +3688,7 @@ void Dbdih::execNODE_FAILREP(Signal* signal) // We also set certain state variables ensuring that the node no longer is // used in transactions and also mark that we received this signal. /*-------------------------------------------------------------------------*/ - for (Uint32 i = 0; i < noOfFailedNodes; i++) { + for (i = 0; i < noOfFailedNodes; i++) { jam(); NodeRecordPtr TNodePtr; TNodePtr.i = failedNodes[i]; @@ -3671,7 +3730,7 @@ void Dbdih::execNODE_FAILREP(Signal* signal) const bool masterTakeOver = (oldMasterId != newMasterId); - for(Uint32 i = 0; i < noOfFailedNodes; i++) { + for(i = 0; i < noOfFailedNodes; i++) { NodeRecordPtr failedNodePtr; failedNodePtr.i = failedNodes[i]; ptrCheckGuard(failedNodePtr, MAX_NDB_NODES, nodeRecord); @@ -6071,13 +6130,9 @@ void Dbdih::execDIRELEASEREQ(Signal* signal) ptrCheckGuard(connectPtr, cconnectFileSize, connectRecord); ndbrequire(connectPtr.p->connectState != ConnectRecord::FREE); ndbrequire(connectPtr.p->userblockref == userRef); - connectPtr.p->connectState = ConnectRecord::FREE; signal->theData[0] = connectPtr.p->userpointer; sendSignal(connectPtr.p->userblockref, GSN_DIRELEASECONF, signal, 1, JBB); - connectPtr.p->nfConnect = cfirstconnect; - cfirstconnect = connectPtr.i; - connectPtr.p->userblockref = ZNIL; - connectPtr.p->userpointer = RNIL; + release_connect(connectPtr); }//Dbdih::execDIRELEASEREQ() /* @@ -6514,11 +6569,16 @@ Dbdih::sendAddFragreq(Signal* signal, ConnectRecordPtr connectPtr, DiAddTabConf::SignalLength, JBB); // Release - connectPtr.p->userblockref = ZNIL; - connectPtr.p->userpointer = RNIL; - connectPtr.p->connectState = ConnectRecord::FREE; - connectPtr.p->nfConnect = cfirstconnect; - cfirstconnect = connectPtr.i; + release_connect(connectPtr); +} +void +Dbdih::release_connect(ConnectRecordPtr ptr) +{ + ptr.p->userblockref = ZNIL; + ptr.p->userpointer = RNIL; + ptr.p->connectState = ConnectRecord::FREE; + ptr.p->nfConnect = cfirstconnect; + cfirstconnect = ptr.i; } void @@ -6555,11 +6615,7 @@ Dbdih::execADD_FRAGREF(Signal* signal){ } // Release - connectPtr.p->userblockref = ZNIL; - connectPtr.p->userpointer = RNIL; - connectPtr.p->connectState = ConnectRecord::FREE; - connectPtr.p->nfConnect = cfirstconnect; - cfirstconnect = connectPtr.i; + release_connect(connectPtr); } /* @@ -6568,10 +6624,10 @@ Dbdih::execADD_FRAGREF(Signal* signal){ */ void Dbdih::addtabrefuseLab(Signal* signal, ConnectRecordPtr connectPtr, Uint32 errorCode) { - connectPtr.p->connectState = ConnectRecord::INUSE; signal->theData[0] = connectPtr.p->userpointer; signal->theData[1] = errorCode; sendSignal(connectPtr.p->userblockref, GSN_DIADDTABREF, signal, 2, JBB); + release_connect(connectPtr); return; }//Dbdih::addtabrefuseLab() @@ -6882,8 +6938,9 @@ void Dbdih::releaseFragments(TabRecordPtr tabPtr) void Dbdih::initialiseFragstore() { + Uint32 i; FragmentstorePtr fragPtr; - for (Uint32 i = 0; i < cfragstoreFileSize; i++) { + for (i = 0; i < cfragstoreFileSize; i++) { fragPtr.i = i; ptrCheckGuard(fragPtr, cfragstoreFileSize, fragmentstore); initFragstore(fragPtr); @@ -6892,7 +6949,8 @@ void Dbdih::initialiseFragstore() fragPtr.i = 0; cfirstfragstore = RNIL; cremainingfrags = 0; - for (Uint32 i = 0; i < noOfChunks; i++) { + for (i = 0; i < noOfChunks; i++) { + refresh_watch_dog(); ptrCheckGuard(fragPtr, cfragstoreFileSize, fragmentstore); fragPtr.p->nextFragmentChunk = cfirstfragstore; cfirstfragstore = fragPtr.i; @@ -10231,11 +10289,12 @@ void Dbdih::allocStoredReplica(FragmentstorePtr fragPtr, ReplicaRecordPtr& newReplicaPtr, Uint32 nodeId) { + Uint32 i; ReplicaRecordPtr arrReplicaPtr; ReplicaRecordPtr arrPrevReplicaPtr; seizeReplicaRec(newReplicaPtr); - for (Uint32 i = 0; i < MAX_LCP_STORED; i++) { + for (i = 0; i < MAX_LCP_STORED; i++) { newReplicaPtr.p->maxGciCompleted[i] = 0; newReplicaPtr.p->maxGciStarted[i] = 0; newReplicaPtr.p->lcpId[i] = 0; @@ -10243,7 +10302,7 @@ void Dbdih::allocStoredReplica(FragmentstorePtr fragPtr, }//for newReplicaPtr.p->noCrashedReplicas = 0; newReplicaPtr.p->initialGci = currentgcp; - for (Uint32 i = 0; i < 8; i++) { + for (i = 0; i < 8; i++) { newReplicaPtr.p->replicaLastGci[i] = (Uint32)-1; newReplicaPtr.p->createGci[i] = 0; }//for @@ -10354,7 +10413,8 @@ void Dbdih::checkEscalation() { Uint32 TnodeGroup[MAX_NDB_NODES]; NodeRecordPtr nodePtr; - for (Uint32 i = 0; i < MAX_NDB_NODES; i++) { + Uint32 i; + for (i = 0; i < MAX_NDB_NODES; i++) { TnodeGroup[i] = ZFALSE; }//for for (nodePtr.i = 1; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) { @@ -10366,7 +10426,7 @@ void Dbdih::checkEscalation() TnodeGroup[nodePtr.p->nodeGroup] = ZTRUE; } } - for (Uint32 i = 0; i < cnoOfNodeGroups; i++) { + for (i = 0; i < cnoOfNodeGroups; i++) { jam(); if (TnodeGroup[i] == ZFALSE) { jam(); @@ -10900,27 +10960,6 @@ void Dbdih::initFragstore(FragmentstorePtr fragPtr) fragPtr.p->distributionKey = 0; }//Dbdih::initFragstore() -void Dbdih::initNodeState(NodeRecordPtr nodePtr) -{ - nodePtr.p->gcpstate = NodeRecord::READY; - - nodePtr.p->activeStatus = Sysfile::NS_NotDefined; - nodePtr.p->recNODE_FAILREP = ZFALSE; - nodePtr.p->nodeGroup = ZNIL; - nodePtr.p->dbtcFailCompleted = ZTRUE; - nodePtr.p->dbdictFailCompleted = ZTRUE; - nodePtr.p->dbdihFailCompleted = ZTRUE; - nodePtr.p->dblqhFailCompleted = ZTRUE; - nodePtr.p->noOfStartedChkpt = 0; - nodePtr.p->noOfQueuedChkpt = 0; - nodePtr.p->lcpStateAtTakeOver = (MasterLCPConf::State)255; - - nodePtr.p->activeTabptr = RNIL; - nodePtr.p->nodeStatus = NodeRecord::NOT_IN_CLUSTER; - nodePtr.p->useInTransactions = false; - nodePtr.p->copyCompleted = false; -}//Dbdih::initNodeState() - /*************************************************************************/ /* */ /* MODULE: INIT_RESTART_INFO */ @@ -10929,7 +10968,8 @@ void Dbdih::initNodeState(NodeRecordPtr nodePtr) /*************************************************************************/ void Dbdih::initRestartInfo() { - for (int i = 0; i < MAX_NDB_NODES; i++) { + Uint32 i; + for (i = 0; i < MAX_NDB_NODES; i++) { SYSFILE->lastCompletedGCI[i] = 0; }//for NodeRecordPtr nodePtr; @@ -10950,10 +10990,10 @@ void Dbdih::initRestartInfo() SYSFILE->oldestRestorableGCI = 1; SYSFILE->newestRestorableGCI = 1; SYSFILE->systemRestartBits = 0; - for (Uint32 i = 0; i < NodeBitmask::Size; i++) { + for (i = 0; i < NodeBitmask::Size; i++) { SYSFILE->lcpActive[0] = 0; }//for - for (Uint32 i = 0; i < Sysfile::TAKE_OVER_SIZE; i++) { + for (i = 0; i < Sysfile::TAKE_OVER_SIZE; i++) { SYSFILE->takeOver[i] = 0; }//for Sysfile::setInitialStartOngoing(SYSFILE->systemRestartBits); @@ -11032,10 +11072,11 @@ void Dbdih::initTable(TabRecordPtr tabPtr) tabPtr.p->tabFile[1] = RNIL; tabPtr.p->m_dropTab.tabUserRef = 0; tabPtr.p->m_dropTab.tabUserPtr = RNIL; - for (Uint32 i = 0; i < MAX_NDB_NODES; i++) { + Uint32 i; + for (i = 0; i < MAX_NDB_NODES; i++) { tabPtr.p->startFid[i] = RNIL; }//for - for (Uint32 i = 0; i < 8; i++) { + for (i = 0; i < 8; i++) { tabPtr.p->pageRef[i] = RNIL; }//for tabPtr.p->tableType = DictTabInfo::UndefTableType; @@ -11100,6 +11141,7 @@ void Dbdih::initialiseRecordsLab(Signal* signal, jam(); /******** INTIALIZING API CONNECT RECORDS ********/ for (apiConnectptr.i = 0; apiConnectptr.i < capiConnectFileSize; apiConnectptr.i++) { + refresh_watch_dog(); ptrAss(apiConnectptr, apiConnectRecord); apiConnectptr.p->nextApi = RNIL; }//for @@ -11111,6 +11153,7 @@ void Dbdih::initialiseRecordsLab(Signal* signal, jam(); /****** CONNECT ******/ for (connectPtr.i = 0; connectPtr.i < cconnectFileSize; connectPtr.i++) { + refresh_watch_dog(); ptrAss(connectPtr, connectRecord); connectPtr.p->userpointer = RNIL; connectPtr.p->userblockref = ZNIL; @@ -11165,7 +11208,7 @@ void Dbdih::initialiseRecordsLab(Signal* signal, NodeRecordPtr nodePtr; for (nodePtr.i = 0; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) { ptrAss(nodePtr, nodeRecord); - initNodeState(nodePtr); + new (nodePtr.p) NodeRecord(); }//for break; } @@ -11175,6 +11218,7 @@ void Dbdih::initialiseRecordsLab(Signal* signal, jam(); /******* PAGE RECORD ******/ for (pagePtr.i = 0; pagePtr.i < cpageFileSize; pagePtr.i++) { + refresh_watch_dog(); ptrAss(pagePtr, pageRecord); pagePtr.p->nextfreepage = pagePtr.i + 1; }//for @@ -11191,6 +11235,7 @@ void Dbdih::initialiseRecordsLab(Signal* signal, /******* REPLICA RECORD ******/ for (initReplicaPtr.i = 0; initReplicaPtr.i < creplicaFileSize; initReplicaPtr.i++) { + refresh_watch_dog(); ptrAss(initReplicaPtr, replicaRecord); initReplicaPtr.p->lcpIdStarted = 0; initReplicaPtr.p->lcpOngoingFlag = false; @@ -11210,6 +11255,7 @@ void Dbdih::initialiseRecordsLab(Signal* signal, /********* TAB-DESCRIPTOR ********/ for (loopTabptr.i = 0; loopTabptr.i < ctabFileSize; loopTabptr.i++) { ptrAss(loopTabptr, tabRecord); + refresh_watch_dog(); initTable(loopTabptr); }//for break; @@ -11367,6 +11413,7 @@ void Dbdih::makeNodeGroups(Uint32 nodeArray[]) Uint32 tmngNodeGroup; Uint32 tmngReplica; Uint32 tmngLimit; + Uint32 i; /**----------------------------------------------------------------------- * ASSIGN ALL ACTIVE NODES INTO NODE GROUPS. HOT SPARE NODES ARE ASSIGNED @@ -11376,7 +11423,7 @@ void Dbdih::makeNodeGroups(Uint32 nodeArray[]) tmngReplica = 0; tmngLimit = csystemnodes - cnoHotSpare; ndbrequire(tmngLimit < MAX_NDB_NODES); - for (Uint32 i = 0; i < tmngLimit; i++) { + for (i = 0; i < tmngLimit; i++) { NodeGroupRecordPtr NGPtr; jam(); tmngNode = nodeArray[i]; @@ -11396,14 +11443,14 @@ void Dbdih::makeNodeGroups(Uint32 nodeArray[]) }//for cnoOfNodeGroups = tmngNodeGroup; ndbrequire(csystemnodes < MAX_NDB_NODES); - for (Uint32 i = tmngLimit + 1; i < csystemnodes; i++) { + for (i = tmngLimit + 1; i < csystemnodes; i++) { jam(); tmngNode = nodeArray[i]; mngNodeptr.i = tmngNode; ptrCheckGuard(mngNodeptr, MAX_NDB_NODES, nodeRecord); mngNodeptr.p->nodeGroup = ZNIL; }//for - for(int i = 0; i < MAX_NDB_NODES; i++){ + for(i = 0; i < MAX_NDB_NODES; i++){ jam(); Sysfile::setNodeGroup(i, SYSFILE->nodeGroups, NO_NODE_GROUP_ID); }//for @@ -11521,7 +11568,7 @@ void Dbdih::makePrnList(ReadNodesConf * readNodes, Uint32 nodeArray[]) jam(); nodePtr.i = nodeArray[i]; ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRecord); - initNodeState(nodePtr); + new (nodePtr.p) NodeRecord(); if (NodeBitmask::get(readNodes->inactiveNodes, nodePtr.i) == false){ jam(); nodePtr.p->nodeStatus = NodeRecord::ALIVE; @@ -11690,12 +11737,13 @@ Uint32 Dbdih::readPageWord(RWFragment* rf) void Dbdih::readReplica(RWFragment* rf, ReplicaRecordPtr readReplicaPtr) { + Uint32 i; readReplicaPtr.p->procNode = readPageWord(rf); readReplicaPtr.p->initialGci = readPageWord(rf); readReplicaPtr.p->noCrashedReplicas = readPageWord(rf); readReplicaPtr.p->nextLcp = readPageWord(rf); - for (Uint32 i = 0; i < MAX_LCP_STORED; i++) { + for (i = 0; i < MAX_LCP_STORED; i++) { readReplicaPtr.p->maxGciCompleted[i] = readPageWord(rf); readReplicaPtr.p->maxGciStarted[i] = readPageWord(rf); readReplicaPtr.p->lcpId[i] = readPageWord(rf); @@ -11703,13 +11751,13 @@ void Dbdih::readReplica(RWFragment* rf, ReplicaRecordPtr readReplicaPtr) }//for const Uint32 noCrashedReplicas = readReplicaPtr.p->noCrashedReplicas; ndbrequire(noCrashedReplicas < 8); - for (Uint32 i = 0; i < noCrashedReplicas; i++) { + for (i = 0; i < noCrashedReplicas; i++) { readReplicaPtr.p->createGci[i] = readPageWord(rf); readReplicaPtr.p->replicaLastGci[i] = readPageWord(rf); ndbrequire(readReplicaPtr.p->createGci[i] != 0xF1F1F1F1); ndbrequire(readReplicaPtr.p->replicaLastGci[i] != 0xF1F1F1F1); }//for - for(Uint32 i = noCrashedReplicas; i<8; i++){ + for(i = noCrashedReplicas; i<8; i++){ readReplicaPtr.p->createGci[i] = readPageWord(rf); readReplicaPtr.p->replicaLastGci[i] = readPageWord(rf); // They are not initialized... @@ -11732,7 +11780,7 @@ void Dbdih::readReplica(RWFragment* rf, ReplicaRecordPtr readReplicaPtr) /* WE ALSO HAVE TO INVALIDATE ANY LOCAL CHECKPOINTS THAT HAVE BEEN */ /* INVALIDATED BY MOVING BACK THE RESTART GCI. */ /* ---------------------------------------------------------------------- */ - for (Uint32 i = 0; i < MAX_LCP_STORED; i++) { + for (i = 0; i < MAX_LCP_STORED; i++) { jam(); if ((readReplicaPtr.p->lcpStatus[i] == ZVALID) && (readReplicaPtr.p->maxGciStarted[i] > SYSFILE->newestRestorableGCI)) { @@ -11764,6 +11812,7 @@ void Dbdih::readReplica(RWFragment* rf, ReplicaRecordPtr readReplicaPtr) void Dbdih::readReplicas(RWFragment* rf, FragmentstorePtr fragPtr) { + Uint32 i; ReplicaRecordPtr newReplicaPtr; Uint32 noStoredReplicas = fragPtr.p->noStoredReplicas; Uint32 noOldStoredReplicas = fragPtr.p->noOldStoredReplicas; @@ -11775,7 +11824,7 @@ void Dbdih::readReplicas(RWFragment* rf, FragmentstorePtr fragPtr) fragPtr.p->noOldStoredReplicas = 0; Uint32 replicaIndex = 0; ndbrequire(noStoredReplicas + noOldStoredReplicas <= MAX_REPLICAS); - for (Uint32 i = 0; i < noStoredReplicas; i++) { + for (i = 0; i < noStoredReplicas; i++) { seizeReplicaRec(newReplicaPtr); readReplica(rf, newReplicaPtr); if (checkNodeAlive(newReplicaPtr.p->procNode)) { @@ -11790,7 +11839,7 @@ void Dbdih::readReplicas(RWFragment* rf, FragmentstorePtr fragPtr) }//if }//for fragPtr.p->fragReplicas = noStoredReplicas; - for (Uint32 i = 0; i < noOldStoredReplicas; i++) { + for (i = 0; i < noOldStoredReplicas; i++) { jam(); seizeReplicaRec(newReplicaPtr); readReplica(rf, newReplicaPtr); @@ -12640,11 +12689,11 @@ void Dbdih::setNodeRestartInfoBits() NodeRecordPtr nodePtr; Uint32 tsnrNodeGroup; Uint32 tsnrNodeActiveStatus; - - for(int i = 1; i < MAX_NDB_NODES; i++){ + Uint32 i; + for(i = 1; i < MAX_NDB_NODES; i++){ Sysfile::setNodeStatus(i, SYSFILE->nodeStatus, Sysfile::NS_Active); }//for - for(Uint32 i = 1; i < Sysfile::NODE_GROUPS_SIZE; i++){ + for(i = 1; i < Sysfile::NODE_GROUPS_SIZE; i++){ SYSFILE->nodeGroups[i] = 0; }//for NdbNodeBitmask::clear(SYSFILE->lcpActive); @@ -12786,13 +12835,14 @@ void Dbdih::writeReplicas(RWFragment* wf, Uint32 replicaStartIndex) writePageWord(wf, wfReplicaPtr.p->initialGci); writePageWord(wf, wfReplicaPtr.p->noCrashedReplicas); writePageWord(wf, wfReplicaPtr.p->nextLcp); - for (Uint32 i = 0; i < MAX_LCP_STORED; i++) { + Uint32 i; + for (i = 0; i < MAX_LCP_STORED; i++) { writePageWord(wf, wfReplicaPtr.p->maxGciCompleted[i]); writePageWord(wf, wfReplicaPtr.p->maxGciStarted[i]); writePageWord(wf, wfReplicaPtr.p->lcpId[i]); writePageWord(wf, wfReplicaPtr.p->lcpStatus[i]); }//if - for (Uint32 i = 0; i < 8; i++) { + for (i = 0; i < 8; i++) { writePageWord(wf, wfReplicaPtr.p->createGci[i]); writePageWord(wf, wfReplicaPtr.p->replicaLastGci[i]); }//if @@ -13003,7 +13053,7 @@ Dbdih::execDUMP_STATE_ORD(Signal* signal) } if(signal->theData[0] == 7012){ - char buf[c_lcpState.m_participatingDIH.TextLength+1]; + char buf[8*_NDB_NODE_BITMASK_SIZE+1]; infoEvent("ParticipatingDIH = %s", c_lcpState.m_participatingDIH.getText(buf)); infoEvent("ParticipatingLQH = %s", c_lcpState.m_participatingLQH.getText(buf)); infoEvent("m_LCP_COMPLETE_REP_Counter_DIH = %s", @@ -13020,8 +13070,8 @@ Dbdih::execDUMP_STATE_ORD(Signal* signal) jam(); ptrAss(nodePtr, nodeRecord); if(nodePtr.p->nodeStatus == NodeRecord::ALIVE){ - - for(Uint32 i = 0; i<nodePtr.p->noOfStartedChkpt; i++){ + Uint32 i; + for(i = 0; i<nodePtr.p->noOfStartedChkpt; i++){ infoEvent("Node %d: started: table=%d fragment=%d replica=%d", nodePtr.i, nodePtr.p->startedChkpt[i].tableId, @@ -13029,7 +13079,7 @@ Dbdih::execDUMP_STATE_ORD(Signal* signal) nodePtr.p->startedChkpt[i].replicaPtr); } - for(Uint32 i = 0; i<nodePtr.p->noOfQueuedChkpt; i++){ + for(i = 0; i<nodePtr.p->noOfQueuedChkpt; i++){ infoEvent("Node %d: queued: table=%d fragment=%d replica=%d", nodePtr.i, nodePtr.p->queuedChkpt[i].tableId, @@ -13360,6 +13410,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(); WaitDropTabConf * conf = (WaitDropTabConf*)signal->getDataPtr(); @@ -14137,3 +14206,25 @@ bool Dbdih::isActiveMaster() { return ((reference() == cmasterdihref) && (cmasterState == MASTER_ACTIVE)); }//Dbdih::isActiveMaster() + +Dbdih::NodeRecord::NodeRecord(){ + m_nodefailSteps.clear(); + gcpstate = NodeRecord::READY; + + activeStatus = Sysfile::NS_NotDefined; + recNODE_FAILREP = ZFALSE; + nodeGroup = ZNIL; + dbtcFailCompleted = ZTRUE; + dbdictFailCompleted = ZTRUE; + dbdihFailCompleted = ZTRUE; + dblqhFailCompleted = ZTRUE; + noOfStartedChkpt = 0; + noOfQueuedChkpt = 0; + lcpStateAtTakeOver = (MasterLCPConf::State)255; + + activeTabptr = RNIL; + nodeStatus = NodeRecord::NOT_IN_CLUSTER; + useInTransactions = false; + copyCompleted = false; + allowNodeStart = true; +} diff --git a/ndb/src/kernel/blocks/dblqh/Dblqh.hpp b/ndb/src/kernel/blocks/dblqh/Dblqh.hpp index 824f74c59af..9fcb6faf3e3 100644 --- a/ndb/src/kernel/blocks/dblqh/Dblqh.hpp +++ b/ndb/src/kernel/blocks/dblqh/Dblqh.hpp @@ -410,7 +410,6 @@ */ class Dblqh: public SimulatedBlock { public: - enum LcpCloseState { LCP_IDLE = 0, LCP_RUNNING = 1, // LCP is running @@ -1990,7 +1989,6 @@ public: UintR nextTcLogQueue; UintR nextTc; UintR nextTcConnectrec; - Uint16 nodeAfterNext[2]; UintR prevHashRec; UintR prevLogTcrec; UintR prevTc; @@ -2027,6 +2025,7 @@ public: Uint16 nextReplica; Uint16 primKeyLen; Uint16 save1; + Uint16 nodeAfterNext[3]; Uint8 activeCreat; Uint8 apiVersionNo; @@ -2765,6 +2764,11 @@ private: /* ------------------------------------------------------------------------- */ UintR cfirstCompletedFragSr; + /** + * List of fragment that the log execution is completed for + */ + Uint32 c_redo_log_complete_frags; + /* ------------------------------------------------------------------------- */ /*USED DURING SYSTEM RESTART, INDICATES THE OLDEST GCI THAT CAN BE RESTARTED */ /*FROM AFTER THIS SYSTEM RESTART. USED TO FIND THE LOG TAIL. */ @@ -2859,8 +2863,9 @@ private: /* ------------------------------------------------------------------------- */ UintR preComputedRequestInfoMask; UintR ctransidHash[1024]; - - + + Uint32 c_diskless; + public: /** * diff --git a/ndb/src/kernel/blocks/dblqh/DblqhInit.cpp b/ndb/src/kernel/blocks/dblqh/DblqhInit.cpp index d5f40ec143c..4bb31185cfe 100644 --- a/ndb/src/kernel/blocks/dblqh/DblqhInit.cpp +++ b/ndb/src/kernel/blocks/dblqh/DblqhInit.cpp @@ -65,6 +65,7 @@ void Dblqh::initData() cLqhTimeOutCount = 0; cLqhTimeOutCheckCount = 0; cbookedAccOps = 0; + c_redo_log_complete_frags = RNIL; }//Dblqh::initData() void Dblqh::initRecords() @@ -120,7 +121,8 @@ void Dblqh::initRecords() logPageRecord = (LogPageRecord*)allocRecord("LogPageRecord", sizeof(LogPageRecord), - clogPageFileSize); + clogPageFileSize, + false); pageRefRecord = (PageRefRecord*)allocRecord("PageRefRecord", sizeof(PageRefRecord), @@ -322,6 +324,31 @@ Dblqh::Dblqh(const class Configuration & conf): addRecSignal(GSN_TUX_ADD_ATTRREF, &Dblqh::execTUX_ADD_ATTRREF); initData(); + +#ifdef VM_TRACE + { + void* tmp[] = { + &addfragptr, + &attrinbufptr, + &databufptr, + &fragptr, + &gcpPtr, + &lcpPtr, + &lcpLocptr, + &logPartPtr, + &logFilePtr, + &lfoPtr, + &logPagePtr, + &pageRefPtr, + &scanptr, + &tabptr, + &tcConnectptr, + &tcNodeFailptr, + }; + init_globals_list(tmp, sizeof(tmp)/sizeof(tmp[0])); + } +#endif + }//Dblqh::Dblqh() Dblqh::~Dblqh() diff --git a/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp b/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp index 1abf4b3a7e9..6b4a78380be 100644 --- a/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp +++ b/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp @@ -60,10 +60,55 @@ // seen only when we debug the product #ifdef VM_TRACE #define DEBUG(x) ndbout << "DBLQH: "<< x << endl; +NdbOut & +operator<<(NdbOut& out, Dblqh::TcConnectionrec::TransactionState state){ + out << (int)state; + return out; +} + +NdbOut & +operator<<(NdbOut& out, Dblqh::TcConnectionrec::LogWriteState state){ + out << (int)state; + return out; +} + +NdbOut & +operator<<(NdbOut& out, Dblqh::TcConnectionrec::ListState state){ + out << (int)state; + return out; +} + +NdbOut & +operator<<(NdbOut& out, Dblqh::TcConnectionrec::AbortState state){ + out << (int)state; + return out; +} + +NdbOut & +operator<<(NdbOut& out, Dblqh::ScanRecord::ScanState state){ + out << (int)state; + return out; +} + +NdbOut & +operator<<(NdbOut& out, Dblqh::LogFileOperationRecord::LfoState state){ + out << (int)state; + return out; +} + +NdbOut & +operator<<(NdbOut& out, Dblqh::ScanRecord::ScanType state){ + out << (int)state; + return out; +} + #else #define DEBUG(x) #endif +//#define MARKER_TRACE 1 +//#define TRACE_SCAN_TAKEOVER 1 + const Uint32 NR_ScanNo = 0; void Dblqh::execACC_COM_BLOCK(Signal* signal) @@ -847,6 +892,8 @@ void Dblqh::execREAD_CONFIG_REQ(Signal* signal) ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_LQH_SCAN, &cscanrecFileSize)); cmaxAccOps = cscanrecFileSize * MAX_PARALLEL_SCANS_PER_FRAG; + ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_DB_DISCLESS, &c_diskless)); + initRecords(); initialiseRecordsLab(signal, 0, ref, senderData); @@ -957,7 +1004,7 @@ void Dblqh::execLQHFRAGREQ(Signal* signal) } else { fragptr.p->tableFragptr = fragptr.i; } - + if (tempTable) { //-------------------------------------------- // reqinfo bit 3-4 = 2 means temporary table @@ -2416,6 +2463,9 @@ Dblqh::execREMOVE_MARKER_ORD(Signal* signal) CommitAckMarkerPtr removedPtr; m_commitAckMarkerHash.release(removedPtr, key); ndbrequire(removedPtr.i != RNIL); +#ifdef MARKER_TRACE + ndbout_c("Rem marker[%.8x %.8x]", key.transid1, key.transid2); +#endif } @@ -3140,6 +3190,13 @@ void Dblqh::execLQHKEYREQ(Signal* signal) noFreeRecordLab(signal, lqhKeyReq, ZNO_TC_CONNECT_ERROR); return; }//if + + if(ERROR_INSERTED(5038) && + refToNode(signal->getSendersBlockRef()) != getOwnNodeId()){ + jam(); + SET_ERROR_INSERT_VALUE(5039); + return; + } c_Counters.operations++; @@ -3208,10 +3265,17 @@ void Dblqh::execLQHKEYREQ(Signal* signal) const NodeId tcNodeId = refToNode(sig5); markerPtr.p->tcNodeId = tcNodeId; + CommitAckMarkerPtr tmp; +#ifdef VM_TRACE +#ifdef MARKER_TRACE + ndbout_c("Add marker[%.8x %.8x]", markerPtr.p->transid1, markerPtr.p->transid2); +#endif + 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); @@ -3510,6 +3574,7 @@ void Dblqh::prepareContinueAfterBlockedLab(Signal* signal) /* -------------------------------------------------------------------------- */ /* ALSO AFTER NORMAL PROCEDURE WE CONTINUE HERE */ /* -------------------------------------------------------------------------- */ + Uint32 tc_ptr_i = tcConnectptr.i; TcConnectionrec * const regTcPtr = tcConnectptr.p; if (regTcPtr->indTakeOver == ZTRUE) { jam(); @@ -3520,7 +3585,10 @@ void Dblqh::prepareContinueAfterBlockedLab(Signal* signal) key.scanNumber = KeyInfo20::getScanNo(regTcPtr->tcScanInfo); key.fragPtrI = fragptr.i; c_scanTakeOverHash.find(scanptr, key); - ndbassert(scanptr.i != RNIL); +#ifdef TRACE_SCAN_TAKEOVER + if(scanptr.i == RNIL) + ndbout_c("not finding (%d %d)", key.scanNumber, key.fragPtrI); +#endif } if (scanptr.i == RNIL) { jam(); @@ -3610,14 +3678,14 @@ void Dblqh::prepareContinueAfterBlockedLab(Signal* signal) EXECUTE_DIRECT(refToBlock(regTcPtr->tcAccBlockref), GSN_ACCKEYREQ, signal, 7 + regTcPtr->primKeyLen); if (signal->theData[0] < RNIL) { - signal->theData[0] = tcConnectptr.i; + signal->theData[0] = tc_ptr_i; execACCKEYCONF(signal); return; } else if (signal->theData[0] == RNIL) { ; } else { ndbrequire(signal->theData[0] == (UintR)-1); - signal->theData[0] = tcConnectptr.i; + signal->theData[0] = tc_ptr_i; execACCKEYREF(signal); }//if return; @@ -5632,9 +5700,7 @@ void Dblqh::execABORT(Signal* signal) BlockReference tcBlockref = signal->theData[1]; Uint32 transid1 = signal->theData[2]; Uint32 transid2 = signal->theData[3]; - if (ERROR_INSERTED(5003)) { - systemErrorLab(signal); - } + CRASH_INSERTION(5003); if (ERROR_INSERTED(5015)) { CLEAR_ERROR_INSERT_VALUE; sendSignalWithDelay(cownref, GSN_ABORT, signal, 2000, 4); @@ -5644,6 +5710,21 @@ void Dblqh::execABORT(Signal* signal) transid2, tcOprec) != ZOK) { jam(); + + if(ERROR_INSERTED(5039) && + refToNode(signal->getSendersBlockRef()) != getOwnNodeId()){ + jam(); + SET_ERROR_INSERT_VALUE(5040); + return; + } + + if(ERROR_INSERTED(5040) && + refToNode(signal->getSendersBlockRef()) != getOwnNodeId()){ + jam(); + SET_ERROR_INSERT_VALUE(5003); + return; + } + /* ------------------------------------------------------------------------- */ // SEND ABORTED EVEN IF NOT FOUND. //THE TRANSACTION MIGHT NEVER HAVE ARRIVED HERE. @@ -5676,7 +5757,23 @@ void Dblqh::execABORT(Signal* signal) }//if regTcPtr->abortState = TcConnectionrec::ABORT_FROM_TC; regTcPtr->activeCreat = ZFALSE; + + const Uint32 commitAckMarker = regTcPtr->commitAckMarker; + if(commitAckMarker != RNIL){ + jam(); +#ifdef MARKER_TRACE + { + CommitAckMarkerPtr tmp; + m_commitAckMarkerHash.getPtr(tmp, commitAckMarker); + ndbout_c("Ab2 marker[%.8x %.8x]", tmp.p->transid1, tmp.p->transid2); + } +#endif + m_commitAckMarkerHash.release(commitAckMarker); + regTcPtr->commitAckMarker = RNIL; + } + abortStateHandlerLab(signal); + return; }//Dblqh::execABORT() @@ -5815,10 +5912,18 @@ void Dblqh::execACCKEYREF(Signal* signal) * Only primary replica can get ZTUPLE_ALREADY_EXIST || ZNO_TUPLE_FOUND * * Unless it's a simple or dirty read + * + * NOT TRUE! + * 1) op1 - primary insert ok + * 2) op1 - backup insert fail (log full or what ever) + * 3) op1 - delete ok @ primary + * 4) op1 - delete fail @ backup + * + * -> ZNO_TUPLE_FOUND is possible */ ndbrequire (tcPtr->seqNoReplica == 0 || - (errCode != ZTUPLE_ALREADY_EXIST && errCode != ZNO_TUPLE_FOUND) || + errCode != ZTUPLE_ALREADY_EXIST || (tcPtr->operation == ZREAD && (tcPtr->dirtyOp || tcPtr->opSimple))); } tcPtr->abortState = TcConnectionrec::ABORT_FROM_LQH; @@ -5925,10 +6030,15 @@ void Dblqh::abortStateHandlerLab(Signal* signal) break; case TcConnectionrec::STOPPED: jam(); -/* ------------------------------------------------------------------------- */ -/*WE ARE CURRENTLY QUEUED FOR ACCESS TO THE FRAGMENT BY A LOCAL CHECKPOINT. */ -/* ------------------------------------------------------------------------- */ + /* --------------------------------------------------------------------- + * WE ARE CURRENTLY QUEUED FOR ACCESS TO THE FRAGMENT BY A LCP + * Since nothing has been done, just release operation + * i.e. no prepare log record has been written + * so no abort log records needs to be written + */ releaseWaitQueue(signal); + continueAfterLogAbortWriteLab(signal); + return; break; case TcConnectionrec::WAIT_AI_AFTER_ABORT: jam(); @@ -6034,7 +6144,13 @@ void Dblqh::abortCommonLab(Signal* signal) * There is no NR ongoing and we have a marker */ jam(); - +#ifdef MARKER_TRACE + { + CommitAckMarkerPtr tmp; + m_commitAckMarkerHash.getPtr(tmp, commitAckMarker); + ndbout_c("Abo marker[%.8x %.8x]", tmp.p->transid1, tmp.p->transid2); + } +#endif m_commitAckMarkerHash.release(commitAckMarker); regTcPtr->commitAckMarker = RNIL; } @@ -6307,12 +6423,13 @@ void Dblqh::execNODE_FAILREP(Signal* signal) UintR TfoundNodes = 0; UintR TnoOfNodes; UintR Tdata[MAX_NDB_NODES]; + Uint32 i; NodeFailRep * const nodeFail = (NodeFailRep *)&signal->theData[0]; TnoOfNodes = nodeFail->noOfNodes; UintR index = 0; - for (Uint32 i = 1; i < MAX_NDB_NODES; i++) { + for (i = 1; i < MAX_NDB_NODES; i++) { jam(); if(NodeBitmask::get(nodeFail->theNodes, i)){ jam(); @@ -6326,7 +6443,7 @@ void Dblqh::execNODE_FAILREP(Signal* signal) ndbrequire(index == TnoOfNodes); ndbrequire(cnoOfNodes - 1 < MAX_NDB_NODES); - for (Uint32 i = 0; i < TnoOfNodes; i++) { + for (i = 0; i < TnoOfNodes; i++) { const Uint32 nodeId = Tdata[i]; lcpPtr.p->m_EMPTY_LCP_REQ.clear(nodeId); @@ -6524,7 +6641,7 @@ Dblqh::scanMarkers(Signal* signal, } const Uint32 RT_BREAK = 256; - for(Uint32 i = 0; i<RT_BREAK || iter.bucket == startBucket; i++){ + for(i = 0; i<RT_BREAK || iter.bucket == startBucket; i++){ jam(); if(iter.curr.i == RNIL){ @@ -6793,7 +6910,8 @@ void Dblqh::execSCAN_NEXTREQ(Signal* signal) if (findTransaction(transid1, transid2, senderData) != ZOK){ jam(); - DEBUG("Received SCAN_NEXTREQ in LQH with close flag when closed"); + DEBUG(senderData << + " Received SCAN_NEXTREQ in LQH with close flag when closed"); ndbrequire(nextReq->closeFlag == ZTRUE); return; } @@ -6833,6 +6951,10 @@ void Dblqh::execSCAN_NEXTREQ(Signal* signal) return; }//if + if(ERROR_INSERTED(5036)){ + return; + } + scanptr.i = tcConnectptr.p->tcScanRec; ndbrequire(scanptr.i != RNIL); c_scanRecordPool.getPtr(scanptr); @@ -6849,6 +6971,10 @@ void Dblqh::execSCAN_NEXTREQ(Signal* signal) if(ERROR_INSERTED(5034)){ CLEAR_ERROR_INSERT_VALUE; } + if(ERROR_INSERTED(5036)){ + CLEAR_ERROR_INSERT_VALUE; + return; + } closeScanRequestLab(signal); return; }//if @@ -7134,7 +7260,7 @@ void Dblqh::execSCAN_FRAGREQ(Signal* signal) ScanFragRef * ref; const Uint32 transid1 = scanFragReq->transId1; const Uint32 transid2 = scanFragReq->transId2; - Uint32 errorCode; + Uint32 errorCode= 0; Uint32 senderData; Uint32 hashIndex; TcConnectionrecPtr nextHashptr; @@ -7862,27 +7988,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; @@ -8200,7 +8309,7 @@ Uint32 Dblqh::initScanrec(const ScanFragReq* scanFragReq) scanptr.p->scanLocalref[1] = 0; scanptr.p->scanLocalFragid = 0; scanptr.p->scanTcWaiting = ZTRUE; - scanptr.p->scanNumber = ZNIL; + scanptr.p->scanNumber = ~0; for (Uint32 i = 0; i < scanConcurrentOperations; i++) { jam(); @@ -8256,6 +8365,11 @@ Uint32 Dblqh::initScanrec(const ScanFragReq* scanFragReq) ScanRecordPtr tmp; ndbrequire(!c_scanTakeOverHash.find(tmp, * scanptr.p)); #endif +#ifdef TRACE_SCAN_TAKEOVER + ndbout_c("adding (%d %d) table: %d fragId: %d frag.i: %d tableFragptr: %d", + scanptr.p->scanNumber, scanptr.p->fragPtrI, + tabptr.i, scanFragReq->fragmentNo, fragptr.i, fragptr.p->tableFragptr); +#endif c_scanTakeOverHash.add(scanptr); } return ZOK; @@ -8318,7 +8432,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() @@ -8345,6 +8460,9 @@ void Dblqh::finishScanrec(Signal* signal) if(scanptr.p->scanKeyinfoFlag){ jam(); ScanRecordPtr tmp; +#ifdef TRACE_SCAN_TAKEOVER + ndbout_c("removing (%d %d)", scanptr.p->scanNumber, scanptr.p->fragPtrI); +#endif c_scanTakeOverHash.remove(tmp, * scanptr.p); ndbrequire(tmp.p == scanptr.p); } @@ -8388,6 +8506,9 @@ void Dblqh::finishScanrec(Signal* signal) ndbrequire(!c_scanTakeOverHash.find(tmp, * restart.p)); #endif c_scanTakeOverHash.add(restart); +#ifdef TRACE_SCAN_TAKEOVER + ndbout_c("adding-r (%d %d)", restart.p->scanNumber, restart.p->fragPtrI); +#endif } scanptr = restart; @@ -8422,78 +8543,131 @@ 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 = true; // TODO 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, + KeyInfo20::HeaderLength + 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){ - 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 - */ + /** + * 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 = 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; + } -}//Dblqh::sendKeyinfo20() + MEMCOPY_NO_WORDS(keyInfo->keyData, src, keyLen); + keyInfo->keyData[keyLen] = ref; + sendSignal(routeBlockref, GSN_KEYINFO20_R, signal, + KeyInfo20::HeaderLength+keyLen+1, JBB); + return; + } + 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 ------- * * ------------------------------------------------------------------------ */ void Dblqh::sendScanFragConf(Signal* signal, Uint32 scanCompleted) { + if(ERROR_INSERTED(5037)){ + CLEAR_ERROR_INSERT_VALUE; + return; + } + scanptr.p->scanTcWaiting = ZFALSE; ScanFragConf * conf = (ScanFragConf*)&signal->theData[0]; @@ -8868,7 +9042,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(); @@ -9832,9 +10006,11 @@ void Dblqh::execLCP_HOLDOPCONF(Signal* signal) return; } else { jam(); + /* NO MORE HOLDOPS NEEDED */ lcpLocptr.p->lcpLocstate = LcpLocRecord::HOLDOP_READY; checkLcpHoldop(signal); + if (lcpPtr.p->lcpState == LcpRecord::LCP_WAIT_ACTIVE_FINISH) { if (fragptr.p->activeList == RNIL) { jam(); @@ -9852,6 +10028,7 @@ void Dblqh::execLCP_HOLDOPCONF(Signal* signal) }//if }//if }//if + /* ----------------------- */ /* ELSE */ /* ------------------------------------------------------------------------ @@ -9924,7 +10101,6 @@ void Dblqh::execTUP_LCPSTARTED(Signal* signal) void Dblqh::lcpStartedLab(Signal* signal) { checkLcpStarted(signal); - if (lcpPtr.p->lcpState == LcpRecord::LCP_STARTED) { jam(); /* ---------------------------------------------------------------------- @@ -9943,7 +10119,7 @@ void Dblqh::lcpStartedLab(Signal* signal) sendAccContOp(signal); /* START OPERATIONS IN ACC */ moveAccActiveFrag(signal); /* MOVE FROM ACC BLOCKED LIST TO ACTIVE LIST ON FRAGMENT */ - }//if + } /*---------------*/ /* ELSE */ /*-------------------------------------------------------------------------*/ @@ -10004,32 +10180,27 @@ void Dblqh::execLQH_RESTART_OP(Signal* signal) lcpPtr.i = signal->theData[1]; ptrCheckGuard(lcpPtr, clcpFileSize, lcpRecord); - if (fragptr.p->fragStatus == Fragrecord::BLOCKED) { - if (lcpPtr.p->lcpState == LcpRecord::LCP_STARTED) { - jam(); - /***********************************************************************/ - /* THIS SIGNAL CAN ONLY BE RECEIVED WHEN FRAGMENT IS BLOCKED AND - * THE LOCAL CHECKPOINT HAS BEEN STARTED. THE BLOCKING WILL BE - * REMOVED AS SOON AS ALL OPERATIONS HAVE BEEN STARTED. - ***********************************************************************/ - restartOperationsLab(signal); - return; - } else { - jam(); - if (lcpPtr.p->lcpState == LcpRecord::LCP_BLOCKED_COMP) { - jam(); - /*******************************************************************> - * THE CHECKPOINT IS COMPLETED BUT HAS NOT YET STARTED UP - * ALL OPERATIONS AGAIN. - * WE PERFORM THIS START-UP BEFORE CONTINUING WITH THE NEXT - * FRAGMENT OF THE LOCAL CHECKPOINT TO AVOID ANY STRANGE ERRORS. - *******************************************************************> */ - restartOperationsLab(signal); - return; - }//if - }//if - }//if - ndbrequire(false); + ndbrequire(fragptr.p->fragStatus == Fragrecord::BLOCKED); + if (lcpPtr.p->lcpState == LcpRecord::LCP_STARTED) { + jam(); + /***********************************************************************/ + /* THIS SIGNAL CAN ONLY BE RECEIVED WHEN FRAGMENT IS BLOCKED AND + * THE LOCAL CHECKPOINT HAS BEEN STARTED. THE BLOCKING WILL BE + * REMOVED AS SOON AS ALL OPERATIONS HAVE BEEN STARTED. + ***********************************************************************/ + restartOperationsLab(signal); + } else if (lcpPtr.p->lcpState == LcpRecord::LCP_BLOCKED_COMP) { + jam(); + /*******************************************************************> + * THE CHECKPOINT IS COMPLETED BUT HAS NOT YET STARTED UP + * ALL OPERATIONS AGAIN. + * WE PERFORM THIS START-UP BEFORE CONTINUING WITH THE NEXT + * FRAGMENT OF THE LOCAL CHECKPOINT TO AVOID ANY STRANGE ERRORS. + *******************************************************************> */ + restartOperationsLab(signal); + } else { + ndbrequire(false); + } }//Dblqh::execLQH_RESTART_OP() void Dblqh::restartOperationsLab(Signal* signal) @@ -10082,13 +10253,13 @@ void Dblqh::restartOperationsAfterStopLab(Signal* signal) * WHEN ARRIVING HERE THE OPERATION IS ALREADY SET IN THE ACTIVE LIST. * THUS WE CAN IMMEDIATELY CALL THE METHODS THAT EXECUTE FROM WHERE * THE OPERATION WAS STOPPED. - *------------------------------------------------------------------------- */ + *------------------------------------------------------------------------ */ switch (tcConnectptr.p->transactionState) { case TcConnectionrec::STOPPED: jam(); /*----------------------------------------------------------------------- * STOPPED BEFORE TRYING TO SEND ACCKEYREQ - *----------------------------------------------------------------------- */ + *---------------------------------------------------------------------- */ prepareContinueAfterBlockedLab(signal); return; break; @@ -10096,7 +10267,7 @@ void Dblqh::restartOperationsAfterStopLab(Signal* signal) jam(); /* ---------------------------------------------------------------------- * STOPPED BEFORE TRYING TO SEND ACC_COMMITREQ - * ---------------------------------------------------------------------- */ + * --------------------------------------------------------------------- */ releaseActiveFrag(signal); commitContinueAfterBlockedLab(signal); return; @@ -10105,7 +10276,7 @@ void Dblqh::restartOperationsAfterStopLab(Signal* signal) jam(); /* ---------------------------------------------------------------------- * STOPPED BEFORE TRYING TO SEND ACC_ABORTREQ - * ---------------------------------------------------------------------- */ + * --------------------------------------------------------------------- */ abortContinueAfterBlockedLab(signal, true); return; break; @@ -10113,7 +10284,7 @@ void Dblqh::restartOperationsAfterStopLab(Signal* signal) jam(); /* ---------------------------------------------------------------------- * STOPPED BEFORE TRYING TO SEND NEXT_SCANREQ DURING COPY FRAGMENT - * ---------------------------------------------------------------------- */ + * --------------------------------------------------------------------- */ continueCopyAfterBlockedLab(signal); return; break; @@ -10121,7 +10292,7 @@ void Dblqh::restartOperationsAfterStopLab(Signal* signal) jam(); /* ---------------------------------------------------------------------- * STOPPED BEFORE TRYING TO SEND NEXT_SCANREQ DURING COPY FRAGMENT - * ---------------------------------------------------------------------- */ + * --------------------------------------------------------------------- */ continueFirstCopyAfterBlockedLab(signal); return; break; @@ -10129,7 +10300,7 @@ void Dblqh::restartOperationsAfterStopLab(Signal* signal) jam(); /* ---------------------------------------------------------------------- * STOPPED BEFORE TRYING TO SEND NEXT_SCANREQ DURING SCAN - * ---------------------------------------------------------------------- */ + * --------------------------------------------------------------------- */ tcConnectptr.p->transactionState = TcConnectionrec::SCAN_STATE_USED; continueFirstScanAfterBlockedLab(signal); return; @@ -10138,7 +10309,7 @@ void Dblqh::restartOperationsAfterStopLab(Signal* signal) jam(); /* ---------------------------------------------------------------------- * STOPPED BEFORE TRYING TO SEND NEXT_SCANREQ DURING SCAN - * ---------------------------------------------------------------------- */ + * --------------------------------------------------------------------- */ tcConnectptr.p->transactionState = TcConnectionrec::SCAN_STATE_USED; continueAfterCheckLcpStopBlocked(signal); return; @@ -10147,7 +10318,7 @@ void Dblqh::restartOperationsAfterStopLab(Signal* signal) jam(); /* ---------------------------------------------------------------------- * STOPPED BEFORE TRYING TO SEND NEXT_SCANREQ DURING SCAN - * ---------------------------------------------------------------------- */ + * --------------------------------------------------------------------- */ tcConnectptr.p->transactionState = TcConnectionrec::SCAN_STATE_USED; continueScanAfterBlockedLab(signal); return; @@ -10157,7 +10328,7 @@ void Dblqh::restartOperationsAfterStopLab(Signal* signal) /* ---------------------------------------------------------------------- * STOPPED BEFORE TRYING TO SEND NEXT_SCANREQ DURING RELEASE * LOCKS IN SCAN - * ---------------------------------------------------------------------- */ + * --------------------------------------------------------------------- */ tcConnectptr.p->transactionState = TcConnectionrec::SCAN_STATE_USED; continueScanReleaseAfterBlockedLab(signal); return; @@ -10166,7 +10337,7 @@ void Dblqh::restartOperationsAfterStopLab(Signal* signal) jam(); /* ---------------------------------------------------------------------- * STOPPED BEFORE TRYING TO SEND NEXT_SCANREQ DURING CLOSE OF SCAN - * ---------------------------------------------------------------------- */ + * --------------------------------------------------------------------- */ continueCloseScanAfterBlockedLab(signal); return; break; @@ -10174,7 +10345,7 @@ void Dblqh::restartOperationsAfterStopLab(Signal* signal) jam(); /* ---------------------------------------------------------------------- * STOPPED BEFORE TRYING TO SEND NEXT_SCANREQ DURING CLOSE OF COPY - * ---------------------------------------------------------------------- */ + * --------------------------------------------------------------------- */ continueCloseCopyAfterBlockedLab(signal); return; break; @@ -10300,7 +10471,12 @@ void Dblqh::contChkpNextFragLab(Signal* signal) * ----------------------------------------------------------------------- */ if (fragptr.p->fragStatus == Fragrecord::BLOCKED) { jam(); + /** + * LCP of fragment complete + * but restarting of operations isn't + */ lcpPtr.p->lcpState = LcpRecord::LCP_BLOCKED_COMP; + //restartOperationsLab(signal); return; }//if @@ -10471,6 +10647,8 @@ void Dblqh::execEND_LCPCONF(Signal* signal) clcpCompletedState = LCP_IDLE; }//if }//if + lcpPtr.i = 0; + ptrAss(lcpPtr, lcpRecord); sendLCP_COMPLETE_REP(signal, lcpPtr.p->currentFragment.lcpFragOrd.lcpId); }//Dblqh::execEND_LCPCONF() @@ -10577,25 +10755,25 @@ void Dblqh::checkLcpStarted(Signal* signal) terrorCode = ZOK; clsLcpLocptr.i = lcpPtr.p->firstLcpLocAcc; + int i = 0; do { ptrCheckGuard(clsLcpLocptr, clcpLocrecFileSize, lcpLocRecord); - if (clsLcpLocptr.p->lcpLocstate != LcpLocRecord::ACC_STARTED) { - ndbrequire((clsLcpLocptr.p->lcpLocstate == LcpLocRecord::ACC_COMPLETED) || - (clsLcpLocptr.p->lcpLocstate == LcpLocRecord::ACC_WAIT_STARTED)); + if (clsLcpLocptr.p->lcpLocstate == LcpLocRecord::ACC_WAIT_STARTED){ return; }//if clsLcpLocptr.i = clsLcpLocptr.p->nextLcpLoc; + i++; } while (clsLcpLocptr.i != RNIL); + i = 0; clsLcpLocptr.i = lcpPtr.p->firstLcpLocTup; do { ptrCheckGuard(clsLcpLocptr, clcpLocrecFileSize, lcpLocRecord); - if (clsLcpLocptr.p->lcpLocstate != LcpLocRecord::TUP_STARTED) { - ndbrequire((clsLcpLocptr.p->lcpLocstate == LcpLocRecord::TUP_COMPLETED) || - (clsLcpLocptr.p->lcpLocstate == LcpLocRecord::TUP_WAIT_STARTED)); + if (clsLcpLocptr.p->lcpLocstate == LcpLocRecord::TUP_WAIT_STARTED){ return; }//if clsLcpLocptr.i = clsLcpLocptr.p->nextLcpLoc; + i++; } while (clsLcpLocptr.i != RNIL); lcpPtr.p->lcpState = LcpRecord::LCP_STARTED; }//Dblqh::checkLcpStarted() @@ -10753,18 +10931,28 @@ void Dblqh::sendAccContOp(Signal* signal) { LcpLocRecordPtr sacLcpLocptr; + int count = 0; sacLcpLocptr.i = lcpPtr.p->firstLcpLocAcc; do { ptrCheckGuard(sacLcpLocptr, clcpLocrecFileSize, lcpLocRecord); sacLcpLocptr.p->accContCounter = 0; -/* ------------------------------------------------------------------------- */ -/*SEND START OPERATIONS TO ACC AGAIN */ -/* ------------------------------------------------------------------------- */ - signal->theData[0] = lcpPtr.p->lcpAccptr; - signal->theData[1] = sacLcpLocptr.p->locFragid; - sendSignal(fragptr.p->accBlockref, GSN_ACC_CONTOPREQ, signal, 2, JBA); + if(sacLcpLocptr.p->lcpLocstate == LcpLocRecord::ACC_STARTED){ + /* ------------------------------------------------------------------- */ + /*SEND START OPERATIONS TO ACC AGAIN */ + /* ------------------------------------------------------------------- */ + signal->theData[0] = lcpPtr.p->lcpAccptr; + signal->theData[1] = sacLcpLocptr.p->locFragid; + sendSignal(fragptr.p->accBlockref, GSN_ACC_CONTOPREQ, signal, 2, JBA); + count++; + } else if(sacLcpLocptr.p->lcpLocstate == LcpLocRecord::ACC_COMPLETED){ + signal->theData[0] = sacLcpLocptr.i; + sendSignal(reference(), GSN_ACC_CONTOPCONF, signal, 1, JBB); + } else { + ndbrequire(false); + } sacLcpLocptr.i = sacLcpLocptr.p->nextLcpLoc; } while (sacLcpLocptr.i != RNIL); + }//Dblqh::sendAccContOp() /* ------------------------------------------------------------------------- */ @@ -11897,18 +12085,18 @@ void Dblqh::writeLogfileLab(Signal* signal) /* WRITE. */ /*---------------------------------------------------------------------------*/ switch (logFilePtr.p->fileChangeState) { -#if 0 - case LogFileRecord::BOTH_WRITES_ONGOING: - jam(); - ndbout_c("not crashing!!"); - // Fall-through -#endif case LogFileRecord::NOT_ONGOING: jam(); checkGcpCompleted(signal, ((lfoPtr.p->lfoPageNo + lfoPtr.p->noPagesRw) - 1), lfoPtr.p->lfoWordWritten); break; +#if 0 + case LogFileRecord::BOTH_WRITES_ONGOING: + jam(); + ndbout_c("not crashing!!"); + // Fall-through +#endif case LogFileRecord::WRITE_PAGE_ZERO_ONGOING: case LogFileRecord::LAST_WRITE_ONGOING: jam(); @@ -12996,20 +13184,11 @@ void Dblqh::execSTART_FRAGREQ(Signal* signal) ptrCheckGuard(tabptr, ctabrecFileSize, tablerec); if (!getFragmentrec(signal, fragId)) { - jam(); - /* ---------------------------------------------------------------------- - * FRAGMENT WAS NOT DEFINED YET. PUT IT IN. IF NO LOCAL CHECKPOINT EXISTED - * THEN THE FRAGMENT HAS ALREADY BEEN ADDED. - * ---------------------------------------------------------------------- */ - if (!insertFragrec(signal, fragId)) { - jam(); - startFragRefLab(signal); - return; - }//if + startFragRefLab(signal); + return; }//if tabptr.p->tableStatus = Tablerec::TABLE_DEFINED; - initFragrec(signal, tabptr.i, fragId, ZPRIMARY_NODE); initFragrecSr(signal); if (startFragReq->lcpNo == ZNIL) { jam(); @@ -13085,11 +13264,12 @@ void Dblqh::execSR_FRAGIDCONF(Signal* signal) Uint32 noLocFrag = srFragidConf->noLocFrag; ndbrequire(noLocFrag == 2); Uint32 fragid[2]; - for (Uint32 i = 0; i < noLocFrag; i++) { + Uint32 i; + for (i = 0; i < noLocFrag; i++) { fragid[i] = srFragidConf->fragId[i]; }//for - for (Uint32 i = 0; i < noLocFrag; i++) { + for (i = 0; i < noLocFrag; i++) { jam(); Uint32 fragId = fragid[i]; /* ---------------------------------------------------------------------- @@ -13495,14 +13675,22 @@ void Dblqh::execSTART_EXEC_SR(Signal* signal) * ALSO SEND START_FRAGCONF TO DIH AND SET THE STATE TO ACTIVE ON THE * FRAGMENT. * ------------------------------------------------------------------- */ + Uint32 next = fragptr.p->nextFrag; if (prevFragptr.i != RNIL) { jam(); ptrCheckGuard(prevFragptr, cfragrecFileSize, fragrecord); - prevFragptr.p->nextFrag = fragptr.p->nextFrag; + prevFragptr.p->nextFrag = next; } else { jam(); - cfirstCompletedFragSr = fragptr.p->nextFrag; + cfirstCompletedFragSr = next; }//if + + /** + * Put fragment on list which has completed REDO log + */ + fragptr.p->nextFrag = c_redo_log_complete_frags; + c_redo_log_complete_frags = fragptr.i; + fragptr.p->fragStatus = Fragrecord::FSACTIVE; fragptr.p->logFlag = Fragrecord::STATE_TRUE; signal->theData[0] = fragptr.p->srUserptr; @@ -13514,7 +13702,7 @@ void Dblqh::execSTART_EXEC_SR(Signal* signal) * THIS IS PERFORMED BY KEEPING PREV_FRAGPTR AS PREV_FRAGPTR BUT MOVING * FRAGPTR TO THE NEXT FRAGMENT IN THE LIST. * ------------------------------------------------------------------- */ - fragptr.i = fragptr.p->nextFrag; + fragptr.i = next; }//if signal->theData[0] = fragptr.i; signal->theData[1] = prevFragptr.i; @@ -14933,6 +15121,11 @@ void Dblqh::openSrFourthPhaseLab(Signal* signal) void Dblqh::readSrFourthPhaseLab(Signal* signal) { + if(c_diskless){ + jam(); + logPagePtr.p->logPageWord[ZPOS_LOG_LAP] = 1; + } + /* ------------------------------------------------------------------------ * INITIALISE ALL LOG PART INFO AND LOG FILE INFO THAT IS NEEDED TO * START UP THE SYSTEM. @@ -14961,6 +15154,7 @@ void Dblqh::readSrFourthPhaseLab(Signal* signal) logPartPtr.p->logLap = logPagePtr.p->logPageWord[ZPOS_LOG_LAP]; logFilePtr.p->currentFilepage = logPartPtr.p->headPageNo; logFilePtr.p->currentLogpage = logPagePtr.i; + initLogpage(signal); logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = logPartPtr.p->headPageIndex; logFilePtr.p->remainingWordsInMbyte = @@ -15120,6 +15314,17 @@ void Dblqh::srFourthComp(Signal* signal) conf->startingNodeId = getOwnNodeId(); sendSignal(cmasterDihBlockref, GSN_START_RECCONF, signal, StartRecConf::SignalLength, JBB); + + if(cstartType == NodeState::ST_SYSTEM_RESTART){ + fragptr.i = c_redo_log_complete_frags; + while(fragptr.i != RNIL){ + ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord); + signal->theData[0] = fragptr.p->tabRef; + signal->theData[1] = fragptr.p->fragId; + sendSignal(DBACC_REF, GSN_EXPANDCHECK2, signal, 2, JBB); + fragptr.i = fragptr.p->nextFrag; + } + } } else { ndbrequire(false); }//if @@ -15657,7 +15862,7 @@ void Dblqh::completedLogPage(Signal* signal, Uint32 clpType) /* ---------------------------------------------------------------- */ void Dblqh::deleteFragrec(Uint32 fragId) { - Uint32 indexFound; + Uint32 indexFound= RNIL; fragptr.i = RNIL; for (Uint32 i = (NO_OF_FRAG_PER_NODE - 1); (Uint32)~i; i--) { jam(); @@ -15810,6 +16015,7 @@ void Dblqh::initialiseAttrbuf(Signal* signal) for (attrinbufptr.i = 0; attrinbufptr.i < cattrinbufFileSize; attrinbufptr.i++) { + refresh_watch_dog(); ptrAss(attrinbufptr, attrbuf); attrinbufptr.p->attrbuf[ZINBUF_NEXT] = attrinbufptr.i + 1; }//for @@ -15832,6 +16038,7 @@ void Dblqh::initialiseDatabuf(Signal* signal) { if (cdatabufFileSize != 0) { for (databufptr.i = 0; databufptr.i < cdatabufFileSize; databufptr.i++) { + refresh_watch_dog(); ptrAss(databufptr, databuf); databufptr.p->nextDatabuf = databufptr.i + 1; }//for @@ -15853,6 +16060,7 @@ void Dblqh::initialiseFragrec(Signal* signal) { if (cfragrecFileSize != 0) { for (fragptr.i = 0; fragptr.i < cfragrecFileSize; fragptr.i++) { + refresh_watch_dog(); ptrAss(fragptr, fragrecord); fragptr.p->fragStatus = Fragrecord::FREE; fragptr.p->fragActiveStatus = ZFALSE; @@ -15985,6 +16193,7 @@ void Dblqh::initialiseLogPage(Signal* signal) { if (clogPageFileSize != 0) { for (logPagePtr.i = 0; logPagePtr.i < clogPageFileSize; logPagePtr.i++) { + refresh_watch_dog(); ptrAss(logPagePtr, logPageRecord); logPagePtr.p->logPageWord[ZNEXT_PAGE] = logPagePtr.i + 1; }//for @@ -16040,17 +16249,18 @@ void Dblqh::initialisePageRef(Signal* signal) void Dblqh::initialiseRecordsLab(Signal* signal, Uint32 data, Uint32 retRef, Uint32 retData) { + Uint32 i; switch (data) { case 0: jam(); - for (Uint32 i = 0; i < MAX_NDB_NODES; i++) { + for (i = 0; i < MAX_NDB_NODES; i++) { cnodeSrState[i] = ZSTART_SR; cnodeExecSrState[i] = ZSTART_SR; }//for - for (Uint32 i = 0; i < 1024; i++) { + for (i = 0; i < 1024; i++) { ctransidHash[i] = RNIL; }//for - for (Uint32 i = 0; i < 4; i++) { + for (i = 0; i < 4; i++) { cactiveCopy[i] = RNIL; }//for cnoActiveCopy = 0; @@ -16162,6 +16372,7 @@ void Dblqh::initialiseScanrec(Signal* signal) DLList<ScanRecord> tmp(c_scanRecordPool); while (tmp.seize(scanptr)){ //new (scanptr.p) ScanRecord(); + refresh_watch_dog(); scanptr.p->scanType = ScanRecord::ST_IDLE; scanptr.p->scanState = ScanRecord::SCAN_FREE; scanptr.p->scanTcWaiting = ZFALSE; @@ -16179,6 +16390,7 @@ void Dblqh::initialiseTabrec(Signal* signal) { if (ctabrecFileSize != 0) { for (tabptr.i = 0; tabptr.i < ctabrecFileSize; tabptr.i++) { + refresh_watch_dog(); ptrAss(tabptr, tablerec); tabptr.p->tableStatus = Tablerec::NOT_DEFINED; tabptr.p->usageCount = 0; @@ -16200,6 +16412,7 @@ void Dblqh::initialiseTcrec(Signal* signal) for (tcConnectptr.i = 0; tcConnectptr.i < ctcConnectrecFileSize; tcConnectptr.i++) { + refresh_watch_dog(); ptrAss(tcConnectptr, tcConnectionrec); tcConnectptr.p->transactionState = TcConnectionrec::TC_NOT_CONNECTED; tcConnectptr.p->tcScanRec = RNIL; @@ -16277,6 +16490,7 @@ void Dblqh::initFragrec(Signal* signal, fragptr.p->execSrNoReplicas = 0; fragptr.p->fragDistributionKey = 0; fragptr.p->activeTcCounter = 0; + fragptr.p->tableFragptr = RNIL; }//Dblqh::initFragrec() /* ========================================================================== @@ -18004,7 +18218,7 @@ Dblqh::execDUMP_STATE_ORD(Signal* signal) infoEvent(" lcpQueued=%d reportEmpty=%d", TlcpPtr.p->lcpQueued, TlcpPtr.p->reportEmpty); - char buf[TlcpPtr.p->m_EMPTY_LCP_REQ.TextLength+1]; + char buf[8*_NDB_NODE_BITMASK_SIZE+1]; infoEvent(" m_EMPTY_LCP_REQ=%d", TlcpPtr.p->m_EMPTY_LCP_REQ.getText(buf)); diff --git a/ndb/src/kernel/blocks/dbtc/Dbtc.hpp b/ndb/src/kernel/blocks/dbtc/Dbtc.hpp index c87712e1887..6e32216557c 100644 --- a/ndb/src/kernel/blocks/dbtc/Dbtc.hpp +++ b/ndb/src/kernel/blocks/dbtc/Dbtc.hpp @@ -139,6 +139,7 @@ #define ZNOT_FOUND 626 #define ZALREADYEXIST 630 #define ZINCONSISTENTHASHINDEX 892 +#define ZNOTUNIQUE 893 #endif class Dbtc: public SimulatedBlock { @@ -235,7 +236,6 @@ public: enum ReturnSignal { RS_NO_RETURN = 0, RS_TCKEYCONF = 1, - RS_TCKEYREF = 2, RS_TC_COMMITCONF = 3, RS_TCROLLBACKCONF = 4, RS_TCROLLBACKREP = 5 @@ -699,7 +699,7 @@ public: UintR lqhkeyreqrec; AbortState abortState; Uint32 buddyPtr; - Uint8 unused; + Uint8 m_exec_flag; Uint8 unused2; Uint8 takeOverRec; Uint8 currentReplicaNo; @@ -993,11 +993,94 @@ public: typedef Ptr<TableRecord> 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(){ + stopFragTimer(); + lqhBlockref = 0; + scanFragState = IDLE; + scanRec = RNIL; + } + /** + * 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<ScanFragRec> ScanFragRecPtr; + typedef LocalDLList<ScanFragRec> 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 +1140,71 @@ 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<ScanFragRec>::Head m_running_scan_frags; // Currently in LQH + union { Uint32 m_queued_count; Uint32 scanReceivedOperations; }; + DLList<ScanFragRec>::Head m_queued_scan_frags; // In TC !sent to API + DLList<ScanFragRec>::Head m_delivered_scan_frags;// Delivered to API + DLList<ScanFragRec>::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; + + // Close is ordered + bool m_close_scan_req; }; typedef Ptr<ScanRecord> 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<ScanOperationRecord> 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<ScanFragRec> ScanFragRecPtr; - /* **********************************************************************$ */ /* ******$ DATA BUFFER ******$ */ /* */ @@ -1369,6 +1362,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); @@ -1403,7 +1397,7 @@ private: void sendCompleteLqh(Signal* signal, TcConnectRecord * const regTcPtr); void sendTCKEY_FAILREF(Signal* signal, const ApiConnectRecord *); - void sendTCKEY_FAILCONF(Signal* signal, const ApiConnectRecord *); + void sendTCKEY_FAILCONF(Signal* signal, ApiConnectRecord *); void checkStartTimeout(Signal* signal); void checkStartFragTimeout(Signal* signal); void timeOutFoundFragLab(Signal* signal, Uint32 TscanConPtr); @@ -1428,23 +1422,17 @@ private: Uint32 buddyPtr, UintR transid1, UintR transid2); - void initScanOprec(Signal* signal); - void initScanrec(Signal* signal, + void initScanrec(ScanRecordPtr, const class ScanTabReq*, 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 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 releaseScanResources(ScanRecordPtr); + ScanRecordPtr seizeScanrec(Signal* signal); + void sendScanFragReq(Signal* signal, ScanRecord*, ScanFragRec*); + void sendScanTabConf(Signal* signal, ScanRecord*); + void close_scan_req(Signal*, ScanRecordPtr, bool received_req); + void close_scan_req_send_conf(Signal*, ScanRecordPtr); + void checkGcp(Signal* signal); void commitGciHandling(Signal* signal, UintR Tgci); void copyApi(Signal* signal); @@ -1473,12 +1461,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); @@ -1577,11 +1565,11 @@ private: void systemErrorLab(Signal* signal); void sendSignalErrorRefuseLab(Signal* signal); void scanTabRefLab(Signal* signal, Uint32 errCode); - void diFcountReqLab(Signal* signal); + void diFcountReqLab(Signal* signal, ScanRecordPtr); void signalErrorRefuseLab(Signal* signal); void abort080Lab(Signal* signal); void packKeyData000Lab(Signal* signal, BlockReference TBRef); - void abortScanLab(Signal* signal, Uint32 errCode); + void abortScanLab(Signal* signal, ScanRecordPtr, Uint32 errCode); void sendAbortedAfterTimeout(Signal* signal, int Tcheck); void abort010Lab(Signal* signal); void abort015Lab(Signal* signal); @@ -1609,7 +1597,7 @@ private: void attrinfo020Lab(Signal* signal); void scanReleaseResourcesLab(Signal* signal); void scanCompletedLab(Signal* signal); - void scanFragError(Signal* signal, Uint32 errorCode); + void scanError(Signal* signal, ScanRecordPtr, Uint32 errorCode); void diverify010Lab(Signal* signal); void intstartphase2x010Lab(Signal* signal); void intstartphase3x010Lab(Signal* signal); @@ -1638,6 +1626,8 @@ private: void checkScanActiveInFailedLqh(Signal* signal, Uint32 scanPtrI, Uint32 failedNodeId); + void checkScanFragList(Signal*, Uint32 failedNodeId, ScanRecord * scanP, + LocalDLList<ScanFragRec>::Head&); // Initialisation void initData(); @@ -1717,20 +1707,12 @@ private: ApiConnectRecordPtr timeOutptr; ScanRecord *scanRecord; - ScanRecordPtr scanptr; UintR cscanrecFileSize; - ScanOperationRecord *scanOperationRecord; - ScanOperationRecordPtr scanOpptr; - UintR cscanOprecFileSize; - - ScanFragRec *scanFragmentRecord; + UnsafeArrayPool<ScanFragRec> 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..6803c3609ed 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<ScanFragRec> 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,11 +287,29 @@ 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); initData(); + +#ifdef VM_TRACE + { + void* tmp[] = { &apiConnectptr, + &tcConnectptr, + &cachePtr, + &attrbufptr, + &hostptr, + &gcpPtr, + &tmpApiConnectptr, + &timeOutptr, + &scanFragptr, + &databufptr, + &tmpDatabufptr }; + init_globals_list(tmp, sizeof(tmp)/sizeof(tmp[0])); + } +#endif }//Dbtc::Dbtc() Dbtc::~Dbtc() @@ -323,17 +338,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); @@ -360,5 +365,3 @@ Dbtc::~Dbtc() BLOCK_FUNCTIONS(Dbtc); - - diff --git a/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp b/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp index 5afd79687a1..7e1db71faee 100644 --- a/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp +++ b/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp @@ -65,6 +65,7 @@ #include <signaldata/DictTabInfo.hpp> #include <NdbOut.hpp> +#include <DebuggerNames.hpp> // Use DEBUG to print messages that should be // seen only when we debug the product @@ -76,6 +77,68 @@ #define INTERNAL_TRIGGER_TCKEYREQ_JBA 0 +#ifdef VM_TRACE +NdbOut & +operator<<(NdbOut& out, Dbtc::ConnectionState state){ + switch(state){ + case Dbtc::CS_CONNECTED: out << "CS_CONNECTED"; break; + case Dbtc::CS_DISCONNECTED: out << "CS_DISCONNECTED"; break; + case Dbtc::CS_STARTED: out << "CS_STARTED"; break; + case Dbtc::CS_RECEIVING: out << "CS_RECEIVING"; break; + case Dbtc::CS_PREPARED: out << "CS_PREPARED"; break; + case Dbtc::CS_START_PREPARING: out << "CS_START_PREPARING"; break; + case Dbtc::CS_REC_PREPARING: out << "CS_REC_PREPARING"; break; + case Dbtc::CS_RESTART: out << "CS_RESTART"; break; + case Dbtc::CS_ABORTING: out << "CS_ABORTING"; break; + case Dbtc::CS_COMPLETING: out << "CS_COMPLETING"; break; + case Dbtc::CS_COMPLETE_SENT: out << "CS_COMPLETE_SENT"; break; + case Dbtc::CS_PREPARE_TO_COMMIT: out << "CS_PREPARE_TO_COMMIT"; break; + case Dbtc::CS_COMMIT_SENT: out << "CS_COMMIT_SENT"; break; + case Dbtc::CS_START_COMMITTING: out << "CS_START_COMMITTING"; break; + case Dbtc::CS_COMMITTING: out << "CS_COMMITTING"; break; + case Dbtc::CS_REC_COMMITTING: out << "CS_REC_COMMITTING"; break; + case Dbtc::CS_WAIT_ABORT_CONF: out << "CS_WAIT_ABORT_CONF"; break; + case Dbtc::CS_WAIT_COMPLETE_CONF: out << "CS_WAIT_COMPLETE_CONF"; break; + case Dbtc::CS_WAIT_COMMIT_CONF: out << "CS_WAIT_COMMIT_CONF"; break; + case Dbtc::CS_FAIL_ABORTING: out << "CS_FAIL_ABORTING"; break; + case Dbtc::CS_FAIL_ABORTED: out << "CS_FAIL_ABORTED"; break; + case Dbtc::CS_FAIL_PREPARED: out << "CS_FAIL_PREPARED"; break; + case Dbtc::CS_FAIL_COMMITTING: out << "CS_FAIL_COMMITTING"; break; + case Dbtc::CS_FAIL_COMMITTED: out << "CS_FAIL_COMMITTED"; break; + case Dbtc::CS_FAIL_COMPLETED: out << "CS_FAIL_COMPLETED"; break; + case Dbtc::CS_START_SCAN: out << "CS_START_SCAN"; break; + default: + out << "Unknown: " << (int)state; break; + } + return out; +} +NdbOut & +operator<<(NdbOut& out, Dbtc::OperationState state){ + out << (int)state; + return out; +} +NdbOut & +operator<<(NdbOut& out, Dbtc::AbortState state){ + out << (int)state; + return out; +} +NdbOut & +operator<<(NdbOut& out, Dbtc::ReturnSignal state){ + out << (int)state; + return out; +} +NdbOut & +operator<<(NdbOut& out, Dbtc::ScanRecord::ScanState state){ + out << (int)state; + return out; +} +NdbOut & +operator<<(NdbOut& out, Dbtc::ScanFragRec::ScanFragState state){ + out << (int)state; + return out; +} +#endif + void Dbtc::updateBuddyTimer(ApiConnectRecordPtr apiPtr) { @@ -110,13 +173,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(); @@ -204,6 +261,7 @@ void Dbtc::execCONTINUEB(Signal* signal) tcConnectptr.i = Tdata0; apiConnectptr.i = Tdata1; ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord); + apiConnectptr.p->counter--; sendAbortedAfterTimeout(signal, 1); return; case TcContinueB::ZHANDLE_FAILED_API_NODE_REMOVE_MARKERS: @@ -375,6 +433,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 +617,6 @@ void Dbtc::execREAD_CONFIG_REQ(Signal* signal) ctcConnectFilesize = tcConnect; ctabrecFilesize = tables; cscanrecFileSize = tcScan; - cscanOprecFileSize = localScan; cscanFragrecFileSize = localScan; initRecords(); @@ -882,7 +972,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, true); + TloopCount += 64; break; case CS_CONNECTED: @@ -952,13 +1050,12 @@ Dbtc::handleFailedApiNode(Signal* signal, apiConnectptr.i++; if (apiConnectptr.i > ((capiConnectFilesize / 3) - 1)) { jam(); - capiConnectClosing[TapiFailedNode]--; /** * Finished with scanning connection record * * Now scan markers */ - removeMarkerForFailedAPI(signal, TapiFailedNode, RNIL); // RNIL = first + removeMarkerForFailedAPI(signal, TapiFailedNode, 0); return; }//if } while (TloopCount++ < 256); @@ -973,15 +1070,26 @@ Dbtc::removeMarkerForFailedAPI(Signal* signal, Uint32 nodeId, Uint32 startBucket) { - CommitAckMarkerIterator iter; - if(startBucket == RNIL){ - jam(); - capiConnectClosing[nodeId]++; - m_commitAckMarkerHash.next(0, iter); - } else { + TcFailRecordPtr node_fail_ptr; + node_fail_ptr.i = 0; + ptrAss(node_fail_ptr, tcFailRecord); + if(node_fail_ptr.p->failStatus != FS_IDLE) { jam(); - m_commitAckMarkerHash.next(startBucket, iter); + DEBUG("Restarting removeMarkerForFailedAPI"); + /** + * TC take-over in progress + * needs to restart as this + * creates new markers + */ + signal->theData[0] = TcContinueB::ZHANDLE_FAILED_API_NODE_REMOVE_MARKERS; + signal->theData[1] = nodeId; + signal->theData[2] = 0; + sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 500, 3); + return; } + + CommitAckMarkerIterator iter; + m_commitAckMarkerHash.next(startBucket, iter); const Uint32 RT_BREAK = 256; for(Uint32 i = 0; i<RT_BREAK || iter.bucket == startBucket; i++){ @@ -1012,7 +1120,6 @@ Dbtc::removeMarkerForFailedAPI(Signal* signal, /** * Check so that the record is not still in use * - * (This can happen when NF and API Fail happens at the same time) */ ApiConnectRecordPtr apiConnectPtr; apiConnectPtr.i = iter.curr.p->apiConnectPtr; @@ -1024,9 +1131,8 @@ Dbtc::removeMarkerForFailedAPI(Signal* signal, * * Don't remove it, but continueb instead */ - break; + break; } - sendRemoveMarkers(signal, iter.curr.p); m_commitAckMarkerHash.release(iter.curr); @@ -1061,136 +1167,6 @@ void Dbtc::handleApiFailState(Signal* signal, UintR TapiConnectptr) }//if }//Dbtc::handleApiFailState() -/** - * Dbtc::handleScanStop - * This function is called when an entire scan should be stopped - * Check state of the scan and take appropriate action. - * The parameter TapiFailedNode indicates if the scan is stopped - * because an API node has failed or if it has been stopped because - * the scan has timed out. - * - */ -void Dbtc::handleScanStop(Signal* signal, UintR TapiFailedNode) -{ - arrGuard(TapiFailedNode, MAX_NODES); - - scanptr.i = apiConnectptr.p->apiScanRec; - ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord); - - // If api has failed we must release all resources - bool apiNodeHasFailed = (TapiFailedNode != 0); - - DEBUG("handleScanStop: scanState = "<< scanptr.p->scanState); - - switch (scanptr.p->scanState) { - case ScanRecord::WAIT_SCAN_TAB_INFO: - case ScanRecord::WAIT_AI: - jam(); - /** - * The scan process is still in the definition phase. - * We will release the resources and then release the connection - * to the failed API. - */ - releaseScanResources(signal); - if (apiNodeHasFailed) { - jam(); - releaseApiCon(signal, apiConnectptr.i); - }//if - break; - - case ScanRecord::WAIT_FRAGMENT_COUNT: - jam(); - if (!apiNodeHasFailed) { - jam(); - /** - * Time-out waiting for a local signal can only happen - * if we have a serious problem. - */ - systemErrorLab(signal); - }//if - capiConnectClosing[TapiFailedNode]++; - apiConnectptr.p->apiFailState = ZTRUE; - scanptr.p->apiIsClosed = true; - break; - - case ScanRecord::CLOSING_SCAN: - jam(); - /** - * With CLOSING_SCAN it is enough to set the - * fail state such that the connection is released at the end of the - * closing process. The close process is already ongoing. - * Set apiIsClosed to true to indicate that resources should be released - * at the end of the close process. - **/ - - if (apiNodeHasFailed) { - jam(); - capiConnectClosing[TapiFailedNode]++; - apiConnectptr.p->apiFailState = ZTRUE; - scanptr.p->apiIsClosed = true; - }//if - if (apiConnectptr.p->apiFailState == ZTRUE) { - jam(); - handleApiFailState(signal, apiConnectptr.i); - return; - }//if - break; - - case ScanRecord::SCAN_NEXT_ORDERED: - /** - * In the SCAN_NEXT_ORDERED state we will wait for the next natural place - * to receive some action from the API and instead of waiting for the - * API here we will start the abort process. - - * After the abort process is completed we will release the connection. - */ - if (apiNodeHasFailed) { - jam(); - capiConnectClosing[TapiFailedNode]++; - apiConnectptr.p->apiFailState = ZTRUE; - }//if - // Release resources and send a response to API - scanptr.p->apiIsClosed = true; - scanCompletedLab(signal); - break; - - case ScanRecord::DELIVERED: - case ScanRecord::QUEUED_DELIVERED: - /** - * A response has been sent to the api but it has not responded - */ - - if (apiNodeHasFailed) { - jam(); - capiConnectClosing[TapiFailedNode]++; - apiConnectptr.p->apiFailState = ZTRUE; - scanptr.p->apiIsClosed = true; - } else { - jam(); - /* - In this case we have received a time-out caused by the application - waiting too long to continue the scan. We will check the application - time-out instead of the deadlock detetection time-out. If the - application time-out hasn't fired we will simply ignore the condition. - */ - if ((ctcTimer - getApiConTimer(apiConnectptr.i)) <= c_appl_timeout_value) { - jam(); - return; - }//if - // Dont' release, wait until api responds or fails - scanptr.p->apiIsClosed = false; - } - scanCompletedLab(signal); - break; - - default: - jam(); - systemErrorLab(signal); - break; - - }//switch -}//Dbtc::handleScanStop() - /**************************************************************************** * T C S E I Z E R E Q * THE APPLICATION SENDS A REQUEST TO SEIZE A CONNECT RECORD TO CARRY OUT A @@ -1303,13 +1279,13 @@ void Dbtc::execTCRELEASEREQ(Signal* signal) jam(); /* JUST REPLY OK */ releaseApiCon(signal, apiConnectptr.i); signal->theData[0] = tuserpointer; - sendSignal(apiConnectptr.p->ndbapiBlockref, + sendSignal(tapiBlockref, GSN_TCRELEASECONF, signal, 1, JBB); } else { jam(); signal->theData[0] = tuserpointer; signal->theData[1] = ZINVALID_CONNECTION; - sendSignal(apiConnectptr.p->ndbapiBlockref, + sendSignal(tapiBlockref, GSN_TCRELEASEREF, signal, 2, JBB); } } else { @@ -1341,6 +1317,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]; @@ -1372,7 +1349,7 @@ void Dbtc::printState(Signal* signal, int place) << " counter = " << apiConnectptr.p->counter << " lqhkeyconfrec = " << apiConnectptr.p->lqhkeyconfrec << " lqhkeyreqrec = " << apiConnectptr.p->lqhkeyreqrec << endl; - ndbout << "abortState = " << (int)apiConnectptr.p->abortState + ndbout << "abortState = " << apiConnectptr.p->abortState << " apiScanRec = " << apiConnectptr.p->apiScanRec << " returncode = " << apiConnectptr.p->returncode << endl; ndbout << "tckeyrec = " << apiConnectptr.p->tckeyrec @@ -1424,6 +1401,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; @@ -1747,6 +1725,13 @@ Dbtc::TCKEY_abort(Signal* signal, int place) return; } + case 59:{ + jam(); + terrorCode = ZABORTINPROGRESS; + abortErrorLab(signal); + return; + } + default: jam(); systemErrorLab(signal); @@ -1881,7 +1866,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; @@ -2264,6 +2249,8 @@ void Dbtc::initApiConnectRec(Signal* signal, UintR Ttransid0 = tcKeyReq->transId1; UintR Ttransid1 = tcKeyReq->transId2; + regApiPtr->m_exec_flag = 0; + regApiPtr->returncode = 0; regApiPtr->returnsignal = RS_TCKEYCONF; regApiPtr->firstTcConnect = RNIL; regApiPtr->lastTcConnect = RNIL; @@ -2424,9 +2411,12 @@ void Dbtc::execTCKEYREQ(Signal* signal) apiConnectptr.p = regApiPtr; Uint32 TstartFlag = tcKeyReq->getStartFlag(Treqinfo); + Uint32 TexecFlag = TcKeyReq::getExecuteFlag(Treqinfo); + bool isIndexOp = regApiPtr->isIndexOp; bool isIndexOpReturn = regApiPtr->indexOpReturn; regApiPtr->isIndexOp = false; // Reset marker + regApiPtr->m_exec_flag |= TexecFlag; switch (regApiPtr->apiConnectstate) { case CS_CONNECTED:{ if (TstartFlag == 1 && getAllowStartTransaction() == true){ @@ -2435,6 +2425,7 @@ void Dbtc::execTCKEYREQ(Signal* signal) //--------------------------------------------------------------------- jam(); initApiConnectRec(signal, regApiPtr); + regApiPtr->m_exec_flag = TexecFlag; } else { if(getAllowStartTransaction() == true){ /*------------------------------------------------------------------ @@ -2477,14 +2468,18 @@ void Dbtc::execTCKEYREQ(Signal* signal) //-------------------------------------------------------------------- jam(); initApiConnectRec(signal, regApiPtr); - } else { + regApiPtr->m_exec_flag = TexecFlag; + } else if(TexecFlag) { + TCKEY_abort(signal, 59); + return; + } else { //-------------------------------------------------------------------- // The current transaction was aborted successfully. // We will not do anything before we receive an operation // with a start indicator. We will ignore this signal. //-------------------------------------------------------------------- - jam(); - // DEBUG("Drop TCKEYREQ - apiConnectState=CS_ABORTING, ==AS_IDLE"); + jam(); + DEBUG("Drop TCKEYREQ - apiConnectState=CS_ABORTING, ==AS_IDLE"); return; }//if } else { @@ -2499,11 +2494,14 @@ void Dbtc::execTCKEYREQ(Signal* signal) //-------------------------------------------------------------------- TCKEY_abort(signal, 2); return; - }//if + } else if(TexecFlag) { + TCKEY_abort(signal, 59); + return; + } //---------------------------------------------------------------------- // Ignore signals without start indicator set when aborting transaction. //---------------------------------------------------------------------- - // DEBUG("Drop TCKEYREQ - apiConnectState=CS_ABORTING, !=AS_IDLE"); + DEBUG("Drop TCKEYREQ - apiConnectState=CS_ABORTING, !=AS_IDLE"); return; }//if break; @@ -2593,7 +2591,7 @@ void Dbtc::execTCKEYREQ(Signal* signal) regTcPtr->triggeringOperation = TsenderData; } - if (TcKeyReq::getExecuteFlag(Treqinfo)){ + if (TexecFlag){ Uint32 currSPId = regApiPtr->currSavePointId; regApiPtr->currSavePointId = ++currSPId; } @@ -2614,7 +2612,7 @@ void Dbtc::execTCKEYREQ(Signal* signal) Uint8 TDistrGroupFlag = tcKeyReq->getDistributionGroupFlag(Treqinfo); Uint8 TDistrGroupTypeFlag = tcKeyReq->getDistributionGroupTypeFlag(Treqinfo); Uint8 TDistrKeyFlag = tcKeyReq->getDistributionKeyFlag(Treqinfo); - Uint8 TexecuteFlag = tcKeyReq->getExecuteFlag(Treqinfo); + Uint8 TexecuteFlag = TexecFlag; //RONM_TEST Disable simple reads temporarily regCachePtr->opSimple = 0; @@ -3238,7 +3236,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 +3262,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 +3294,7 @@ void Dbtc::releaseAttrinfo(Signal* signal) regApiPtr->cachePtr = RNIL; return; }//if - systemErrorLab(signal); + systemErrorLab(0); return; }//Dbtc::releaseAttrinfo() @@ -3306,7 +3304,7 @@ void Dbtc::releaseAttrinfo(Signal* signal) void Dbtc::releaseSimpleRead(Signal* signal) { unlinkReadyTcCon(signal); - releaseTcCon(signal); + releaseTcCon(); /** * No LQHKEYCONF in Simple/Dirty read @@ -3370,7 +3368,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; @@ -3724,7 +3722,7 @@ Dbtc::lqhKeyConf_checkTransactionState(Signal * signal, case CS_RECEIVING: if (TnoOfOutStanding == 0) { jam(); - sendtckeyconf(signal, 0); + sendtckeyconf(signal, 2); return; } else { if (apiConnectPtrP->tckeyrec == ZTCOPCONF_SIZE) { @@ -3783,7 +3781,7 @@ void Dbtc::sendtckeyconf(Signal* signal, UintR TcommitFlag) ptrAss(localHostptr, hostRecord); UintR TcurrLen = localHostptr.p->noOfWordsTCKEYCONF; UintR confInfo = 0; - TcKeyConf::setCommitFlag(confInfo, TcommitFlag); + TcKeyConf::setCommitFlag(confInfo, TcommitFlag == 1); TcKeyConf::setMarkerFlag(confInfo, Tmarker); const UintR TpacketLen = 6 + TopWords; regApiPtr->tckeyrec = 0; @@ -3808,7 +3806,10 @@ void Dbtc::sendtckeyconf(Signal* signal, UintR TcommitFlag) return; // No queued TcKeyConf }//if }//if - + if(TcommitFlag){ + jam(); + regApiPtr->m_exec_flag = 0; + } TcKeyConf::setNoOfOperations(confInfo, (TopWords >> 1)); if ((TpacketLen > 25) || !is_api){ TcKeyConf * const tcKeyConf = (TcKeyConf *)signal->getDataPtrSend(); @@ -4521,6 +4522,8 @@ void Dbtc::copyApi(Signal* signal) setApiConTimer(tmpApiConnectptr.i, 0, __LINE__); regTmpApiPtr->apiConnectstate = CS_CONNECTED; regTmpApiPtr->commitAckMarker = RNIL; + regTmpApiPtr->firstTcConnect = RNIL; + regTmpApiPtr->lastTcConnect = RNIL; }//Dbtc::copyApi() void Dbtc::unlinkApiConnect(Signal* signal) @@ -4787,7 +4790,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 +4844,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) { @@ -4924,7 +4927,9 @@ void Dbtc::execLQHKEYREF(Signal* signal) // The operation executed an index trigger const Uint32 opType = regTcPtr->operation; - if (!(opType == ZDELETE && errCode == ZNOT_FOUND)) { + if (errCode == ZALREADYEXIST) + errCode = terrorCode = ZNOTUNIQUE; + else if (!(opType == ZDELETE && errCode == ZNOT_FOUND)) { jam(); /** * "Normal path" @@ -4942,7 +4947,7 @@ void Dbtc::execLQHKEYREF(Signal* signal) regApiPtr->lqhkeyconfrec++; unlinkReadyTcCon(signal); - releaseTcCon(signal); + releaseTcCon(); opPtr.p->triggerExecutionCount--; if (opPtr.p->triggerExecutionCount == 0) { @@ -4958,6 +4963,7 @@ void Dbtc::execLQHKEYREF(Signal* signal) } } + Uint32 marker = regTcPtr->commitAckMarker; markOperationAborted(regApiPtr, regTcPtr); if(regApiPtr->apiConnectstate == CS_ABORTING){ @@ -4977,7 +4983,7 @@ void Dbtc::execLQHKEYREF(Signal* signal) return; }//if - if (regTcPtr->commitAckMarker != RNIL){ + if (marker != RNIL){ /** * This was an insert/update/delete/write which failed * that contained the marker @@ -4998,12 +5004,15 @@ 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(); + regApiPtr->lqhkeyreqrec--; // Compensate for extra during read tcKeyRef->connectPtr = indexOp; EXECUTE_DIRECT(DBTC, GSN_TCKEYREF, signal, TcKeyRef::SignalLength); + apiConnectptr.i = regTcPtr->apiConnect; + apiConnectptr.p = regApiPtr; } else { jam(); tcKeyRef->connectPtr = clientData; @@ -5041,11 +5050,11 @@ void Dbtc::execLQHKEYREF(Signal* signal) jam(); diverify010Lab(signal); return; - } else if (regApiPtr->tckeyrec > 0) { + } else if (regApiPtr->tckeyrec > 0 || regApiPtr->m_exec_flag) { jam(); - sendtckeyconf(signal, 0); + sendtckeyconf(signal, 2); return; - }//if + } }//if return; @@ -5140,8 +5149,8 @@ void Dbtc::execTC_COMMITREQ(Signal* signal) // We will abort it instead. /*******************************************************************/ regApiPtr->returnsignal = RS_NO_RETURN; - abort010Lab(signal); errorCode = ZTRANS_STATUS_ERROR; + abort010Lab(signal); }//if } else { jam(); @@ -5167,8 +5176,8 @@ void Dbtc::execTC_COMMITREQ(Signal* signal) // transaction. We will abort it instead. /***********************************************************************/ regApiPtr->returnsignal = RS_NO_RETURN; - abort010Lab(signal); errorCode = ZPREPAREINPROGRESS; + abort010Lab(signal); break; case CS_START_COMMITTING: @@ -5243,6 +5252,7 @@ void Dbtc::execTCROLLBACKREQ(Signal* signal) return; }//if + apiConnectptr.p->m_exec_flag = 1; switch (apiConnectptr.p->apiConnectstate) { case CS_STARTED: case CS_RECEIVING: @@ -5278,8 +5288,9 @@ void Dbtc::execTCROLLBACKREQ(Signal* signal) signal->theData[1] = apiConnectptr.p->transid[0]; signal->theData[2] = apiConnectptr.p->transid[1]; signal->theData[3] = ZROLLBACKNOTALLOWED; + signal->theData[4] = apiConnectptr.p->apiConnectstate; sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_TCROLLBACKREF, - signal, 4, JBB); + signal, 5, JBB); break; /* SEND A REFUSAL SIGNAL*/ case CS_ABORTING: @@ -5700,7 +5711,10 @@ void Dbtc::abortErrorLab(Signal* signal) return; } transP->returnsignal = RS_TCROLLBACKREP; - transP->returncode = terrorCode; + if(transP->returncode == 0){ + jam(); + transP->returncode = terrorCode; + } abort010Lab(signal); }//Dbtc::abortErrorLab() @@ -6027,8 +6041,12 @@ void Dbtc::timeOutFoundLab(Signal* signal, Uint32 TapiConPtr) /* THIS TRANSACTION HAVE EXPERIENCED A TIME-OUT AND WE NEED TO*/ /* FIND OUT WHAT WE NEED TO DO BASED ON THE STATE INFORMATION.*/ /*------------------------------------------------------------------*/ - DEBUG("Time-out in state = " << apiConnectptr.p->apiConnectstate - << " apiConnectptr.i = " << apiConnectptr.i); + DEBUG("[ H'" << hex << apiConnectptr.p->transid[0] + << " H'" << apiConnectptr.p->transid[1] << "] " << dec + << "Time-out in state = " << apiConnectptr.p->apiConnectstate + << " apiConnectptr.i = " << apiConnectptr.i + << " - exec: " << apiConnectptr.p->m_exec_flag + << " - place: " << c_apiConTimer_line[apiConnectptr.i]); switch (apiConnectptr.p->apiConnectstate) { case CS_STARTED: if(apiConnectptr.p->lqhkeyreqrec == apiConnectptr.p->lqhkeyconfrec){ @@ -6042,11 +6060,8 @@ void Dbtc::timeOutFoundLab(Signal* signal, Uint32 TapiConPtr) jam(); return; }//if - apiConnectptr.p->returnsignal = RS_NO_RETURN; - } else { - jam(); - apiConnectptr.p->returnsignal = RS_TCROLLBACKREP; } + apiConnectptr.p->returnsignal = RS_TCROLLBACKREP; apiConnectptr.p->returncode = ZTIME_OUT_ERROR; abort010Lab(signal); return; @@ -6125,11 +6140,14 @@ void Dbtc::timeOutFoundLab(Signal* signal, Uint32 TapiConPtr) tcConnectptr.i = apiConnectptr.p->firstTcConnect; sendAbortedAfterTimeout(signal, 0); break; - case CS_START_SCAN: + case CS_START_SCAN:{ jam(); - apiConnectptr.p->returncode = ZSCANTIME_OUT_ERROR; - handleScanStop(signal, 0); + ScanRecordPtr scanPtr; + scanPtr.i = apiConnectptr.p->apiScanRec; + ptrCheckGuard(scanPtr, cscanrecFileSize, scanRecord); + scanError(signal, scanPtr, ZSCANTIME_OUT_ERROR); break; + } case CS_WAIT_ABORT_CONF: jam(); tcConnectptr.i = apiConnectptr.p->currentTcConnect; @@ -6289,9 +6307,8 @@ void Dbtc::sendAbortedAfterTimeout(Signal* signal, int Tcheck) warningEvent(buf); ndbout_c(buf); ndbrequire(false); - releaseAbortResources(signal); - return; - }//if + } + releaseAbortResources(signal); return; }//if TloopCount++; @@ -6302,6 +6319,7 @@ void Dbtc::sendAbortedAfterTimeout(Signal* signal, int Tcheck) // away the job buffer. /*------------------------------------------------------------------*/ setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__); + apiConnectptr.p->counter++; signal->theData[0] = TcContinueB::ZABORT_TIMEOUT_BREAK; signal->theData[1] = tcConnectptr.i; signal->theData[2] = apiConnectptr.i; @@ -6396,7 +6414,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; @@ -6408,14 +6426,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; @@ -6467,7 +6485,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) { @@ -6483,6 +6501,7 @@ void Dbtc::timeOutLoopStartFragLab(Signal* signal, Uint32 TscanConPtr) }//if }//for ctimeOutCheckFragActive = TOCS_FALSE; + return; }//timeOutLoopStartFragLab() @@ -6495,19 +6514,17 @@ 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: DEBUG("execSCAN_HBREP: scanFragState="<<scanFragptr.p->scanFragState); systemErrorLab(signal); break; } + ScanRecordPtr scanptr; scanptr.i = scanFragptr.p->scanRec; ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord); @@ -6538,6 +6555,7 @@ void Dbtc::execSCAN_HBREP(Signal* signal) updateBuddyTimer(apiConnectptr); scanFragptr.p->startFragTimer(ctcTimer); } else { + ndbassert(false); DEBUG("SCAN_HBREP when scanFragTimer was turned off"); } }//execSCAN_HBREP() @@ -6548,62 +6566,50 @@ void Dbtc::execSCAN_HBREP(Signal* signal) /*--------------------------------------------------------------------------*/ void Dbtc::timeOutFoundFragLab(Signal* signal, UintR TscanConPtr) { - scanFragptr.i = TscanConPtr; - ptrAss(scanFragptr, scanFragmentRecord); - DEBUG("timeOutFoundFragLab: scanFragState = "<<scanFragptr.p->scanFragState); + ScanFragRecPtr ptr; + c_scan_frag_pool.getPtr(ptr, TscanConPtr); + DEBUG(TscanConPtr << " timeOutFoundFragLab: scanFragState = "<< ptr.p->scanFragState); /*-------------------------------------------------------------------------*/ // The scan fragment has expired its timeout. Check its state to decide // what to do. /*-------------------------------------------------------------------------*/ - switch (scanFragptr.p->scanFragState) { - + switch (ptr.p->scanFragState) { case ScanFragRec::WAIT_GET_PRIMCONF: jam(); - // Crash the system if we do not return from DIGETPRIMREQ in time. - systemErrorLab(signal); + ndbrequire(false); break; - - case ScanFragRec::LQH_ACTIVE: + case ScanFragRec::LQH_ACTIVE:{ jam(); + /** * The LQH expired it's timeout, try to close it */ - scanFragError(signal, ZSCAN_FRAG_LQH_ERROR); - DEBUG(" LQH_ACTIVE - closing the fragment scan in node " - <<scanFragptr.p->scanFragNodeId); - 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"); + Uint32 nodeId = refToNode(ptr.p->lqhBlockref); + Uint32 connectCount = getNodeInfo(nodeId).m_connectCount; + ScanRecordPtr scanptr; + scanptr.i = ptr.p->scanRec; + ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord); + + if(connectCount != ptr.p->m_connectCount){ + jam(); + /** + * The node has died + */ + ptr.p->scanFragState = ScanFragRec::COMPLETED; + 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(ptr); + comp.add(ptr); + ptr.p->stopFragTimer(); } - scanFragptr.p->stopFragTimer(); + + scanError(signal, scanptr, ZSCAN_FRAG_LQH_ERROR); break; } - case ScanFragRec::DELIVERED: jam(); - case ScanFragRec::RETURNING_FROM_DELIVERY: - jam(); case ScanFragRec::IDLE: jam(); case ScanFragRec::QUEUED_FOR_DELIVERY: @@ -6725,7 +6731,8 @@ void Dbtc::execNODE_FAILREP(Signal* signal) tcNodeFailptr.i = 0; ptrAss(tcNodeFailptr, tcFailRecord); - for (Uint32 tindex = 0; tindex < tnoOfNodes; tindex++) { + Uint32 tindex; + for (tindex = 0; tindex < tnoOfNodes; tindex++) { jam(); hostptr.i = cdata[tindex]; ptrCheckGuard(hostptr, chostFilesize, hostRecord); @@ -6842,8 +6849,7 @@ void Dbtc::execNODE_FAILREP(Signal* signal) }//if }//for }//if - - for (Uint32 tindex = 0; tindex < tnoOfNodes; tindex++) { + for (tindex = 0; tindex < tnoOfNodes; tindex++) { jam(); hostptr.i = cdata[tindex]; ptrCheckGuard(hostptr, chostFilesize, hostRecord); @@ -6859,47 +6865,41 @@ void Dbtc::execNODE_FAILREP(Signal* signal) }//Dbtc::execNODE_FAILREP() void Dbtc::checkScanActiveInFailedLqh(Signal* signal, - Uint32 scanPtrI, - Uint32 failedNodeId){ + Uint32 scanPtrI, + Uint32 failedNodeId){ + ScanRecordPtr scanptr; for (scanptr.i = scanPtrI; scanptr.i < cscanrecFileSize; scanptr.i++) { jam(); ptrAss(scanptr, scanRecord); + bool found = false; 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(); + ScanFragRecPtr ptr; + ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags); + ScanFragList comp(c_scan_frag_pool, scanptr.p->m_completed_scan_frags); + + for(run.first(ptr); !ptr.isNull(); ){ + jam(); + ScanFragRecPtr curr = ptr; + run.next(ptr); + if (curr.p->scanFragState == ScanFragRec::LQH_ACTIVE && + refToNode(curr.p->lqhBlockref) == failedNodeId){ 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); - - // 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 + + run.remove(curr); + comp.add(curr); + curr.p->scanFragState = ScanFragRec::COMPLETED; + curr.p->stopFragTimer(); + found = true; + } + } + } + if(found){ + jam(); + scanError(signal, scanptr, ZSCAN_LQH_ERROR); + } - } //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 @@ -6909,6 +6909,15 @@ void Dbtc::checkScanActiveInFailedLqh(Signal* signal, }//for } +void +Dbtc::checkScanFragList(Signal* signal, + Uint32 failedNodeId, + ScanRecord * scanP, + ScanFragList::Head & head){ + + DEBUG("checkScanActiveInFailedLqh: scanFragError"); +} + void Dbtc::execTAKE_OVERTCCONF(Signal* signal) { jamEntry(); @@ -7336,25 +7345,23 @@ Dbtc::sendTCKEY_FAILREF(Signal* signal, const ApiConnectRecord * regApiPtr){ } void -Dbtc::sendTCKEY_FAILCONF(Signal* signal, const ApiConnectRecord * regApiPtr){ +Dbtc::sendTCKEY_FAILCONF(Signal* signal, ApiConnectRecord * regApiPtr){ jam(); TcKeyFailConf * const failConf = (TcKeyFailConf *)&signal->theData[0]; - if(regApiPtr->commitAckMarker == RNIL){ - jam(); - failConf->apiConnectPtr = regApiPtr->ndbapiConnect; - } else { - jam(); - failConf->apiConnectPtr = regApiPtr->ndbapiConnect | 1; + const Uint32 ref = regApiPtr->ndbapiBlockref; + const Uint32 marker = regApiPtr->commitAckMarker; + if(ref != 0){ + failConf->apiConnectPtr = regApiPtr->ndbapiConnect | (marker != RNIL); + failConf->transId1 = regApiPtr->transid[0]; + failConf->transId2 = regApiPtr->transid[1]; + + sendSignal(regApiPtr->ndbapiBlockref, + GSN_TCKEY_FAILCONF, signal, TcKeyFailConf::SignalLength, JBB); } - failConf->transId1 = regApiPtr->transid[0]; - failConf->transId2 = regApiPtr->transid[1]; - - sendSignal(regApiPtr->ndbapiBlockref, - GSN_TCKEY_FAILCONF, signal, TcKeyFailConf::SignalLength, JBB); + regApiPtr->commitAckMarker = RNIL; } - /*------------------------------------------------------------*/ /* THIS PART HANDLES THE ABORT PHASE IN THE CASE OF A */ /* NODE FAILURE BEFORE THE COMMIT DECISION. */ @@ -8415,10 +8422,17 @@ 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; + ScanRecordPtr scanptr; + + if(noOprecPerFrag == 0){ + jam(); + scanParallel = (scanConcurrency + 15) / 16; + noOprecPerFrag = (scanConcurrency >= 16 ? 16 : scanConcurrency & 15); + } jamEntry(); apiConnectptr.i = scanTabReq->apiConnectPtr; @@ -8433,12 +8447,13 @@ void Dbtc::execSCAN_TABREQ(Signal* signal) return; }//if ptrAss(apiConnectptr, apiConnectRecord); + ApiConnectRecord * transP = apiConnectptr.p; - if (apiConnectptr.p->apiConnectstate != CS_CONNECTED) { + if (transP->apiConnectstate != CS_CONNECTED) { jam(); // could be left over from TCKEYREQ rollback - if (apiConnectptr.p->apiConnectstate == CS_ABORTING && - apiConnectptr.p->abortState == AS_IDLE) { + if (transP->apiConnectstate == CS_ABORTING && + transP->abortState == AS_IDLE) { jam(); } else { jam(); @@ -8469,43 +8484,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; @@ -8521,22 +8512,39 @@ void Dbtc::execSCAN_TABREQ(Signal* signal) if ((transid1 == buddyApiPtr.p->transid[0]) && (transid2 == buddyApiPtr.p->transid[1])) { jam(); + + if (buddyApiPtr.p->apiConnectstate == CS_ABORTING) { + // transaction has been aborted + jam(); + errCode = buddyApiPtr.p->returncode; + goto SCAN_TAB_error; + }//if currSavePointId = buddyApiPtr.p->currSavePointId; buddyApiPtr.p->currSavePointId++; } } seizeTcConnect(signal); + tcConnectptr.p->apiConnect = apiConnectptr.i; + seizeCacheRecord(signal); - seizeScanrec(signal); - initScanrec(signal, scanParallel, noOprecPerFrag); - initScanTcrec(signal); - initScanApirec(signal, buddyPtr, transid1, transid2); - cnoFreeScanOprec = cnoFreeScanOprec - scanParallel; + scanptr = seizeScanrec(signal); + + ndbrequire(transP->apiScanRec == RNIL); + ndbrequire(scanptr.p->scanApiRec == RNIL); + + initScanrec(scanptr, scanTabReq, scanParallel, noOprecPerFrag); + + //initScanApirec(signal, buddyPtr, transid1, transid2); + transP->apiScanRec = scanptr.i; + transP->returncode = 0; + transP->transid[0] = transid1; + transP->transid[1] = transid2; + transP->buddyPtr = buddyPtr; // The scan is started - apiConnectptr.p->apiConnectstate = CS_START_SCAN; - apiConnectptr.p->currSavePointId = currSavePointId; + transP->apiConnectstate = CS_START_SCAN; + transP->currSavePointId = currSavePointId; /********************************************************** * We start the timer on scanRec to be able to discover a @@ -8544,11 +8552,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 @@ -8564,48 +8568,28 @@ void Dbtc::execSCAN_TABREQ(Signal* signal) SCAN_TAB_error: jam(); ScanTabRef * ref = (ScanTabRef*)&signal->theData[0]; - ref->apiConnectPtr = apiConnectptr.p->ndbapiConnect; + ref->apiConnectPtr = transP->ndbapiConnect; ref->transId1 = transid1; ref->transId2 = transid2; ref->errorCode = errCode; - sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_SCAN_TABREF, + ref->closeNeeded = 0; + sendSignal(transP->ndbapiBlockref, GSN_SCAN_TABREF, signal, ScanTabRef::SignalLength, JBB); 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) { - ApiConnectRecord * apiPtr = apiConnectptr.p; - apiPtr->apiScanRec = scanptr.i; - apiPtr->returncode = 0; - apiPtr->transid[0] = transid1; - apiPtr->transid[1] = transid2; - apiPtr->buddyPtr = buddyPtr; - }//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, +void Dbtc::initScanrec(ScanRecordPtr scanptr, + const ScanTabReq * scanTabReq, UintR scanParallel, UintR noOprecPerFrag) { - const ScanTabReq * const scanTabReq = (ScanTabReq *)&signal->theData[0]; const UintR reqinfo = scanTabReq->requestInfo; ndbrequire(scanParallel < 16); @@ -8615,34 +8599,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) @@ -8652,68 +8628,18 @@ void Dbtc::scanTabRefLab(Signal* signal, Uint32 errCode) ref->transId1 = apiConnectptr.p->transid[0]; ref->transId2 = apiConnectptr.p->transid[1]; ref->errorCode = errCode; + ref->closeNeeded = 0; sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_SCAN_TABREF, 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. */ /*---------------------------------------------------------------------------*/ void Dbtc::scanAttrinfoLab(Signal* signal, UintR Tlen) { + ScanRecordPtr scanptr; scanptr.i = apiConnectptr.p->apiScanRec; ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord); tcConnectptr.i = scanptr.p->scanTcrec; @@ -8743,7 +8669,7 @@ void Dbtc::scanAttrinfoLab(Signal* signal, UintR Tlen) * THIS SCAN. WE ARE READY TO START THE ACTUAL * EXECUTION OF THE SCAN QUERY **************************************************/ - diFcountReqLab(signal); + diFcountReqLab(signal, scanptr); return; }//if }//if @@ -8751,21 +8677,21 @@ void Dbtc::scanAttrinfoLab(Signal* signal, UintR Tlen) scanAttrinfo_attrbuf_error: jam(); - abortScanLab(signal, ZGET_ATTRBUF_ERROR); + abortScanLab(signal, scanptr, ZGET_ATTRBUF_ERROR); return; scanAttrinfo_attrbuf2_error: jam(); - abortScanLab(signal, ZGET_ATTRBUF_ERROR); + abortScanLab(signal, scanptr, ZGET_ATTRBUF_ERROR); return; scanAttrinfo_len_error: jam(); - abortScanLab(signal, ZLENGTH_ERROR); + abortScanLab(signal, scanptr, ZLENGTH_ERROR); return; }//Dbtc::scanAttrinfoLab() -void Dbtc::diFcountReqLab(Signal* signal) +void Dbtc::diFcountReqLab(Signal* signal, ScanRecordPtr scanptr) { /** * Check so that the table is not being dropped @@ -8776,7 +8702,8 @@ void Dbtc::diFcountReqLab(Signal* signal) if (tabPtr.p->checkTable(scanptr.p->scanSchemaVersion)){ ; } else { - abortScanLab(signal, tabPtr.p->getErrorCode(scanptr.p->scanSchemaVersion)); + abortScanLab(signal, scanptr, + tabPtr.p->getErrorCode(scanptr.p->scanSchemaVersion)); return; } @@ -8808,18 +8735,19 @@ void Dbtc::execDI_FCOUNTCONF(Signal* signal) ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord); apiConnectptr.i = tcConnectptr.p->apiConnect; ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord); + ScanRecordPtr scanptr; scanptr.i = apiConnectptr.p->apiScanRec; ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord); ndbrequire(scanptr.p->scanState == ScanRecord::WAIT_FRAGMENT_COUNT); if (apiConnectptr.p->apiFailState == ZTRUE) { jam(); - releaseScanResources(signal); + releaseScanResources(scanptr); handleApiFailState(signal, apiConnectptr.i); return; }//if if (tfragCount == 0) { jam(); - abortScanLab(signal, ZNO_FRAGMENT_ERROR); + abortScanLab(signal, scanptr, ZNO_FRAGMENT_ERROR); return; }//if @@ -8832,35 +8760,43 @@ void Dbtc::execDI_FCOUNTCONF(Signal* signal) if (tabPtr.p->checkTable(scanptr.p->scanSchemaVersion)){ ; } else { - abortScanLab(signal, tabPtr.p->getErrorCode(scanptr.p->scanSchemaVersion)); + abortScanLab(signal, scanptr, + tabPtr.p->getErrorCode(scanptr.p->scanSchemaVersion)); 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, scanptr, 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; + scanptr.p->scanState = ScanRecord::RUNNING; + 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(); + + ptr.p->lqhBlockref = 0; + 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() /****************************************************** @@ -8874,140 +8810,60 @@ void Dbtc::execDI_FCOUNTREF(Signal* signal) const Uint32 errCode = signal->theData[1]; apiConnectptr.i = tcConnectptr.p->apiConnect; ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord); + ScanRecordPtr scanptr; scanptr.i = apiConnectptr.p->apiScanRec; ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord); ndbrequire(scanptr.p->scanState == ScanRecord::WAIT_FRAGMENT_COUNT); if (apiConnectptr.p->apiFailState == ZTRUE) { jam(); - releaseScanResources(signal); + releaseScanResources(scanptr); handleApiFailState(signal, apiConnectptr.i); return; }//if - abortScanLab(signal, errCode); + abortScanLab(signal, scanptr, errCode); }//Dbtc::execDI_FCOUNTREF() -void Dbtc::abortScanLab(Signal* signal, Uint32 errCode) +void Dbtc::abortScanLab(Signal* signal, ScanRecordPtr scanptr, 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) { 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()); + + + ndbassert(scanPtr.p->scanApiRec == apiConnectptr.i); + ndbassert(apiConnectptr.p->apiScanRec == scanPtr.i); + + // link into free list + scanPtr.p->nextScan = cfirstfreeScanrec; + scanPtr.p->scanState = ScanRecord::IDLE; + scanPtr.p->scanTcrec = RNIL; + scanPtr.p->scanApiRec = 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 * @@ -9020,15 +8876,15 @@ 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; - + + ScanRecordPtr scanptr; scanptr.i = scanFragptr.p->scanRec; ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord); @@ -9042,7 +8898,12 @@ void Dbtc::execDIGETPRIMCONF(Signal* signal) Uint32 schemaVersion = scanptr.p->scanSchemaVersion; if(tabPtr.p->checkTable(schemaVersion) == false){ jam(); - scanFragError(signal, tabPtr.p->getErrorCode(schemaVersion)); + 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); + scanError(signal, scanptr, tabPtr.p->getErrorCode(schemaVersion)); return; } } @@ -9057,18 +8918,24 @@ 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); + sendScanFragReq(signal, scanptr.p, scanFragptr.p); attrbufptr.i = cachePtr.p->firstAttrbuf; while (attrbufptr.i != RNIL) { jam(); @@ -9076,12 +8943,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 @@ -9101,9 +8968,20 @@ 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); + + ScanRecordPtr scanptr; + scanptr.i = scanFragptr.p->scanRec; + ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord); + + 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); + + scanError(signal, scanptr, errCode); }//Dbtc::execDIGETPRIMREF() /** @@ -9120,8 +8998,9 @@ 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); + ScanRecordPtr scanptr; scanptr.i = scanFragptr.p->scanRec; ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord); @@ -9141,56 +9020,64 @@ 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); + ndbrequire(scanFragptr.p->scanFragState == ScanFragRec::LQH_ACTIVE); + { + scanFragptr.p->scanFragState = ScanFragRec::COMPLETED; + 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); + scanFragptr.p->stopFragTimer(); + } + scanError(signal, scanptr, errCode); }//Dbtc::execSCAN_FRAGREF() /** - * Dbtc::scanFragError + * Dbtc::scanError * * Called when an error occurs during - * a scan of a fragment. - * NOTE that one scan may consist of several fragment scans. - * */ -void Dbtc::scanFragError(Signal* signal, Uint32 errorCode) +void Dbtc::scanError(Signal* signal, ScanRecordPtr scanptr, Uint32 errorCode) { jam(); - scanptr.i = scanFragptr.p->scanRec; - ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord); - DEBUG("scanFragError, errorCode = "<< errorCode - << ", scanState = " << scanptr.p->scanState); - - scanFragptr.p->stopFragTimer(); + ScanRecord* scanP = scanptr.p; + + DEBUG("scanError, errorCode = "<< errorCode << + ", scanState = " << scanptr.p->scanState); - apiConnectptr.i = scanptr.p->scanApiRec; + apiConnectptr.i = scanP->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 + ndbrequire(apiConnectptr.p->apiScanRec == scanptr.i); - // If close of the scan is not already started - if (scanptr.p->scanState != ScanRecord::CLOSING_SCAN) { + if(scanP->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); + close_scan_req_send_conf(signal, scanptr); return; - }//if -}//Dbtc::scanFragError() - + } + + ndbrequire(scanP->scanState == ScanRecord::RUNNING); + + /** + * Close scan wo/ having received an order to do so + */ + close_scan_req(signal, scanptr, false); + + const bool apiFail = (apiConnectptr.p->apiFailState == ZTRUE); + if(apiFail){ + jam(); + return; + } + + 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 = errorCode; + ref->closeNeeded = 1; + sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_SCAN_TABREF, + signal, ScanTabRef::SignalLength, JBB); +}//Dbtc::scanError() /************************************************************ * execSCAN_FRAGCONF @@ -9205,14 +9092,13 @@ void Dbtc::execSCAN_FRAGCONF(Signal* signal) const ScanFragConf * const conf = (ScanFragConf*)&signal->theData[0]; const Uint32 noCompletedOps = conf->completedOps; - for(Uint32 i = 0; i<noCompletedOps; i++) - cdata[i] = conf->opReturnDataLen[i]; scanFragptr.i = conf->senderData; - ptrCheckGuard(scanFragptr, cscanFragrecFileSize, scanFragmentRecord); - + c_scan_frag_pool.getPtr(scanFragptr); + + ScanRecordPtr scanptr; scanptr.i = scanFragptr.p->scanRec; ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord); - + apiConnectptr.i = scanptr.p->scanApiRec; ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord); @@ -9223,270 +9109,79 @@ void Dbtc::execSCAN_FRAGCONF(Signal* signal) jam(); systemErrorLab(signal); }//if - - scanFragptr.p->scanFragCompletedStatus = conf->fragmentCompleted; - scanFragptr.p->stopFragTimer(); - - switch (scanFragptr.p->scanFragCompletedStatus) { - case ZFALSE: - case ZTRUE: - jam(); - /* empty */ - break; - - 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: + + ndbrequire(scanFragptr.p->scanFragState == ScanFragRec::LQH_ACTIVE); + + const Uint32 status = conf->fragmentCompleted; + + if(scanptr.p->scanState == ScanRecord::CLOSING_SCAN){ 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; + if(status == ZFALSE){ + /** + * We have started closing = we sent a close -> ignore this + */ 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) { + } else { 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. - **************************************************/ + 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); + scanFragptr.p->stopFragTimer(); + scanFragptr.p->scanFragState = ScanFragRec::COMPLETED; + } + close_scan_req_send_conf(signal, scanptr); 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(); + if(status == ZCLOSED && scanptr.p->scanNextFragId < scanptr.p->scanNoFrag){ /** - * THE SENDING NODE IS OUT OF ORDER WE WILL KILL IT BY SENDING SYSTEM - * ERROR TO IT + * Start on next fragment */ - 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; - 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 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(); + ndbrequire(noCompletedOps == 0); + scanFragptr.p->scanFragState = ScanFragRec::WAIT_GET_PRIMCONF; + scanFragptr.p->startFragTimer(ctcTimer); - scanptr.i = signal->theData[0]; - ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord); - scanptr.p->scanProcessesCompleted++; - ndbassert(scanptr.p->scanProcessesCompleted <= scanptr.p->scanParallel); + 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; i<noCompletedOps; i++){ + Uint32 tmp = conf->opReturnDataLen[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.i = signal->theData[1]; - ptrCheckGuard(scanFragptr, cscanFragrecFileSize, scanFragmentRecord); + 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(); - scanFragptr.p->scanFragState = ScanFragRec::COMPLETED; - - if (scanptr.p->scanProcessesCompleted == scanptr.p->scanParallel) { + + if(scanptr.p->m_queued_count > /** Min */ 0){ 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: - 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 + sendScanTabConf(signal, scanptr.p); } -}//Dbtc::execSCAN_PROCCONF() - +}//Dbtc::execSCAN_FRAGCONF() /**************************************************************************** * execSCAN_NEXTREQ @@ -9522,6 +9217,7 @@ void Dbtc::execSCAN_NEXTREQ(Signal* signal) ref->transId1 = transid1; ref->transId2 = transid2; ref->errorCode = ZSTATE_ERROR; + ref->closeNeeded = 0; sendSignal(signal->senderBlockRef(), GSN_SCAN_TABREF, signal, ScanTabRef::SignalLength, JBB); DEBUG("Wrong transid"); @@ -9546,358 +9242,340 @@ void Dbtc::execSCAN_NEXTREQ(Signal* signal) } DEBUG("scanTabRefLab: ZSTATE_ERROR"); DEBUG(" apiConnectstate="<<apiConnectptr.p->apiConnectstate); + ndbrequire(false); //B2 indication of strange things going on scanTabRefLab(signal, ZSTATE_ERROR); return; }//if - + /******************************************************* * START THE ACTUAL LOGIC OF SCAN_NEXTREQ. ********************************************************/ // Stop the timer that is used to check for timeout in the API setApiConTimer(apiConnectptr.i, 0, __LINE__); + ScanRecordPtr scanptr; 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="<<apiConnectptr.p->apiConnectstate); - DEBUG(" scanState="<<scanptr.p->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, true); 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++) { + if (scanptr.p->scanState == ScanRecord::CLOSING_SCAN){ 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 - - 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. - *********************************************************************/ - jam(); - sendScanTabConf(signal); - scanptr.p->scanState = 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 */ + /** + * The scan is closing (typically due to error) + * but the API hasn't understood it yet + * + * Wait for API close request + */ return; - default: + } + + // Copy op ptrs so I dont overwrite them when sending... + memcpy(signal->getDataPtrSend()+25, signal->getDataPtr()+4, 4 * len); + + 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 ; i<len; i++){ jam(); - systemErrorLab(signal); - return; - }//switch + 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); + + scanFragptr.p->m_ops = 0; + nextReq->senderData = scanFragptr.i; + sendSignal(scanFragptr.p->lqhBlockref, GSN_SCAN_NEXTREQ, signal, + ScanFragNextReq::SignalLength, JBB); + delivered.remove(scanFragptr); + running.add(scanFragptr); + }//for + }//Dbtc::execSCAN_NEXTREQ() -void Dbtc::scanCompletedLab(Signal* signal) { - scanptr.p->scanReceivedOperations = 0; - scanptr.p->scanState = ScanRecord::CLOSING_SCAN; +void +Dbtc::close_scan_req(Signal* signal, ScanRecordPtr scanPtr, bool req_received){ - // 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); + ScanRecord* scanP = scanPtr.p; + ndbrequire(scanPtr.p->scanState != ScanRecord::IDLE); + scanPtr.p->scanState = ScanRecord::CLOSING_SCAN; + scanPtr.p->m_close_scan_req = req_received; + + /** + * Queue : Action + * ============= : ================= + * completed : - + * running : close -> LQH + * delivered w/ : close -> LQH + * delivered wo/ : move to completed + * queued w/ : close -> LQH + * queued wo/ : move to completed + */ + + 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); + ScanFragList queued(c_scan_frag_pool, scanP->m_queued_scan_frags); - if (scanFragptr.p->lqhBlockref == RNIL){ - // The connection to this LQH has been closed - jam(); - continue; + // Close running + for(running.first(ptr); !ptr.isNull(); ){ + ScanFragRecPtr curr = ptr; // Remove while iterating... + running.next(ptr); + + if(curr.p->scanFragState == ScanFragRec::WAIT_GET_PRIMCONF){ + jam(); + continue; + } + ndbrequire(curr.p->scanFragState == ScanFragRec::LQH_ACTIVE); + + curr.p->startFragTimer(ctcTimer); + curr.p->scanFragState = ScanFragRec::LQH_ACTIVE; + nextReq->senderData = curr.i; + sendSignal(curr.p->lqhBlockref, GSN_SCAN_NEXTREQ, signal, + ScanFragNextReq::SignalLength, JBB); } - - if (scanFragptr.p->scanFragCompletedStatus == ZCLOSED){ - // The fragment scan is already completed + + // Close delivered + for(delivered.first(ptr); !ptr.isNull(); ){ 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; + 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); + + } else { + jam(); + completed.add(curr); + curr.p->scanFragState = ScanFragRec::COMPLETED; + curr.p->stopFragTimer(); + } + }//for + + /** + * All queued with data should be closed + */ + 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); + } else { + jam(); + completed.add(curr); + curr.p->scanFragState = ScanFragRec::COMPLETED; + curr.p->stopFragTimer(); + } } - - apiConnectptr.i = scanptr.p->scanApiRec; - ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord); + } + close_scan_req_send_conf(signal, scanPtr); +} - ScanFragNextReq * nextReq = (ScanFragNextReq*)&signal->theData[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); +void +Dbtc::close_scan_req_send_conf(Signal* signal, ScanRecordPtr scanPtr){ - updateBuddyTimer(apiConnectptr); - scanFragptr.p->startFragTimer(ctcTimer); - scanFragptr.p->scanFragState = ScanFragRec::LQH_ACTIVE_CLOSE; + jam(); - }//for -}//Dbtc::scanCompletedLab() + ndbrequire(scanPtr.p->m_queued_scan_frags.isEmpty()); + ndbrequire(scanPtr.p->m_delivered_scan_frags.isEmpty()); + //ndbrequire(scanPtr.p->m_running_scan_frags.isEmpty()); -void Dbtc::sendScanProcConf(Signal* signal){ - signal->theData[0] = scanptr.i; - signal->theData[1] = scanFragptr.i; - sendSignal(cownref, GSN_SCAN_PROCCONF, signal, 2, JBB); -} +#if 0 + { + ScanFragList comp(c_scan_frag_pool, scanPtr.p->m_completed_scan_frags); + ScanFragRecPtr ptr; + for(comp.first(ptr); !ptr.isNull(); comp.next(ptr)){ + ndbrequire(ptr.p->scanFragTimer == 0); + ndbrequire(ptr.p->scanFragState == ScanFragRec::COMPLETED); + } + } +#endif + + if(!scanPtr.p->m_running_scan_frags.isEmpty()){ + jam(); + return; + } -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::releaseScanFragrec(Signal* signal) { - scanFragptr.p->nextScanFrag = cfirstfreeScanFragrec; - scanFragptr.p->scanFragState = ScanFragRec::IDLE; - cfirstfreeScanFragrec = scanFragptr.i; - scanFragptr.p->stopFragTimer(); -}//Dbtc::releaseScanFragrec() + const bool apiFail = (apiConnectptr.p->apiFailState == ZTRUE); + + if(!scanPtr.p->m_close_scan_req){ + jam(); + /** + * The API hasn't order closing yet + */ + return; + } -void Dbtc::releaseScanOprec(Signal* signal) { - scanOpptr.p->nextScanOp = cfirstfreeScanOprec; - cfirstfreeScanOprec = scanOpptr.i; -}//Dbtc::releaseScanOprec() + Uint32 ref = apiConnectptr.p->ndbapiBlockref; + if(!apiFail && ref){ + jam(); + 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); + } + + releaseScanResources(scanPtr); + + if(apiFail){ + jam(); + /** + * API has failed + */ + handleApiFailState(signal, apiConnectptr.i); + } +} -void Dbtc::seizeScanrec(Signal* signal) { +Dbtc::ScanRecordPtr +Dbtc::seizeScanrec(Signal* signal) { + ScanRecordPtr scanptr; scanptr.i = cfirstfreeScanrec; ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord); cfirstfreeScanrec = scanptr.p->nextScan; scanptr.p->nextScan = RNIL; ndbrequire(scanptr.p->scanState == ScanRecord::IDLE); + return scanptr; }//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); - +void Dbtc::sendScanFragReq(Signal* signal, + ScanRecord* scanP, + ScanFragRec* scanFragP){ Uint32 requestInfo = 0; - ScanFragReq::setConcurrency(requestInfo, scanFragptr.p->scanFragConcurrency); - ScanFragReq::setLockMode(requestInfo, scanptr.p->scanLockMode); - ScanFragReq::setHoldLockFlag(requestInfo, scanptr.p->scanLockHold); - if(scanptr.p->scanLockMode == 1){ // Not read -> keyinfo + ScanFragReq::setConcurrency(requestInfo, scanFragP->scanFragConcurrency); + ScanFragReq::setLockMode(requestInfo, scanP->scanLockMode); + ScanFragReq::setHoldLockFlag(requestInfo, scanP->scanLockHold); + if(scanP->scanLockMode == 1){ // Not read -> keyinfo jam(); ScanFragReq::setKeyinfoFlag(requestInfo, 1); } - ScanFragReq::setReadCommittedFlag(requestInfo, scanptr.p->readCommitted); - ScanFragReq::setRangeScanFlag(requestInfo, scanptr.p->rangeScan); - ScanFragReq::setAttrLen(requestInfo, scanptr.p->scanAiLength); + ScanFragReq::setReadCommittedFlag(requestInfo, scanP->readCommitted); + ScanFragReq::setRangeScanFlag(requestInfo, scanP->rangeScan); + ScanFragReq::setAttrLen(requestInfo, scanP->scanAiLength); ScanFragReq::setScanPrio(requestInfo, 1); - apiConnectptr.i = scanptr.p->scanApiRec; + apiConnectptr.i = scanP->scanApiRec; ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord); ScanFragReq * const req = (ScanFragReq *)&signal->theData[0]; req->senderData = scanFragptr.i; req->resultRef = apiConnectptr.p->ndbapiBlockref; req->requestInfo = requestInfo; req->savePointId = apiConnectptr.p->currSavePointId; - req->tableId = scanptr.p->scanTableref; - req->fragmentNo = scanFragptr.p->scanFragId; - req->schemaVersion = scanptr.p->scanSchemaVersion; + req->tableId = scanP->scanTableref; + req->fragmentNo = scanFragP->scanFragId; + req->schemaVersion = scanP->scanSchemaVersion; 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] = scanFragP->m_apiPtr; } - sendSignal(scanFragptr.p->lqhBlockref, GSN_SCAN_FRAGREQ, signal, 25, JBB); + sendSignal(scanFragP->lqhBlockref, GSN_SCAN_FRAGREQ, signal, 25, JBB); updateBuddyTimer(apiConnectptr); - scanFragptr.p->startFragTimer(ctcTimer); - scanFragptr.p->scanFragCompletedStatus = ZFALSE; + scanFragP->startFragTimer(ctcTimer); }//Dbtc::sendScanFragReq() -void Dbtc::sendScanTabConf(Signal* signal) { +void Dbtc::sendScanTabConf(Signal* signal, ScanRecord * scanP) { 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 = scanP->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); - - scanptr.p->scanReceivedOperations = 0; - // Start the scanRec-timer again and wait for response from the API. - setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__); - updateBuddyTimer(apiConnectptr); + ScanFragRecPtr ptr; + 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); + + * 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); + } + scanP->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; @@ -9913,6 +9591,7 @@ void Dbtc::initApiConnect(Signal* signal) ndbrequire(tiacTmp > 0); guard4 = tiacTmp + 1; for (cachePtr.i = 0; cachePtr.i < guard4; cachePtr.i++) { + refresh_watch_dog(); ptrAss(cachePtr, cacheRecord); cachePtr.p->firstAttrbuf = RNIL; cachePtr.p->lastAttrbuf = RNIL; @@ -9927,6 +9606,7 @@ void Dbtc::initApiConnect(Signal* signal) guard4 = tiacTmp - 1; for (apiConnectptr.i = 0; apiConnectptr.i <= guard4; apiConnectptr.i++) { + refresh_watch_dog(); jam(); ptrAss(apiConnectptr, apiConnectRecord); apiConnectptr.p->apiConnectstate = CS_DISCONNECTED; @@ -9952,6 +9632,7 @@ void Dbtc::initApiConnect(Signal* signal) guard4 = (2 * tiacTmp) - 1; for (apiConnectptr.i = tiacTmp; apiConnectptr.i <= guard4; apiConnectptr.i++) { + refresh_watch_dog(); jam(); ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord); apiConnectptr.p->apiConnectstate = CS_RESTART; @@ -9977,6 +9658,7 @@ void Dbtc::initApiConnect(Signal* signal) guard4 = (3 * tiacTmp) - 1; for (apiConnectptr.i = 2 * tiacTmp; apiConnectptr.i <= guard4; apiConnectptr.i++) { + refresh_watch_dog(); jam(); ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord); setApiConTimer(apiConnectptr.i, 0, __LINE__); @@ -10005,6 +9687,7 @@ void Dbtc::initattrbuf(Signal* signal) { ndbrequire(cattrbufFilesize > 0); for (attrbufptr.i = 0; attrbufptr.i < cattrbufFilesize; attrbufptr.i++) { + refresh_watch_dog(); jam(); ptrAss(attrbufptr, attrbufRecord); attrbufptr.p->attrbuf[ZINBUF_NEXT] = attrbufptr.i + 1; /* NEXT ATTRBUF */ @@ -10019,6 +9702,7 @@ void Dbtc::initdatabuf(Signal* signal) { ndbrequire(cdatabufFilesize > 0); for (databufptr.i = 0; databufptr.i < cdatabufFilesize; databufptr.i++) { + refresh_watch_dog(); ptrAss(databufptr, databufRecord); databufptr.p->nextDatabuf = databufptr.i + 1; }//for @@ -10143,11 +9827,15 @@ void Dbtc::initialiseRecordsLab(Signal* signal, UintR Tdata0, /* ========================================================================= */ void Dbtc::initialiseScanrec(Signal* signal) { + ScanRecordPtr scanptr; ndbrequire(cscanrecFileSize > 0); for (scanptr.i = 0; scanptr.i < cscanrecFileSize; scanptr.i++) { + refresh_watch_dog(); jam(); ptrAss(scanptr, scanRecord); + new (scanptr.p) ScanRecord(); scanptr.p->scanState = ScanRecord::IDLE; + scanptr.p->scanApiRec = RNIL; scanptr.p->nextScan = scanptr.i + 1; }//for scanptr.i = cscanrecFileSize - 1; @@ -10158,34 +9846,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) @@ -10193,6 +9857,7 @@ void Dbtc::initTable(Signal* signal) ndbrequire(ctabrecFilesize > 0); for (tabptr.i = 0; tabptr.i < ctabrecFilesize; tabptr.i++) { + refresh_watch_dog(); ptrAss(tabptr, tableRecord); tabptr.p->currentSchemaVersion = 0; tabptr.p->storedTable = true; @@ -10209,6 +9874,7 @@ void Dbtc::initialiseTcConnect(Signal* signal) // Place half of tcConnectptr's in cfirstfreeTcConnectFail list Uint32 titcTmp = ctcConnectFilesize / 2; for (tcConnectptr.i = 0; tcConnectptr.i < titcTmp; tcConnectptr.i++) { + refresh_watch_dog(); jam(); ptrAss(tcConnectptr, tcConnectRecord); tcConnectptr.p->tcConnectstate = OS_RESTART; @@ -10224,6 +9890,7 @@ void Dbtc::initialiseTcConnect(Signal* signal) // Place other half in cfirstfreeTcConnect list for (tcConnectptr.i = titcTmp; tcConnectptr.i < ctcConnectFilesize; tcConnectptr.i++) { + refresh_watch_dog(); jam(); ptrAss(tcConnectptr, tcConnectRecord); tcConnectptr.p->tcConnectstate = OS_RESTART; @@ -10310,8 +9977,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) { @@ -10320,7 +9987,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; @@ -10334,48 +10001,53 @@ void Dbtc::releaseAbortResources(Signal* signal) apiConnectptr.p->apiConnectstate = CS_ABORTING; apiConnectptr.p->abortState = AS_IDLE; - bool ok = false; - Uint32 blockRef = apiConnectptr.p->ndbapiBlockref; - switch(apiConnectptr.p->returnsignal){ - case RS_TCROLLBACKCONF: + if(apiConnectptr.p->m_exec_flag || apiConnectptr.p->apiFailState == ZTRUE){ jam(); - ok = true; - signal->theData[0] = apiConnectptr.p->ndbapiConnect; - signal->theData[1] = apiConnectptr.p->transid[0]; - signal->theData[2] = apiConnectptr.p->transid[1]; - sendSignal(blockRef, GSN_TCROLLBACKCONF, signal, 3, JBB); - break; - case RS_TCROLLBACKREP:{ - jam(); - ok = true; - TcRollbackRep * const tcRollbackRep = - (TcRollbackRep *) signal->getDataPtr(); - - tcRollbackRep->connectPtr = apiConnectptr.p->ndbapiConnect; - tcRollbackRep->transId[0] = apiConnectptr.p->transid[0]; - tcRollbackRep->transId[1] = apiConnectptr.p->transid[1]; - tcRollbackRep->returnCode = apiConnectptr.p->returncode; - sendSignal(blockRef, GSN_TCROLLBACKREP, signal, - TcRollbackRep::SignalLength, JBB); - } - break; - case RS_NO_RETURN: - jam(); - ok = true; - break; - case RS_TCKEYCONF: - case RS_TCKEYREF: - case RS_TC_COMMITCONF: - break; - } - if(!ok){ - jam(); - ndbout_c("returnsignal = %d", apiConnectptr.p->returnsignal); - sendSystemError(signal); - }//if + bool ok = false; + Uint32 blockRef = apiConnectptr.p->ndbapiBlockref; + ReturnSignal ret = apiConnectptr.p->returnsignal; + apiConnectptr.p->returnsignal = RS_NO_RETURN; + apiConnectptr.p->m_exec_flag = 0; + switch(ret){ + case RS_TCROLLBACKCONF: + jam(); + ok = true; + signal->theData[0] = apiConnectptr.p->ndbapiConnect; + signal->theData[1] = apiConnectptr.p->transid[0]; + signal->theData[2] = apiConnectptr.p->transid[1]; + sendSignal(blockRef, GSN_TCROLLBACKCONF, signal, 3, JBB); + break; + case RS_TCROLLBACKREP:{ + jam(); + ok = true; + TcRollbackRep * const tcRollbackRep = + (TcRollbackRep *) signal->getDataPtr(); + + tcRollbackRep->connectPtr = apiConnectptr.p->ndbapiConnect; + tcRollbackRep->transId[0] = apiConnectptr.p->transid[0]; + tcRollbackRep->transId[1] = apiConnectptr.p->transid[1]; + tcRollbackRep->returnCode = apiConnectptr.p->returncode; + sendSignal(blockRef, GSN_TCROLLBACKREP, signal, + TcRollbackRep::SignalLength, JBB); + } + break; + case RS_NO_RETURN: + jam(); + ok = true; + break; + case RS_TCKEYCONF: + case RS_TC_COMMITCONF: + break; + } + if(!ok){ + jam(); + ndbout_c("returnsignal = %d", apiConnectptr.p->returnsignal); + sendSystemError(signal); + }//if - setApiConTimer(apiConnectptr.i, 0, __LINE__); - apiConnectptr.p->abortState = AS_IDLE; + } + setApiConTimer(apiConnectptr.i, 0, + 100000+c_apiConTimer_line[apiConnectptr.i]); if (apiConnectptr.p->apiFailState == ZTRUE) { jam(); handleApiFailState(signal, apiConnectptr.i); @@ -10393,6 +10065,8 @@ void Dbtc::releaseApiCon(Signal* signal, UintR TapiConnectPtr) cfirstfreeApiConnect = TlocalApiConnectptr.i; setApiConTimer(TlocalApiConnectptr.i, 0, __LINE__); TlocalApiConnectptr.p->apiConnectstate = CS_DISCONNECTED; + ndbassert(TlocalApiConnectptr.p->apiScanRec == RNIL); + TlocalApiConnectptr.p->ndbapiBlockref = 0; }//Dbtc::releaseApiCon() void Dbtc::releaseApiConnectFail(Signal* signal) @@ -10411,7 +10085,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; @@ -10445,12 +10119,12 @@ void Dbtc::seizeApiConnect(Signal* signal) apiConnectptr.p->nextApiConnect = RNIL; setApiConTimer(apiConnectptr.i, 0, __LINE__); apiConnectptr.p->apiConnectstate = CS_CONNECTED; /* STATE OF CONNECTION */ + apiConnectptr.p->triggerPending = false; + apiConnectptr.p->isIndexOp = false; } else { jam(); terrorCode = ZNO_FREE_API_CONNECTION; }//if - apiConnectptr.p->triggerPending = false; - apiConnectptr.p->isIndexOp = false; }//Dbtc::seizeApiConnect() void Dbtc::seizeApiConnectFail(Signal* signal) @@ -10690,20 +10364,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 @@ -10770,11 +10439,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", @@ -10782,17 +10450,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", @@ -10800,13 +10462,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; @@ -10883,6 +10552,13 @@ Dbtc::execDUMP_STATE_ORD(Signal* signal) set_timeout_value(signal->theData[1]); } } + + if (dumpState->args[0] == DumpStateOrd::TcSetApplTransactionTimeout){ + jam(); + if(signal->getLength() > 1){ + set_appl_timeout_value(signal->theData[1]); + } + } }//Dbtc::execDUMP_STATE_ORD() void Dbtc::execSET_VAR_REQ(Signal* signal) @@ -11405,11 +11081,16 @@ void Dbtc::sendTcIndxConf(Signal* signal, UintR TcommitFlag) UintR TcurrLen = localHostptr.p->noOfWordsTCINDXCONF; UintR confInfo = 0; TcIndxConf::setNoOfOperations(confInfo, (TopWords >> 1)); - TcIndxConf::setCommitFlag(confInfo, TcommitFlag); + TcIndxConf::setCommitFlag(confInfo, TcommitFlag == 1); TcIndxConf::setMarkerFlag(confInfo, Tmarker); const UintR TpacketLen = 6 + TopWords; regApiPtr->tcindxrec = 0; + if(TcommitFlag || (regApiPtr->lqhkeyreqrec == regApiPtr->lqhkeyconfrec)){ + jam(); + regApiPtr->m_exec_flag = 0; + } + if ((TpacketLen > 25) || !is_api){ TcIndxConf * const tcIndxConf = (TcIndxConf *)signal->getDataPtrSend(); @@ -11653,6 +11334,8 @@ void Dbtc::execTCKEYCONF(Signal* signal) } const UintR TconnectIndex = indexOp->connectionIndex; ApiConnectRecord * const regApiPtr = &apiConnectRecord[TconnectIndex]; + apiConnectptr.p = regApiPtr; + apiConnectptr.i = TconnectIndex; switch(indexOp->indexOpState) { case(IOS_NOOP): { jam(); @@ -11952,7 +11635,8 @@ void Dbtc::readIndexTable(Signal* signal, Uint32 transId1 = indexOp->tcIndxReq->transId1; Uint32 transId2 = indexOp->tcIndxReq->transId2; - const Uint8 opType = TcKeyReq::getOperationType(tcKeyRequestInfo); + const Operation_t opType = + (Operation_t)TcKeyReq::getOperationType(tcKeyRequestInfo); // Find index table if ((indexData = c_theIndexes.getPtr(indexOp->tcIndxReq->indexId)) == NULL) { @@ -12494,34 +12178,33 @@ void Dbtc::insertIntoIndexTable(Signal* signal, // Calculate key length and renumber attribute id:s AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool; LocalDataBuffer<11> afterValues(pool, firedTriggerData->afterValues); + bool skipNull = false; for(bool moreKeyAttrs = afterValues.first(iter); moreKeyAttrs; attrId++) { jam(); AttributeHeader* attrHeader = (AttributeHeader *) iter.data; + // Filter out NULL valued attributes + if (attrHeader->isNULL()) { + skipNull = true; + break; + } attrHeader->setAttributeId(attrId); keyLength += attrHeader->getDataSize(); hops = attrHeader->getHeaderSize() + attrHeader->getDataSize(); moreKeyAttrs = afterValues.next(iter, hops); } - - // Filter out single NULL attributes - if (attrId == 1) { + if (skipNull) { jam(); - afterValues.first(iter); - AttributeHeader* attrHeader = (AttributeHeader *) iter.data; - if (attrHeader->isNULL() && !afterValues.next(iter)) { - jam(); - opRecord->triggerExecutionCount--; - if (opRecord->triggerExecutionCount == 0) { - /* - We have completed current trigger execution - Continue triggering operation - */ - jam(); - continueTriggeringOp(signal, opRecord); - }//if - return; + opRecord->triggerExecutionCount--; + if (opRecord->triggerExecutionCount == 0) { + /* + We have completed current trigger execution + Continue triggering operation + */ + jam(); + continueTriggeringOp(signal, opRecord); }//if + return; }//if // Calculate total length of primary key to be stored in index table @@ -12849,36 +12532,36 @@ void Dbtc::deleteFromIndexTable(Signal* signal, // Calculate key length and renumber attribute id:s AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool; LocalDataBuffer<11> beforeValues(pool, firedTriggerData->beforeValues); + bool skipNull = false; for(bool moreKeyAttrs = beforeValues.first(iter); (moreKeyAttrs); attrId++) { jam(); AttributeHeader* attrHeader = (AttributeHeader *) iter.data; + // Filter out NULL valued attributes + if (attrHeader->isNULL()) { + skipNull = true; + break; + } attrHeader->setAttributeId(attrId); keyLength += attrHeader->getDataSize(); hops = attrHeader->getHeaderSize() + attrHeader->getDataSize(); moreKeyAttrs = beforeValues.next(iter, hops); } - // Filter out single NULL attributes - if (attrId == 1) { + if (skipNull) { jam(); - beforeValues.first(iter); - AttributeHeader* attrHeader = (AttributeHeader *) iter.data; - if (attrHeader->isNULL() && !beforeValues.next(iter)) { - jam(); - opRecord->triggerExecutionCount--; - if (opRecord->triggerExecutionCount == 0) { - /* + opRecord->triggerExecutionCount--; + if (opRecord->triggerExecutionCount == 0) { + /* We have completed current trigger execution Continue triggering operation - */ - jam(); - continueTriggeringOp(signal, opRecord); - }//if - return; + */ + jam(); + continueTriggeringOp(signal, opRecord); }//if + return; }//if TcKeyReq::setKeyLength(tcKeyRequestInfo, keyLength); diff --git a/ndb/src/kernel/blocks/dbtup/Dbtup.hpp b/ndb/src/kernel/blocks/dbtup/Dbtup.hpp index 4781230a311..b792edf9333 100644 --- a/ndb/src/kernel/blocks/dbtup/Dbtup.hpp +++ b/ndb/src/kernel/blocks/dbtup/Dbtup.hpp @@ -950,9 +950,6 @@ typedef Ptr<TableDescriptor> TableDescriptorPtr; struct HostBuffer { bool inPackedList; - Uint32 packetLenRC; - Uint32 noOfPacketsRC; - Uint32 packetBufferRC[29]; Uint32 packetLenTA; Uint32 noOfPacketsTA; Uint32 packetBufferTA[30]; @@ -1017,9 +1014,15 @@ public: void tuxReadAttrs(Uint32 fragPtrI, Uint32 pageId, Uint32 pageOffset, Uint32 tupVersion, Uint32 numAttrs, const Uint32* attrIds, const Uint32** attrData); /* - * TUX reads primary key for md5 summing and when returning keyinfo. + * TUX reads primary key without headers into an array of words. Used + * for md5 summing and when returning keyinfo. */ - void tuxReadKeys(); // under construction + void tuxReadKeys(Uint32 fragPtrI, Uint32 pageId, Uint32 pageOffset, Uint32* pkSize, Uint32* pkData); + + /* + * TUX checks if tuple is visible to scan. + */ + bool tuxQueryTh(Uint32 fragPtrI, Uint32 tupAddr, Uint32 tupVersion, Uint32 transId1, Uint32 transId2, Uint32 savePointId); private: BLOCK_DEFINES(Dbtup); @@ -1065,9 +1068,6 @@ private: void execTUP_WRITELOG_REQ(Signal* signal); // Ordered index related - void execTUP_READ_ATTRS(Signal* signal); - void execTUP_QUERY_TH(Signal* signal); - void execTUP_STORE_TH(Signal* signal); void execBUILDINDXREQ(Signal* signal); void buildIndex(Signal* signal, Uint32 buildPtrI); void buildIndexReply(Signal* signal, const BuildIndexRec* buildRec); @@ -1662,11 +1662,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 @@ -2326,10 +2322,15 @@ private: // Counters for num UNDO log records executed Uint32 cSrUndoRecords[9]; + STATIC_CONST(MAX_PARALLELL_TUP_SRREQ = 2); + Uint32 c_sr_free_page_0; + Uint32 c_errorInsert4000TableId; void initGlobalTemporaryVars(); void reportMemoryUsage(Signal* signal, int incDec); + + #ifdef VM_TRACE struct Th { Uint32 data[1]; diff --git a/ndb/src/kernel/blocks/dbtup/DbtupBuffer.cpp b/ndb/src/kernel/blocks/dbtup/DbtupBuffer.cpp index 90c6dbc6802..ea46ee94fdc 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,20 @@ 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) { + if(Tlen == 3) + return; + 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 +76,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 +111,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 +134,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; - + Uint32 sig0 = regOperPtr->tcOperationPtr; + Uint32 sig1 = regOperPtr->transid1; + Uint32 sig2 = regOperPtr->transid2; + + TransIdAI * transIdAI = (TransIdAI *)signal->getDataPtrSend(); + transIdAI->connectPtr = sig0; + transIdAI->transId[0] = sig1; + transIdAI->transId[1] = sig2; + + if (connectedToNode){ /** - * 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; + * 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; + } - 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; + /** + * short sig + api -> buffer + */ +#ifndef NDB_NO_DROPPED_SIGNAL + if (ToutBufIndex < 22 && is_api){ + ljam(); + bufferTRANSID_AI(signal, recBlockref, 3+ToutBufIndex); + return; + }//if +#endif + + /** + * 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; } + EXECUTE_DIRECT(block, GSN_TRANSID_AI, signal, 3 + ToutBufIndex); + ljamEntry(); 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; - - 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); - 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 { + /** + * 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(true){ // TODO 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; - }//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); - ljamEntry(); - }//if + } + + /** + * 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/DbtupDebug.cpp b/ndb/src/kernel/blocks/dbtup/DbtupDebug.cpp index c38fde23404..768a61655b5 100644 --- a/ndb/src/kernel/blocks/dbtup/DbtupDebug.cpp +++ b/ndb/src/kernel/blocks/dbtup/DbtupDebug.cpp @@ -201,6 +201,10 @@ Dbtup::execDUMP_STATE_ORD(Signal* signal) ndbrequire(chunk.pageCount <= alloc); if(chunk.pageCount != 0){ chunks.push_back(chunk); + if(chunk.pageCount != alloc) { + ndbout_c(" Tried to allocate %d - only allocated %d - free: %d", + alloc, chunk.pageCount, free); + } } else { ndbout_c(" Failed to alloc %d pages with %d pages free", alloc, free); @@ -212,6 +216,9 @@ Dbtup::execDUMP_STATE_ORD(Signal* signal) ptrCheckGuard(pagePtr, cnoOfPage, page); pagePtr.p->pageWord[ZPAGE_STATE_POS] = ~ZFREE_COMMON; } + + if(alloc == 1 && free > 0) + ndbrequire(chunk.pageCount == alloc); } break; } @@ -238,11 +245,12 @@ void Dbtup::execMEMCHECKREQ(Signal* signal) ljamEntry(); BlockReference blockref = signal->theData[0]; - for (Uint32 i = 0; i < 25; i++) { + Uint32 i; + for (i = 0; i < 25; i++) { ljam(); data[i] = 0; }//for - for (Uint32 i = 0; i < 16; i++) { + for (i = 0; i < 16; i++) { regPagePtr.i = cfreepageList[i]; ljam(); while (regPagePtr.i != RNIL) { diff --git a/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp b/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp index 07bad00acf1..0dc196d5f56 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 @@ -1445,7 +1441,10 @@ int Dbtup::interpreterNextLab(Signal* signal, register Uint32 theRegister; Uint32 TdataWritten = 0; Uint32 RstackPtr = 0; - Uint32 TregMemBuffer[32]; + union { + Uint32 TregMemBuffer[32]; + Uint64 Tdummy[16]; + }; Uint32 TstackMemBuffer[32]; /* ---------------------------------------------------------------- */ @@ -1496,19 +1495,23 @@ int Dbtup::interpreterNextLab(Signal* signal, // word read. Thus we set the register to be a 32 bit register. /* ------------------------------------------------------------- */ TregMemBuffer[theRegister] = 0x50; - TregMemBuffer[theRegister + 2] = 0; + * (Int64*)(TregMemBuffer+theRegister+2) = TregMemBuffer[theRegister+1]; } else if (TnoDataRW == 3) { /* ------------------------------------------------------------- */ // Three words read means that we get the instruction plus two // 32 words read. Thus we set the register to be a 64 bit register. /* ------------------------------------------------------------- */ TregMemBuffer[theRegister] = 0x60; + TregMemBuffer[theRegister+3] = TregMemBuffer[theRegister+2]; + TregMemBuffer[theRegister+2] = TregMemBuffer[theRegister+1]; } else if (TnoDataRW == 1) { /* ------------------------------------------------------------- */ // One word read means that we must have read a NULL value. We set // the register to indicate a NULL value. /* ------------------------------------------------------------- */ TregMemBuffer[theRegister] = 0; + TregMemBuffer[theRegister + 2] = 0; + TregMemBuffer[theRegister + 3] = 0; } else if (TnoDataRW == (Uint32)-1) { jam(); tupkeyErrorLab(signal); @@ -1550,8 +1553,8 @@ int Dbtup::interpreterNextLab(Signal* signal, AttributeHeader& ah = AttributeHeader::init(&TdataForUpdate[0], TattrId, TattrNoOfWords); - TdataForUpdate[1] = TregMemBuffer[theRegister + 1]; - TdataForUpdate[2] = TregMemBuffer[theRegister + 2]; + TdataForUpdate[1] = TregMemBuffer[theRegister + 2]; + TdataForUpdate[2] = TregMemBuffer[theRegister + 3]; Tlen = TattrNoOfWords + 1; if (Toptype == ZUPDATE) { if (TattrNoOfWords <= 2) { @@ -1597,24 +1600,22 @@ int Dbtup::interpreterNextLab(Signal* signal, case Interpreter::LOAD_CONST16: jam(); TregMemBuffer[theRegister] = 0x50; /* 32 BIT UNSIGNED CONSTANT */ - TregMemBuffer[theRegister + 1] = theInstruction >> 16; - TregMemBuffer[theRegister + 2] = 0; + * (Int64*)(TregMemBuffer+theRegister+2) = theInstruction >> 16; break; case Interpreter::LOAD_CONST32: jam(); TregMemBuffer[theRegister] = 0x50; /* 32 BIT UNSIGNED CONSTANT */ - TregMemBuffer[theRegister + 1] = TcurrentProgram[TprogramCounter]; - TregMemBuffer[theRegister + 2] = 0; + * (Int64*)(TregMemBuffer+theRegister+2) = * + (TcurrentProgram+TprogramCounter); TprogramCounter++; break; case Interpreter::LOAD_CONST64: jam(); TregMemBuffer[theRegister] = 0x60; /* 64 BIT UNSIGNED CONSTANT */ - TregMemBuffer[theRegister + 1] = TcurrentProgram[TprogramCounter + 0]; - TregMemBuffer[theRegister + 2] = TcurrentProgram[TprogramCounter + 1]; - TprogramCounter += 2; + TregMemBuffer[theRegister + 2 ] = * (TcurrentProgram + TprogramCounter++); + TregMemBuffer[theRegister + 3 ] = * (TcurrentProgram + TprogramCounter++); break; case Interpreter::ADD_REG_REG: @@ -1624,27 +1625,16 @@ int Dbtup::interpreterNextLab(Signal* signal, Uint32 TdestRegister = Interpreter::getReg3(theInstruction) << 2; Uint32 TrightType = TregMemBuffer[TrightRegister]; - Uint32 Tright0 = TregMemBuffer[TrightRegister + 1]; - Uint32 Tright1 = TregMemBuffer[TrightRegister + 2]; + Int64 Tright0 = * (Int64*)(TregMemBuffer + TrightRegister + 2); + Uint32 TleftType = TregMemBuffer[theRegister]; - Uint32 Tleft0 = TregMemBuffer[theRegister + 1]; - Uint32 Tleft1 = TregMemBuffer[theRegister + 2]; - Uint32 Tany64bit = (((TleftType | TrightType) & 0x60) == 0x60); + Int64 Tleft0 = * (Int64*)(TregMemBuffer + theRegister + 2); if ((TleftType | TrightType) != 0) { - Uint32 Tdest0 = Tleft0 + Tright0; - Uint32 Tdest1 = 0; - TregMemBuffer[TdestRegister + 1] = Tdest0; - TregMemBuffer[TdestRegister] = 0x50; - if (Tany64bit) { - TregMemBuffer[TdestRegister] = 0x60; - Tdest1 = Tleft1 + Tright1; - if (Tdest0 < Tleft0) { - Tdest1++; - } - }//if - TregMemBuffer[TdestRegister + 2] = Tdest1; + Uint64 Tdest0 = Tleft0 + Tright0; + * (Int64*)(TregMemBuffer+TdestRegister+2) = Tdest0; + TregMemBuffer[TdestRegister] = 0x60; } else { return TUPKEY_abort(signal, 20); } @@ -1658,30 +1648,18 @@ int Dbtup::interpreterNextLab(Signal* signal, Uint32 TdestRegister = Interpreter::getReg3(theInstruction) << 2; Uint32 TrightType = TregMemBuffer[TrightRegister]; - Uint32 Tright0 = TregMemBuffer[TrightRegister + 1]; - Uint32 Tright1 = TregMemBuffer[TrightRegister + 2]; - + Int64 Tright0 = * (Int64*)(TregMemBuffer + TrightRegister + 2); + Uint32 TleftType = TregMemBuffer[theRegister]; - Uint32 Tleft0 = TregMemBuffer[theRegister + 1]; - Uint32 Tleft1 = TregMemBuffer[theRegister + 2]; - Uint32 Tany64bit = (((TleftType | TrightType) & 0x60) == 0x60); + Int64 Tleft0 = * (Int64*)(TregMemBuffer + theRegister + 2); if ((TleftType | TrightType) != 0) { - Uint32 Tdest0 = Tleft0 - Tright0; - Uint32 Tdest1 = 0; - TregMemBuffer[TdestRegister + 1] = Tdest0; - TregMemBuffer[TdestRegister] = 0x50; - if (Tany64bit) { - TregMemBuffer[TdestRegister] = 0x60; - Tdest1 = Tleft1 - Tright1; - if (Tdest0 > Tleft0) { - Tdest1--; - }//if - }//if - TregMemBuffer[TdestRegister + 2] = Tdest1; + Int64 Tdest0 = Tleft0 - Tright0; + * (Int64*)(TregMemBuffer+TdestRegister+2) = Tdest0; + TregMemBuffer[TdestRegister] = 0x60; } else { - return TUPKEY_abort(signal, 21); - }//if + return TUPKEY_abort(signal, 20); + } break; } @@ -1715,12 +1693,12 @@ int Dbtup::interpreterNextLab(Signal* signal, Uint32 TrightRegister = Interpreter::getReg2(theInstruction) << 2; Uint32 TleftType = TregMemBuffer[theRegister]; - Uint32 Tleft0 = TregMemBuffer[theRegister + 1]; - Uint32 Tleft1 = TregMemBuffer[theRegister + 2]; + Uint32 Tleft0 = TregMemBuffer[theRegister + 2]; + Uint32 Tleft1 = TregMemBuffer[theRegister + 3]; Uint32 TrightType = TregMemBuffer[TrightRegister]; - Uint32 Tright0 = TregMemBuffer[TrightRegister + 1]; - Uint32 Tright1 = TregMemBuffer[TrightRegister + 2]; + Uint32 Tright0 = TregMemBuffer[TrightRegister + 2]; + Uint32 Tright1 = TregMemBuffer[TrightRegister + 3]; if ((TrightType | TleftType) != 0) { jam(); if ((Tleft0 == Tright0) && (Tleft1 == Tright1)) { @@ -1737,12 +1715,12 @@ int Dbtup::interpreterNextLab(Signal* signal, Uint32 TrightRegister = Interpreter::getReg2(theInstruction) << 2; Uint32 TleftType = TregMemBuffer[theRegister]; - Uint32 Tleft0 = TregMemBuffer[theRegister + 1]; - Uint32 Tleft1 = TregMemBuffer[theRegister + 2]; + Uint32 Tleft0 = TregMemBuffer[theRegister + 2]; + Uint32 Tleft1 = TregMemBuffer[theRegister + 3]; Uint32 TrightType = TregMemBuffer[TrightRegister]; - Uint32 Tright0 = TregMemBuffer[TrightRegister + 1]; - Uint32 Tright1 = TregMemBuffer[TrightRegister + 2]; + Uint32 Tright0 = TregMemBuffer[TrightRegister + 2]; + Uint32 Tright1 = TregMemBuffer[TrightRegister + 3]; if ((TrightType | TleftType) != 0) { jam(); if ((Tleft0 != Tright0) || (Tleft1 != Tright1)) { @@ -1758,17 +1736,16 @@ int Dbtup::interpreterNextLab(Signal* signal, { Uint32 TrightRegister = Interpreter::getReg2(theInstruction) << 2; + Uint32 TrightType = TregMemBuffer[TrightRegister]; + Int64 Tright0 = * (Int64*)(TregMemBuffer + TrightRegister + 2); + Uint32 TleftType = TregMemBuffer[theRegister]; - Uint32 Tleft0 = TregMemBuffer[theRegister + 1]; - Uint32 Tleft1 = TregMemBuffer[theRegister + 2]; + Int64 Tleft0 = * (Int64*)(TregMemBuffer + theRegister + 2); + - Uint32 TrightType = TregMemBuffer[TrightRegister]; - Uint32 Tright0 = TregMemBuffer[TrightRegister + 1]; - Uint32 Tright1 = TregMemBuffer[TrightRegister + 2]; if ((TrightType | TleftType) != 0) { jam(); - if ((Tleft0 < Tright0) || ((Tleft0 == Tright0) && - (Tleft1 < Tright1))) { + if (Tleft0 < Tright0) { TprogramCounter = brancher(theInstruction, TprogramCounter); }//if } else { @@ -1781,17 +1758,16 @@ int Dbtup::interpreterNextLab(Signal* signal, { Uint32 TrightRegister = Interpreter::getReg2(theInstruction) << 2; + Uint32 TrightType = TregMemBuffer[TrightRegister]; + Int64 Tright0 = * (Int64*)(TregMemBuffer + TrightRegister + 2); + Uint32 TleftType = TregMemBuffer[theRegister]; - Uint32 Tleft0 = TregMemBuffer[theRegister + 1]; - Uint32 Tleft1 = TregMemBuffer[theRegister + 2]; + Int64 Tleft0 = * (Int64*)(TregMemBuffer + theRegister + 2); + - Uint32 TrightType = TregMemBuffer[TrightRegister]; - Uint32 Tright0 = TregMemBuffer[TrightRegister + 1]; - Uint32 Tright1 = TregMemBuffer[TrightRegister + 2]; if ((TrightType | TleftType) != 0) { jam(); - if ((Tleft0 < Tright0) || ((Tleft0 == Tright0) && - (Tleft1 <= Tright1))) { + if (Tleft0 <= Tright0) { TprogramCounter = brancher(theInstruction, TprogramCounter); }//if } else { @@ -1804,17 +1780,16 @@ int Dbtup::interpreterNextLab(Signal* signal, { Uint32 TrightRegister = Interpreter::getReg2(theInstruction) << 2; + Uint32 TrightType = TregMemBuffer[TrightRegister]; + Int64 Tright0 = * (Int64*)(TregMemBuffer + TrightRegister + 2); + Uint32 TleftType = TregMemBuffer[theRegister]; - Uint32 Tleft0 = TregMemBuffer[theRegister + 1]; - Uint32 Tleft1 = TregMemBuffer[theRegister + 2]; + Int64 Tleft0 = * (Int64*)(TregMemBuffer + theRegister + 2); + - Uint32 TrightType = TregMemBuffer[TrightRegister]; - Uint32 Tright0 = TregMemBuffer[TrightRegister + 1]; - Uint32 Tright1 = TregMemBuffer[TrightRegister + 2]; if ((TrightType | TleftType) != 0) { jam(); - if ((Tleft0 > Tright0) || ((Tleft0 == Tright0) && - (Tleft1 > Tright1))) { + if (Tleft0 > Tright0){ TprogramCounter = brancher(theInstruction, TprogramCounter); }//if } else { @@ -1827,17 +1802,16 @@ int Dbtup::interpreterNextLab(Signal* signal, { Uint32 TrightRegister = Interpreter::getReg2(theInstruction) << 2; + Uint32 TrightType = TregMemBuffer[TrightRegister]; + Int64 Tright0 = * (Int64*)(TregMemBuffer + TrightRegister + 2); + Uint32 TleftType = TregMemBuffer[theRegister]; - Uint32 Tleft0 = TregMemBuffer[theRegister + 1]; - Uint32 Tleft1 = TregMemBuffer[theRegister + 2]; + Int64 Tleft0 = * (Int64*)(TregMemBuffer + theRegister + 2); + - Uint32 TrightType = TregMemBuffer[TrightRegister]; - Uint32 Tright0 = TregMemBuffer[TrightRegister + 1]; - Uint32 Tright1 = TregMemBuffer[TrightRegister + 2]; if ((TrightType | TleftType) != 0) { jam(); - if ((Tleft0 > Tright0) || ((Tleft0 == Tright0) && - (Tleft1 >= Tright1))) { + if (Tleft0 >= Tright0){ TprogramCounter = brancher(theInstruction, TprogramCounter); }//if } else { diff --git a/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp b/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp index 095ea412701..f5c3e2b4128 100644 --- a/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp +++ b/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp @@ -132,9 +132,6 @@ Dbtup::Dbtup(const class Configuration & conf) addRecSignal(GSN_TUP_WRITELOG_REQ, &Dbtup::execTUP_WRITELOG_REQ); // Ordered index related - addRecSignal(GSN_TUP_READ_ATTRS, &Dbtup::execTUP_READ_ATTRS); - addRecSignal(GSN_TUP_QUERY_TH, &Dbtup::execTUP_QUERY_TH); - addRecSignal(GSN_TUP_STORE_TH, &Dbtup::execTUP_STORE_TH); addRecSignal(GSN_BUILDINDXREQ, &Dbtup::execBUILDINDXREQ); initData(); @@ -701,7 +698,8 @@ void Dbtup::initRecords() page = (Page*)allocRecord("Page", sizeof(Page), - cnoOfPage); + cnoOfPage, + false); pageRange = (PageRange*)allocRecord("PageRange", sizeof(PageRange), @@ -891,6 +889,7 @@ void Dbtup::initializeAttrbufrec() AttrbufrecPtr attrBufPtr; for (attrBufPtr.i = 0; attrBufPtr.i < cnoOfAttrbufrec; attrBufPtr.i++) { + refresh_watch_dog(); ptrAss(attrBufPtr, attrbufrec); attrBufPtr.p->attrbuf[ZBUF_NEXT] = attrBufPtr.i + 1; }//for @@ -947,6 +946,7 @@ void Dbtup::initializeFragrecord() { FragrecordPtr regFragPtr; for (regFragPtr.i = 0; regFragPtr.i < cnoOfFragrec; regFragPtr.i++) { + refresh_watch_dog(); ptrAss(regFragPtr, fragrecord); regFragPtr.p->nextfreefrag = regFragPtr.i + 1; regFragPtr.p->checkpointVersion = RNIL; @@ -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() @@ -987,6 +985,7 @@ void Dbtup::initializeOperationrec() { OperationrecPtr regOpPtr; for (regOpPtr.i = 0; regOpPtr.i < cnoOfOprec; regOpPtr.i++) { + refresh_watch_dog(); ptrAss(regOpPtr, operationrec); regOpPtr.p->firstAttrinbufrec = RNIL; regOpPtr.p->lastAttrinbufrec = RNIL; @@ -1041,6 +1040,7 @@ void Dbtup::initializeTablerec() TablerecPtr regTabPtr; for (regTabPtr.i = 0; regTabPtr.i < cnoOfTablerec; regTabPtr.i++) { ljam(); + refresh_watch_dog(); ptrAss(regTabPtr, tablerec); initTab(regTabPtr.p); }//for @@ -1104,6 +1104,7 @@ void Dbtup::initializeTabDescr() cfreeTdList[i] = RNIL; }//for for (regTabDesPtr.i = 0; regTabDesPtr.i < cnoOfTabDescrRec; regTabDesPtr.i++) { + refresh_watch_dog(); ptrAss(regTabDesPtr, tableDescriptor); regTabDesPtr.p->tabDescr = RNIL; }//for @@ -1116,6 +1117,7 @@ void Dbtup::initializeUndoPage() for (undoPagep.i = 0; undoPagep.i < cnoOfUndoPage; undoPagep.i = undoPagep.i + ZUB_SEGMENT_SIZE) { + refresh_watch_dog(); ptrAss(undoPagep, undoPage); undoPagep.p->undoPageWord[ZPAGE_NEXT_POS] = undoPagep.i + ZUB_SEGMENT_SIZE; diff --git a/ndb/src/kernel/blocks/dbtup/DbtupIndex.cpp b/ndb/src/kernel/blocks/dbtup/DbtupIndex.cpp index f11de5238e2..e7a431f17de 100644 --- a/ndb/src/kernel/blocks/dbtup/DbtupIndex.cpp +++ b/ndb/src/kernel/blocks/dbtup/DbtupIndex.cpp @@ -22,7 +22,6 @@ #include <AttributeDescriptor.hpp> #include "AttributeOffset.hpp" #include <AttributeHeader.hpp> -#include <signaldata/TupAccess.hpp> #include <signaldata/TuxMaint.hpp> #define ljam() { jamLine(28000 + __LINE__); } @@ -152,10 +151,10 @@ Dbtup::tuxReadAttrs(Uint32 fragPtrI, Uint32 pageId, Uint32 pageOffset, Uint32 tu const Uint32* tupleHeader = &pagePtr.p->pageWord[pageOffset]; for (Uint32 i = 0; i < numAttrs; i++) { AttributeHeader ah(attrIds[i]); - Uint32 attrId = ah.getAttributeId(); - Uint32 index = tabDescriptor + (attrId << ZAD_LOG_SIZE); - Uint32 desc1 = tableDescriptor[index].tabDescr; - Uint32 desc2 = tableDescriptor[index + 1].tabDescr; + const Uint32 attrId = ah.getAttributeId(); + const Uint32 index = tabDescriptor + (attrId << ZAD_LOG_SIZE); + const Uint32 desc1 = tableDescriptor[index].tabDescr; + const Uint32 desc2 = tableDescriptor[index + 1].tabDescr; if (AttributeDescriptor::getNullable(desc1)) { Uint32 offset = AttributeOffset::getNullFlagOffset(desc2); ndbrequire(offset < tablePtr.p->tupNullWords); @@ -171,275 +170,78 @@ Dbtup::tuxReadAttrs(Uint32 fragPtrI, Uint32 pageId, Uint32 pageOffset, Uint32 tu } } -void // under construction -Dbtup::tuxReadKeys() -{ -} - -// deprecated signal interfaces - void -Dbtup::execTUP_READ_ATTRS(Signal* signal) +Dbtup::tuxReadKeys(Uint32 fragPtrI, Uint32 pageId, Uint32 pageOffset, Uint32* pkSize, Uint32* pkData) { ljamEntry(); - TupReadAttrs* const sig = (TupReadAttrs*)signal->getDataPtrSend(); - TupReadAttrs reqCopy = *sig; - TupReadAttrs* const req = &reqCopy; - req->errorCode = 0; - // get table + FragrecordPtr fragPtr; + fragPtr.i = fragPtrI; + ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord); TablerecPtr tablePtr; - tablePtr.i = req->tableId; + tablePtr.i = fragPtr.p->fragTableId; ptrCheckGuard(tablePtr, cnoOfTablerec, tablerec); - // get fragment - FragrecordPtr fragPtr; - if (req->fragPtrI == RNIL) { - ljam(); - getFragmentrec(fragPtr, req->fragId, tablePtr.p); - ndbrequire(fragPtr.i != RNIL); - req->fragPtrI = fragPtr.i; - } else { - fragPtr.i = req->fragPtrI; - ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord); - ndbrequire(req->fragId == fragPtr.p->fragmentId); - } - // get page PagePtr pagePtr; - if (req->pageId == RNIL) { - ljam(); - Uint32 fragPageId = req->tupAddr >> MAX_TUPLES_BITS; - Uint32 pageIndex = req->tupAddr & ((1 << MAX_TUPLES_BITS ) - 1); - ndbrequire((pageIndex & 0x1) == 0); - // data returned for original tuple - req->pageId = getRealpid(fragPtr.p, fragPageId); - req->pageOffset = ZPAGE_HEADER_SIZE + (pageIndex >> 1) * tablePtr.p->tupheadsize; - } - pagePtr.i = req->pageId; + pagePtr.i = pageId; ptrCheckGuard(pagePtr, cnoOfPage, page); - Uint32 pageOffset = req->pageOffset; - // search for tuple version if not original - if (! (req->requestInfo & TupReadAttrs::ReadKeys) && - pagePtr.p->pageWord[pageOffset + 1] != req->tupVersion) { - ljam(); - OperationrecPtr opPtr; - opPtr.i = pagePtr.p->pageWord[pageOffset]; - Uint32 loopGuard = 0; - while (true) { - ptrCheckGuard(opPtr, cnoOfOprec, operationrec); - if (opPtr.p->realPageIdC != RNIL) { - pagePtr.i = opPtr.p->realPageIdC; - pageOffset = opPtr.p->pageOffsetC; - ptrCheckGuard(pagePtr, cnoOfPage, page); - if (pagePtr.p->pageWord[pageOffset + 1] == req->tupVersion) { - ljam(); - break; - } - } - ljam(); - // next means before in event order - opPtr.i = opPtr.p->nextActiveOp; - ndbrequire(++loopGuard < (1 << ZTUP_VERSION_BITS)); + const Uint32 tabDescriptor = tablePtr.p->tabDescriptor; + const Uint32 numAttrs = tablePtr.p->noOfKeyAttr; + const Uint32* attrIds = &tableDescriptor[tablePtr.p->readKeyArray].tabDescr; + const Uint32* tupleHeader = &pagePtr.p->pageWord[pageOffset]; + Uint32 size = 0; + for (Uint32 i = 0; i < numAttrs; i++) { + AttributeHeader ah(attrIds[i]); + const Uint32 attrId = ah.getAttributeId(); + const Uint32 index = tabDescriptor + (attrId << ZAD_LOG_SIZE); + const Uint32 desc1 = tableDescriptor[index].tabDescr; + const Uint32 desc2 = tableDescriptor[index + 1].tabDescr; + ndbrequire(! AttributeDescriptor::getNullable(desc1)); + const Uint32 attrSize = AttributeDescriptor::getSizeInWords(desc1); + const Uint32* attrData = tupleHeader + AttributeOffset::getOffset(desc2); + for (Uint32 j = 0; j < attrSize; j++) { + pkData[size + j] = attrData[j]; } + size += attrSize; } - // shared buffer - Uint32* buffer = (Uint32*)sig + TupReadAttrs::SignalLength; - // if request is for keys then we create input section - if (req->requestInfo & TupReadAttrs::ReadKeys) { - ljam(); - buffer[0] = tablePtr.p->noOfKeyAttr; - const Uint32* keyArray = &tableDescriptor[tablePtr.p->readKeyArray].tabDescr; - MEMCOPY_NO_WORDS(&buffer[1], keyArray, tablePtr.p->noOfKeyAttr); - } - Uint32 inBufLen = buffer[0]; - Uint32* inBuffer = &buffer[1]; - Uint32* outBuffer = &buffer[1 + inBufLen]; - Uint32 maxRead = ZATTR_BUFFER_SIZE; - // save globals - TablerecPtr tabptr_old = tabptr; - FragrecordPtr fragptr_old = fragptr; - OperationrecPtr operPtr_old = operPtr; - // new globals - tabptr = tablePtr; - fragptr = fragPtr; - operPtr.i = RNIL; // XXX check later - operPtr.p = NULL; - int ret = readAttributes(pagePtr.p, pageOffset, inBuffer, inBufLen, outBuffer, maxRead); - // restore globals - tabptr = tabptr_old; - fragptr = fragptr_old; - operPtr = operPtr_old; - // check error - if ((Uint32)ret == (Uint32)-1) { - ljam(); - req->errorCode = terrorCode; - } - // copy back - *sig = *req; + *pkSize = size; } -void -Dbtup::execTUP_QUERY_TH(Signal* signal) +bool +Dbtup::tuxQueryTh(Uint32 fragPtrI, Uint32 tupAddr, Uint32 tupVersion, Uint32 transId1, Uint32 transId2, Uint32 savePointId) { ljamEntry(); - Operationrec tempOp; - TupQueryTh* const req = (TupQueryTh*)signal->getDataPtrSend(); - Uint32 tableId = req->tableId; - Uint32 fragId = req->fragId; - Uint32 tupAddr = req->tupAddr; - Uint32 req_tupVersion = req->tupVersion; - Uint32 transid1 = req->transId1; - Uint32 transid2 = req->transId2; - Uint32 savePointId = req->savePointId; - Uint32 ret_result = 0; - // get table + FragrecordPtr fragPtr; + fragPtr.i = fragPtrI; + ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord); TablerecPtr tablePtr; - tablePtr.i = tableId; + tablePtr.i = fragPtr.p->fragTableId; ptrCheckGuard(tablePtr, cnoOfTablerec, tablerec); - // get fragment - FragrecordPtr fragPtr; - getFragmentrec(fragPtr, fragId, tablePtr.p); - ndbrequire(fragPtr.i != RNIL); // get page PagePtr pagePtr; Uint32 fragPageId = tupAddr >> MAX_TUPLES_BITS; Uint32 pageIndex = tupAddr & ((1 << MAX_TUPLES_BITS ) - 1); - + // use temp op rec + Operationrec tempOp; tempOp.fragPageId = fragPageId; tempOp.pageIndex = pageIndex; - tempOp.transid1 = transid1; - tempOp.transid2 = transid2; + tempOp.transid1 = transId1; + tempOp.transid2 = transId2; tempOp.savePointId = savePointId; tempOp.optype = ZREAD; tempOp.dirtyOp = 1; if (getPage(pagePtr, &tempOp, fragPtr.p, tablePtr.p)) { /* - We use the normal getPage which will return the tuple to be used - for this transaction and savepoint id. If its tuple version equals - the requested then we have a visible tuple otherwise not. + * We use the normal getPage which will return the tuple to be used + * for this transaction and savepoint id. If its tuple version + * equals the requested then we have a visible tuple otherwise not. */ ljam(); Uint32 read_tupVersion = pagePtr.p->pageWord[tempOp.pageOffset + 1]; - if (read_tupVersion == req_tupVersion) { + if (read_tupVersion == tupVersion) { ljam(); - ret_result = 1; - } - } - req->returnCode = ret_result; - return; -} - -void -Dbtup::execTUP_STORE_TH(Signal* signal) -{ - ljamEntry(); - TupStoreTh* const sig = (TupStoreTh*)signal->getDataPtrSend(); - TupStoreTh reqCopy = *sig; - TupStoreTh* const req = &reqCopy; - req->errorCode = 0; - ndbrequire(req->tupVersion == 0); - // get table - TablerecPtr tablePtr; - tablePtr.i = req->tableId; - ptrCheckGuard(tablePtr, cnoOfTablerec, tablerec); - // offset to attribute 0 - Uint32 attrDescIndex = tablePtr.p->tabDescriptor + (0 << ZAD_LOG_SIZE); - Uint32 attrDataOffset = AttributeOffset::getOffset(tableDescriptor[attrDescIndex + 1].tabDescr); - // get fragment - FragrecordPtr fragPtr; - if (req->fragPtrI == RNIL) { - ljam(); - getFragmentrec(fragPtr, req->fragId, tablePtr.p); - ndbrequire(fragPtr.i != RNIL); - req->fragPtrI = fragPtr.i; - } else { - fragPtr.i = req->fragPtrI; - ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord); - ndbrequire(req->fragId == fragPtr.p->fragmentId); - } - // handle each case - switch (req->opCode) { - case TupStoreTh::OpRead: - ljam(); - { - PagePtr pagePtr; - if (req->pageId == RNIL) { - ljam(); - Uint32 fragPageId = req->tupAddr >> MAX_TUPLES_BITS; - Uint32 pageIndex = req->tupAddr & ((1 << MAX_TUPLES_BITS ) - 1); - ndbrequire((pageIndex & 0x1) == 0); - req->pageId = getRealpid(fragPtr.p, fragPageId); - req->pageOffset = ZPAGE_HEADER_SIZE + (pageIndex >> 1) * tablePtr.p->tupheadsize; - } - pagePtr.i = req->pageId; - ptrCheckGuard(pagePtr, cnoOfPage, page); - Uint32* data = &pagePtr.p->pageWord[req->pageOffset] + attrDataOffset; - Uint32* buffer = (Uint32*)sig + TupStoreTh::SignalLength; - ndbrequire(req->dataOffset + req->dataSize <= tablePtr.p->tupheadsize); - memcpy(buffer + req->dataOffset, data + req->dataOffset, req->dataSize << 2); - } - break; - case TupStoreTh::OpInsert: - ljam(); - { - PagePtr pagePtr; - if (! allocTh(fragPtr.p, tablePtr.p, NORMAL_PAGE, signal, req->pageOffset, pagePtr)) { - ljam(); - req->errorCode = terrorCode; - break; - } - req->pageId = pagePtr.i; - Uint32 fragPageId = pagePtr.p->pageWord[ZPAGE_FRAG_PAGE_ID_POS]; - Uint32 pageIndex = ((req->pageOffset - ZPAGE_HEADER_SIZE) / tablePtr.p->tupheadsize) << 1; - req->tupAddr = (fragPageId << MAX_TUPLES_BITS) | pageIndex; - ndbrequire(req->dataOffset + req->dataSize <= tablePtr.p->tupheadsize); - Uint32* data = &pagePtr.p->pageWord[req->pageOffset] + attrDataOffset; - Uint32* buffer = (Uint32*)sig + TupStoreTh::SignalLength; - memcpy(data + req->dataOffset, buffer + req->dataOffset, req->dataSize << 2); + return true; } - break; - case TupStoreTh::OpUpdate: - ljam(); - { - PagePtr pagePtr; - if (req->pageId == RNIL) { - ljam(); - Uint32 fragPageId = req->tupAddr >> MAX_TUPLES_BITS; - Uint32 pageIndex = req->tupAddr & ((1 << MAX_TUPLES_BITS ) - 1); - ndbrequire((pageIndex & 0x1) == 0); - req->pageId = getRealpid(fragPtr.p, fragPageId); - req->pageOffset = ZPAGE_HEADER_SIZE + (pageIndex >> 1) * tablePtr.p->tupheadsize; - } - pagePtr.i = req->pageId; - ptrCheckGuard(pagePtr, cnoOfPage, page); - Uint32* data = &pagePtr.p->pageWord[req->pageOffset] + attrDataOffset; - Uint32* buffer = (Uint32*)sig + TupStoreTh::SignalLength; - ndbrequire(req->dataOffset + req->dataSize <= tablePtr.p->tupheadsize); - memcpy(data + req->dataOffset, buffer + req->dataOffset, req->dataSize << 2); - } - break; - case TupStoreTh::OpDelete: - ljam(); - { - PagePtr pagePtr; - if (req->pageId == RNIL) { - ljam(); - Uint32 fragPageId = req->tupAddr >> MAX_TUPLES_BITS; - Uint32 pageIndex = req->tupAddr & ((1 << MAX_TUPLES_BITS ) - 1); - ndbrequire((pageIndex & 0x1) == 0); - req->pageId = getRealpid(fragPtr.p, fragPageId); - req->pageOffset = ZPAGE_HEADER_SIZE + (pageIndex >> 1) * tablePtr.p->tupheadsize; - } - pagePtr.i = req->pageId; - ptrCheckGuard(pagePtr, cnoOfPage, page); - freeTh(fragPtr.p, tablePtr.p, signal, pagePtr.p, req->pageOffset); - // null location - req->tupAddr = (Uint32)-1; - req->pageId = RNIL; - req->pageOffset = 0; - } - break; } - // copy back - *sig = *req; + return false; } // ordered index build diff --git a/ndb/src/kernel/blocks/dbtup/DbtupLCP.cpp b/ndb/src/kernel/blocks/dbtup/DbtupLCP.cpp index b74b2c00e3e..f8f2b9bdbd2 100644 --- a/ndb/src/kernel/blocks/dbtup/DbtupLCP.cpp +++ b/ndb/src/kernel/blocks/dbtup/DbtupLCP.cpp @@ -344,6 +344,8 @@ void Dbtup::lcpSaveDataPageLab(Signal* signal, Uint32 ciIndex) if (ciPtr.p->lcpTabPtr == c_errorInsert4000TableId) { // Delay writing of data pages during LCP ndbout << "Delay writing of data pages during LCP" << endl; + signal->theData[0] = ZCONT_SAVE_DP; + signal->theData[1] = ciIndex; sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 1000, 2); return; }//if diff --git a/ndb/src/kernel/blocks/dbtup/DbtupPagMan.cpp b/ndb/src/kernel/blocks/dbtup/DbtupPagMan.cpp index 410cafee161..9722aa437c0 100644 --- a/ndb/src/kernel/blocks/dbtup/DbtupPagMan.cpp +++ b/ndb/src/kernel/blocks/dbtup/DbtupPagMan.cpp @@ -123,6 +123,7 @@ void Dbtup::initializePage() PagePtr pagePtr; for (pagePtr.i = 0; pagePtr.i < cnoOfPage; pagePtr.i++) { ljam(); + refresh_watch_dog(); ptrAss(pagePtr, page); pagePtr.p->pageWord[ZPAGE_PHYSICAL_INDEX] = pagePtr.i; pagePtr.p->pageWord[ZPAGE_NEXT_POS] = pagePtr.i + 1; @@ -138,20 +139,29 @@ void Dbtup::initializePage() pagePtr.i = 0; ptrAss(pagePtr, page); pagePtr.p->pageWord[ZPAGE_STATE_POS] = ~ZFREE_COMMON; + + for(size_t j = 0; j<MAX_PARALLELL_TUP_SRREQ; j++){ + pagePtr.i = 1+j; + ptrAss(pagePtr, page); + pagePtr.p->pageWord[ZPAGE_STATE_POS] = ~ZFREE_COMMON; + } - returnCommonArea(1, cnoOfPage - 1); - cnoOfAllocatedPages = 1; + Uint32 tmp = 1 + MAX_PARALLELL_TUP_SRREQ; + returnCommonArea(tmp, cnoOfPage - tmp); + cnoOfAllocatedPages = tmp; // Is updated by returnCommonArea + c_sr_free_page_0 = ~0; }//Dbtup::initializePage() void Dbtup::allocConsPages(Uint32 noOfPagesToAllocate, Uint32& noOfPagesAllocated, Uint32& allocPageRef) { - if (noOfPagesToAllocate == 0) { + if (noOfPagesToAllocate == 0){ ljam(); noOfPagesAllocated = 0; return; }//if + Uint32 firstListToCheck = nextHigherTwoLog(noOfPagesToAllocate - 1); for (Uint32 i = firstListToCheck; i < 16; i++) { ljam(); diff --git a/ndb/src/kernel/blocks/dbtup/DbtupSystemRestart.cpp b/ndb/src/kernel/blocks/dbtup/DbtupSystemRestart.cpp index 580d764c96f..ed835dc057a 100644 --- a/ndb/src/kernel/blocks/dbtup/DbtupSystemRestart.cpp +++ b/ndb/src/kernel/blocks/dbtup/DbtupSystemRestart.cpp @@ -92,12 +92,25 @@ void Dbtup::rfrReadRestartInfoLab(Signal* signal, RestartInfoRecordPtr riPtr) seizeDiskBufferSegmentRecord(dbsiPtr); riPtr.p->sriDataBufferSegmentP = dbsiPtr.i; - Uint32 retPageRef; + Uint32 retPageRef = RNIL; Uint32 noAllocPages = 1; Uint32 noOfPagesAllocated; - allocConsPages(noAllocPages, noOfPagesAllocated, retPageRef); - ndbrequire(noOfPagesAllocated == 1); - + { + /** + * Use low pages for 0-pages during SR + * bitmask of free pages is kept in c_sr_free_page_0 + */ + Uint32 tmp = c_sr_free_page_0; + for(Uint32 i = 1; i<(1+MAX_PARALLELL_TUP_SRREQ); i++){ + if(tmp & (1 << i)){ + retPageRef = i; + c_sr_free_page_0 = tmp & (~(1 << i)); + break; + } + } + ndbrequire(retPageRef != RNIL); + } + dbsiPtr.p->pdxDataPage[0] = retPageRef; dbsiPtr.p->pdxNumDataPages = 1; dbsiPtr.p->pdxFilePage = 0; @@ -150,7 +163,10 @@ Dbtup::rfrInitRestartInfoLab(Signal* signal, DiskBufferSegmentInfoPtr dbsiPtr) /* LETS REMOVE IT AND REUSE THE SEGMENT FOR REAL DATA PAGES */ /* REMOVE ONE PAGE ONLY, PAGEP IS ALREADY SET TO THE RESTART INFO PAGE */ /************************************************************************/ - returnCommonArea(pagePtr.i, 1); + { + ndbrequire(pagePtr.i > 0 && pagePtr.i <= MAX_PARALLELL_TUP_SRREQ); + c_sr_free_page_0 |= (1 << pagePtr.i); + } Uint32 undoFileVersion = TzeroDataPage[ZSRI_UNDO_FILE_VER]; lliPtr.i = (undoFileVersion << 2) + (regTabPtr.i & 0x3); @@ -494,16 +510,17 @@ void Dbtup::readExecUndoLogLab(Signal* signal, DiskBufferSegmentInfoPtr dbsiPtr, Uint32 dataPages[16]; ndbrequire(dbsiPtr.p->pdxFilePage > 0); ndbrequire(dbsiPtr.p->pdxFilePage <= ZUB_SEGMENT_SIZE); - for (Uint32 i = 0; i < dbsiPtr.p->pdxFilePage; i++) { + Uint32 i; + for (i = 0; i < dbsiPtr.p->pdxFilePage; i++) { ljam(); dataPages[i] = dbsiPtr.p->pdxDataPage[i + ZUB_SEGMENT_SIZE]; }//for - for (Uint32 i = 0; i < ZUB_SEGMENT_SIZE; i++) { + for (i = 0; i < ZUB_SEGMENT_SIZE; i++) { ljam(); dataPages[i + dbsiPtr.p->pdxFilePage] = dbsiPtr.p->pdxDataPage[i]; }//for Uint32 limitLoop = ZUB_SEGMENT_SIZE + dbsiPtr.p->pdxFilePage; - for (Uint32 i = 0; i < limitLoop; i++) { + for (i = 0; i < limitLoop; i++) { ljam(); dbsiPtr.p->pdxDataPage[i] = dataPages[i]; }//for @@ -977,7 +994,8 @@ void Dbtup::allocRestartUndoBufferSegment(Signal* signal, DiskBufferSegmentInfoP seizeDiskBufferSegmentRecord(dbsiPtr); dbsiPtr.p->pdxBuffertype = UNDO_RESTART_PAGES; dbsiPtr.p->pdxUndoBufferSet[0] = undoPagePtr.i; - for (Uint32 i = 0; i < ZUB_SEGMENT_SIZE; i++) { + Uint32 i; + for (i = 0; i < ZUB_SEGMENT_SIZE; i++) { dbsiPtr.p->pdxDataPage[i] = undoPagePtr.i + i; }//for @@ -994,7 +1012,7 @@ void Dbtup::allocRestartUndoBufferSegment(Signal* signal, DiskBufferSegmentInfoP undoPagePtr.p->undoPageWord[ZPAGE_NEXT_POS] = RNIL; dbsiPtr.p->pdxUndoBufferSet[1] = undoPagePtr.i; // lliPtr.p->lliUndoPage = undoPagePtr.i; - for (Uint32 i = ZUB_SEGMENT_SIZE; i < (2 * ZUB_SEGMENT_SIZE); i++) { + for (i = ZUB_SEGMENT_SIZE; i < (2 * ZUB_SEGMENT_SIZE); i++) { dbsiPtr.p->pdxDataPage[i] = undoPagePtr.i + (i - ZUB_SEGMENT_SIZE); }//for return; diff --git a/ndb/src/kernel/blocks/dbtux/Dbtux.hpp b/ndb/src/kernel/blocks/dbtux/Dbtux.hpp index 25e85ba9f5f..1a3c7f64ac3 100644 --- a/ndb/src/kernel/blocks/dbtux/Dbtux.hpp +++ b/ndb/src/kernel/blocks/dbtux/Dbtux.hpp @@ -37,7 +37,6 @@ #include <signaldata/AlterIndx.hpp> #include <signaldata/DropTab.hpp> #include <signaldata/TuxMaint.hpp> -#include <signaldata/TupAccess.hpp> #include <signaldata/AccScan.hpp> #include <signaldata/TuxBound.hpp> #include <signaldata/NextScan.hpp> @@ -77,10 +76,14 @@ #define jam() jamLine(60000 + __LINE__) #define jamEntry() jamEntryLine(60000 + __LINE__) #endif -#ifdef DBTUX_CMP_CPP +#ifdef DBTUX_SEARCH_CPP #define jam() jamLine(70000 + __LINE__) #define jamEntry() jamEntryLine(70000 + __LINE__) #endif +#ifdef DBTUX_CMP_CPP +#define jam() jamLine(80000 + __LINE__) +#define jamEntry() jamEntryLine(80000 + __LINE__) +#endif #ifdef DBTUX_DEBUG_CPP #define jam() jamLine(90000 + __LINE__) #define jamEntry() jamEntryLine(90000 + __LINE__) @@ -112,6 +115,7 @@ public: static const unsigned DescPageSize = 256; private: static const unsigned MaxTreeNodeSize = MAX_TTREE_NODE_SIZE; + static const unsigned MaxPrefSize = MAX_TTREE_PREF_SIZE; static const unsigned ScanBoundSegmentSize = 7; static const unsigned MaxAccLockOps = MAX_PARALLEL_OP_PER_SCAN; BLOCK_DEFINES(Dbtux); @@ -206,19 +210,19 @@ private: unsigned m_fragBit : 1; // which duplicated table fragment TreeEnt(); // methods + bool eq(const TreeEnt ent) const; int cmp(const TreeEnt ent) const; }; static const unsigned TreeEntSize = sizeof(TreeEnt) >> 2; static const TreeEnt NullTreeEnt; /* - * Tree node has 1) fixed part 2) actual table data for min and max - * prefix 3) max and min entries 4) rest of entries 5) one extra entry + * Tree node has 1) fixed part 2) a prefix of index key data for min + * entry 3) max and min entries 4) rest of entries 5) one extra entry * used as work space. * * struct TreeNode part 1, size 6 words * min prefix part 2, size TreeHead::m_prefSize - * max prefix part 2, size TreeHead::m_prefSize * max entry part 3 * min entry part 3 * rest of entries part 4 @@ -265,14 +269,14 @@ private: friend struct TreeHead; struct TreeHead { Uint8 m_nodeSize; // words in tree node - Uint8 m_prefSize; // words in min/max prefix each + Uint8 m_prefSize; // words in min prefix Uint8 m_minOccup; // min entries in internal node Uint8 m_maxOccup; // max entries in node TupLoc m_root; // root node TreeHead(); // methods unsigned getSize(AccSize acc) const; - Data getPref(TreeNode* node, unsigned i) const; + Data getPref(TreeNode* node) const; TreeEnt* getEntList(TreeNode* node) const; }; @@ -442,6 +446,7 @@ private: Uint32 m_descPage; // descriptor page Uint16 m_descOff; // offset within the page Uint16 m_numAttrs; + bool m_storeNullKey; union { Uint32 nextPool; }; @@ -465,6 +470,7 @@ private: Uint32 m_descPage; // copy from index level Uint16 m_descOff; Uint16 m_numAttrs; + bool m_storeNullKey; TreeHead m_tree; TupLoc m_freeLoc; // one node pre-allocated for insert DLList<ScanOp> m_scanList; // current scans on this fragment @@ -514,6 +520,8 @@ private: NodeHandle(Frag& frag); NodeHandle(const NodeHandle& node); NodeHandle& operator=(const NodeHandle& node); + // check if unassigned + bool isNull(); // getters TupLoc getLink(unsigned i); unsigned getChilds(); // cannot spell @@ -528,56 +536,13 @@ private: void setBalance(int b); void setNodeScan(Uint32 scanPtrI); // access other parts of the node - Data getPref(unsigned i); + Data getPref(); TreeEnt getEnt(unsigned pos); TreeEnt getMinMax(unsigned i); // for ndbrequire and ndbassert void progError(int line, int cause, const char* file); }; - // parameters for methods - - /* - * Copy attribute data. - */ - struct CopyPar { - unsigned m_items; // number of attributes - bool m_headers; // copy headers flag (default true) - unsigned m_maxwords; // limit size (default no limit) - // output - unsigned m_numitems; // number of attributes fully copied - unsigned m_numwords; // number of words copied - CopyPar(); - }; - - /* - * Read index key attributes. - */ - struct ReadPar; - friend struct ReadPar; - struct ReadPar { - TreeEnt m_ent; // tuple to read - unsigned m_first; // first index attribute - unsigned m_count; // number of consecutive index attributes - Data m_data; // set pointer if 0 else copy result to it - unsigned m_size; // number of words (set in read keys only) - ReadPar(); - }; - - /* - * Scan bound comparison. - */ - struct BoundPar; - friend struct BoundPar; - struct BoundPar { - ConstData m_data1; // full bound data - ConstData m_data2; // full or prefix data - unsigned m_count1; // number of bounds - unsigned m_len2; // words in data2 buffer - unsigned m_dir; // 0-lower bound 1-upper bound - BoundPar(); - }; - // methods /* @@ -589,7 +554,7 @@ private: // utils void setKeyAttrs(const Frag& frag); void readKeyAttrs(const Frag& frag, TreeEnt ent, unsigned start, TableData keyData); - void copyAttrs(Data dst, ConstData src, CopyPar& copyPar); + void readTablePk(const Frag& frag, TreeEnt ent, unsigned& pkSize, Data pkData); void copyAttrs(const Frag& frag, TableData data1, Data data2, unsigned maxlen2 = MaxAttrDataSize); /* @@ -607,8 +572,6 @@ private: * DbtuxMaint.cpp */ void execTUX_MAINT_REQ(Signal* signal); - void tupReadAttrs(Signal* signal, const Frag& frag, ReadPar& readPar); - void tupReadKeys(Signal* signal, const Frag& frag, ReadPar& readPar); /* * DbtuxNode.cpp @@ -618,7 +581,7 @@ private: void selectNode(Signal* signal, NodeHandle& node, TupLoc loc, AccSize acc); void insertNode(Signal* signal, NodeHandle& node, AccSize acc); void deleteNode(Signal* signal, NodeHandle& node); - void setNodePref(Signal* signal, NodeHandle& node, unsigned i); + void setNodePref(Signal* signal, NodeHandle& node); // node operations void nodePushUp(Signal* signal, NodeHandle& node, unsigned pos, const TreeEnt& ent); void nodePopDown(Signal* signal, NodeHandle& node, unsigned pos, TreeEnt& ent); @@ -633,7 +596,6 @@ private: /* * DbtuxTree.cpp */ - void treeSearch(Signal* signal, Frag& frag, TableData searchKey, TreeEnt searchEnt, TreePos& treePos); void treeAdd(Signal* signal, Frag& frag, TreePos treePos, TreeEnt ent); void treeRemove(Signal* signal, Frag& frag, TreePos treePos); void treeRotateSingle(Signal* signal, Frag& frag, NodeHandle& node, unsigned i); @@ -658,11 +620,19 @@ private: void releaseScanOp(ScanOpPtr& scanPtr); /* + * DbtuxSearch.cpp + */ + void searchToAdd(Signal* signal, Frag& frag, TableData searchKey, TreeEnt searchEnt, TreePos& treePos); + void searchToRemove(Signal* signal, Frag& frag, TableData searchKey, TreeEnt searchEnt, TreePos& treePos); + void searchToScan(Signal* signal, Frag& frag, ConstData boundInfo, unsigned boundCount, TreePos& treePos); + + /* * DbtuxCmp.cpp */ - int cmpSearchKey(const Frag& frag, unsigned& start, TableData data1, ConstData data2, unsigned maxlen2 = MaxAttrDataSize); - int cmpSearchKey(const Frag& frag, unsigned& start, TableData data1, TableData data2); - int cmpScanBound(const Frag& frag, const BoundPar boundPar); + int cmpSearchKey(const Frag& frag, unsigned& start, TableData searchKey, ConstData entryData, unsigned maxlen = MaxAttrDataSize); + int cmpSearchKey(const Frag& frag, unsigned& start, TableData searchKey, TableData entryKey); + int cmpScanBound(const Frag& frag, unsigned dir, ConstData boundInfo, unsigned boundCount, ConstData entryData, unsigned maxlen = MaxAttrDataSize); + int cmpScanBound(const Frag& frag, unsigned dir, ConstData boundInfo, unsigned boundCount, TableData entryKey); /* * DbtuxDebug.cpp @@ -675,6 +645,7 @@ private: TupLoc m_parent; // expected parent address int m_depth; // returned depth unsigned m_occup; // returned occupancy + TreeEnt m_minmax[2]; // returned subtree min and max bool m_ok; // returned status PrintPar(); }; @@ -699,6 +670,8 @@ private: DebugTree = 4, // log and check tree after each op DebugScan = 8 // log scans }; + static const int DataFillByte = 0xa2; + static const int NodeFillByte = 0xa4; #endif // start up info @@ -859,13 +832,18 @@ Dbtux::TreeEnt::TreeEnt() : { } +inline bool +Dbtux::TreeEnt::eq(const TreeEnt ent) const +{ + return + m_tupLoc == ent.m_tupLoc && + m_tupVersion == ent.m_tupVersion && + m_fragBit == ent.m_fragBit; +} + inline int Dbtux::TreeEnt::cmp(const TreeEnt ent) const { - if (m_fragBit < ent.m_fragBit) - return -1; - if (m_fragBit > ent.m_fragBit) - return +1; if (m_tupLoc.m_pageId < ent.m_tupLoc.m_pageId) return -1; if (m_tupLoc.m_pageId > ent.m_tupLoc.m_pageId) @@ -878,6 +856,10 @@ Dbtux::TreeEnt::cmp(const TreeEnt ent) const return -1; if (m_tupVersion > ent.m_tupVersion) return +1; + if (m_fragBit < ent.m_fragBit) + return -1; + if (m_fragBit > ent.m_fragBit) + return +1; return 0; } @@ -920,25 +902,25 @@ Dbtux::TreeHead::getSize(AccSize acc) const case AccHead: return NodeHeadSize; case AccPref: - return NodeHeadSize + 2 * m_prefSize + 2 * TreeEntSize; + return NodeHeadSize + m_prefSize + 2 * TreeEntSize; case AccFull: return m_nodeSize; } - REQUIRE(false, "invalid Dbtux::AccSize"); + abort(); return 0; } inline Dbtux::Data -Dbtux::TreeHead::getPref(TreeNode* node, unsigned i) const +Dbtux::TreeHead::getPref(TreeNode* node) const { - Uint32* ptr = (Uint32*)node + NodeHeadSize + i * m_prefSize; + Uint32* ptr = (Uint32*)node + NodeHeadSize; return ptr; } inline Dbtux::TreeEnt* Dbtux::TreeHead::getEntList(TreeNode* node) const { - Uint32* ptr = (Uint32*)node + NodeHeadSize + 2 * m_prefSize; + Uint32* ptr = (Uint32*)node + NodeHeadSize + m_prefSize; return (TreeEnt*)ptr; } @@ -1013,7 +995,8 @@ Dbtux::Index::Index() : m_numFrags(0), m_descPage(RNIL), m_descOff(0), - m_numAttrs(0) + m_numAttrs(0), + m_storeNullKey(false) { for (unsigned i = 0; i < MaxIndexFragments; i++) { m_fragId[i] = ZNIL; @@ -1032,6 +1015,7 @@ Dbtux::Frag::Frag(ArrayPool<ScanOp>& scanOpPool) : m_descPage(RNIL), m_descOff(0), m_numAttrs(ZNIL), + m_storeNullKey(false), m_tree(), m_freeLoc(), m_scanList(scanOpPool), @@ -1087,6 +1071,12 @@ Dbtux::NodeHandle::operator=(const NodeHandle& node) return *this; } +inline bool +Dbtux::NodeHandle::isNull() +{ + return m_node == 0; +} + inline Dbtux::TupLoc Dbtux::NodeHandle::getLink(unsigned i) { @@ -1161,11 +1151,11 @@ Dbtux::NodeHandle::setNodeScan(Uint32 scanPtrI) } inline Dbtux::Data -Dbtux::NodeHandle::getPref(unsigned i) +Dbtux::NodeHandle::getPref() { TreeHead& tree = m_frag.m_tree; - ndbrequire(m_acc >= AccPref && i <= 1); - return tree.getPref(m_node, i); + ndbrequire(m_acc >= AccPref); + return tree.getPref(m_node); } inline Dbtux::TreeEnt @@ -1193,36 +1183,6 @@ Dbtux::NodeHandle::getMinMax(unsigned i) // parameters for methods -inline -Dbtux::CopyPar::CopyPar() : - m_items(0), - m_headers(true), - m_maxwords(~0), // max unsigned - // output - m_numitems(0), - m_numwords(0) -{ -} - -inline -Dbtux::ReadPar::ReadPar() : - m_first(0), - m_count(0), - m_data(0), - m_size(0) -{ -} - -inline -Dbtux::BoundPar::BoundPar() : - m_data1(0), - m_data2(0), - m_count1(0), - m_len2(0), - m_dir(255) -{ -} - #ifdef VM_TRACE inline Dbtux::PrintPar::PrintPar() : diff --git a/ndb/src/kernel/blocks/dbtux/DbtuxCmp.cpp b/ndb/src/kernel/blocks/dbtux/DbtuxCmp.cpp index 7601a14a242..1b8755a1dc4 100644 --- a/ndb/src/kernel/blocks/dbtux/DbtuxCmp.cpp +++ b/ndb/src/kernel/blocks/dbtux/DbtuxCmp.cpp @@ -25,14 +25,14 @@ * prefix may be partial in which case CmpUnknown may be returned. */ int -Dbtux::cmpSearchKey(const Frag& frag, unsigned& start, TableData data1, ConstData data2, unsigned maxlen2) +Dbtux::cmpSearchKey(const Frag& frag, unsigned& start, TableData searchKey, ConstData entryData, unsigned maxlen) { const unsigned numAttrs = frag.m_numAttrs; const DescEnt& descEnt = getDescEnt(frag.m_descPage, frag.m_descOff); // number of words of attribute data left - unsigned len2 = maxlen2; + unsigned len2 = maxlen; // skip to right position in search key - data1 += start; + searchKey += start; int ret = 0; while (start < numAttrs) { if (len2 < AttributeHeaderSize) { @@ -41,20 +41,20 @@ Dbtux::cmpSearchKey(const Frag& frag, unsigned& start, TableData data1, ConstDat break; } len2 -= AttributeHeaderSize; - if (*data1 != 0) { - if (! data2.ah().isNULL()) { + if (*searchKey != 0) { + if (! entryData.ah().isNULL()) { jam(); // current attribute const DescAttr& descAttr = descEnt.m_descAttr[start]; const unsigned typeId = descAttr.m_typeId; // full data size const unsigned size1 = AttributeDescriptor::getSizeInWords(descAttr.m_attrDesc); - ndbrequire(size1 != 0 && size1 == data2.ah().getDataSize()); + ndbrequire(size1 != 0 && size1 == entryData.ah().getDataSize()); const unsigned size2 = min(size1, len2); len2 -= size2; // compare - const Uint32* const p1 = *data1; - const Uint32* const p2 = &data2[AttributeHeaderSize]; + const Uint32* const p1 = *searchKey; + const Uint32* const p2 = &entryData[AttributeHeaderSize]; ret = NdbSqlUtil::cmp(typeId, p1, p2, size1, size2); if (ret != 0) { jam(); @@ -62,20 +62,20 @@ Dbtux::cmpSearchKey(const Frag& frag, unsigned& start, TableData data1, ConstDat } } else { jam(); - // not NULL < NULL - ret = -1; + // not NULL > NULL + ret = +1; break; } } else { - if (! data2.ah().isNULL()) { + if (! entryData.ah().isNULL()) { jam(); - // NULL > not NULL - ret = +1; + // NULL < not NULL + ret = -1; break; } } - data1 += 1; - data2 += AttributeHeaderSize + data2.ah().getDataSize(); + searchKey += 1; + entryData += AttributeHeaderSize + entryData.ah().getDataSize(); start++; } // XXX until data format errors are handled @@ -89,17 +89,17 @@ Dbtux::cmpSearchKey(const Frag& frag, unsigned& start, TableData data1, ConstDat * Start position is updated as in previous routine. */ int -Dbtux::cmpSearchKey(const Frag& frag, unsigned& start, TableData data1, TableData data2) +Dbtux::cmpSearchKey(const Frag& frag, unsigned& start, TableData searchKey, TableData entryKey) { const unsigned numAttrs = frag.m_numAttrs; const DescEnt& descEnt = getDescEnt(frag.m_descPage, frag.m_descOff); // skip to right position - data1 += start; - data2 += start; + searchKey += start; + entryKey += start; int ret = 0; while (start < numAttrs) { - if (*data1 != 0) { - if (*data2 != 0) { + if (*searchKey != 0) { + if (*entryKey != 0) { jam(); // current attribute const DescAttr& descAttr = descEnt.m_descAttr[start]; @@ -107,8 +107,8 @@ Dbtux::cmpSearchKey(const Frag& frag, unsigned& start, TableData data1, TableDat // full data size const unsigned size1 = AttributeDescriptor::getSizeInWords(descAttr.m_attrDesc); // compare - const Uint32* const p1 = *data1; - const Uint32* const p2 = *data2; + const Uint32* const p1 = *searchKey; + const Uint32* const p2 = *entryKey; ret = NdbSqlUtil::cmp(typeId, p1, p2, size1, size1); if (ret != 0) { jam(); @@ -116,20 +116,20 @@ Dbtux::cmpSearchKey(const Frag& frag, unsigned& start, TableData data1, TableDat } } else { jam(); - // not NULL < NULL - ret = -1; + // not NULL > NULL + ret = +1; break; } } else { - if (*data2 != 0) { + if (*entryKey != 0) { jam(); - // NULL > not NULL - ret = +1; + // NULL < not NULL + ret = -1; break; } } - data1 += 1; - data2 += 1; + searchKey += 1; + entryKey += 1; start++; } // XXX until data format errors are handled @@ -137,94 +137,96 @@ Dbtux::cmpSearchKey(const Frag& frag, unsigned& start, TableData data1, TableDat return ret; } - /* - * Scan bound vs tree entry. + * Scan bound vs node prefix. * * Compare lower or upper bound and index attribute data. The attribute * data may be partial in which case CmpUnknown may be returned. - * Returns -1 if the boundary is to the left of the compared key and +1 if - * the boundary is to the right of the compared key. + * Returns -1 if the boundary is to the left of the compared key and +1 + * if the boundary is to the right of the compared key. * - * To get this behaviour we treat equality a little bit special. - * If the boundary is a lower bound then the boundary is to the left of all - * equal keys and if it is an upper bound then the boundary is to the right - * of all equal keys. + * To get this behaviour we treat equality a little bit special. If the + * boundary is a lower bound then the boundary is to the left of all + * equal keys and if it is an upper bound then the boundary is to the + * right of all equal keys. * * When searching for the first key we are using the lower bound to try - * to find the first key that is to the right of the boundary. - * Then we start scanning from this tuple (including the tuple itself) - * until we find the first key which is to the right of the boundary. Then - * we stop and do not include that key in the scan result. + * to find the first key that is to the right of the boundary. Then we + * start scanning from this tuple (including the tuple itself) until we + * find the first key which is to the right of the boundary. Then we + * stop and do not include that key in the scan result. */ int -Dbtux::cmpScanBound(const Frag& frag, const BoundPar boundPar) +Dbtux::cmpScanBound(const Frag& frag, unsigned dir, ConstData boundInfo, unsigned boundCount, ConstData entryData, unsigned maxlen) { - unsigned type = 4; - int ret = 0; - /* - No boundary means full scan, low boundary is to the right of all keys. - Thus we should always return -1. For upper bound we are to the right of - all keys, thus we should always return +1. We achieve this behaviour - by initialising return value to 0 and set type to 4. - */ const DescEnt& descEnt = getDescEnt(frag.m_descPage, frag.m_descOff); - ConstData data1 = boundPar.m_data1; - ConstData data2 = boundPar.m_data2; // direction 0-lower 1-upper - const unsigned dir = boundPar.m_dir; ndbrequire(dir <= 1); // number of words of data left - unsigned len2 = boundPar.m_len2; - for (unsigned i = 0; i < boundPar.m_count1; i++) { + unsigned len2 = maxlen; + /* + * No boundary means full scan, low boundary is to the right of all + * keys. Thus we should always return -1. For upper bound we are to + * the right of all keys, thus we should always return +1. We achieve + * this behaviour by initializing type to 4. + */ + unsigned type = 4; + while (boundCount != 0) { if (len2 < AttributeHeaderSize) { jam(); return NdbSqlUtil::CmpUnknown; } len2 -= AttributeHeaderSize; // get and skip bound type - type = data1[0]; - data1 += 1; - ndbrequire(! data1.ah().isNULL()); - if (! data2.ah().isNULL()) { - jam(); - // current attribute - const unsigned index = data1.ah().getAttributeId(); - const DescAttr& descAttr = descEnt.m_descAttr[index]; - const unsigned typeId = descAttr.m_typeId; - ndbrequire(data2.ah().getAttributeId() == descAttr.m_primaryAttrId); - // full data size - const unsigned size1 = data1.ah().getDataSize(); - ndbrequire(size1 != 0 && size1 == data2.ah().getDataSize()); - const unsigned size2 = min(size1, len2); - len2 -= size2; - // compare - const Uint32* const p1 = &data1[AttributeHeaderSize]; - const Uint32* const p2 = &data2[AttributeHeaderSize]; - ret = NdbSqlUtil::cmp(typeId, p1, p2, size1, size2); - if (ret != 0) { + type = boundInfo[0]; + boundInfo += 1; + if (! boundInfo.ah().isNULL()) { + if (! entryData.ah().isNULL()) { jam(); - return ret; + // current attribute + const unsigned index = boundInfo.ah().getAttributeId(); + const DescAttr& descAttr = descEnt.m_descAttr[index]; + const unsigned typeId = descAttr.m_typeId; + ndbrequire(entryData.ah().getAttributeId() == descAttr.m_primaryAttrId); + // full data size + const unsigned size1 = boundInfo.ah().getDataSize(); + ndbrequire(size1 != 0 && size1 == entryData.ah().getDataSize()); + const unsigned size2 = min(size1, len2); + len2 -= size2; + // compare + const Uint32* const p1 = &boundInfo[AttributeHeaderSize]; + const Uint32* const p2 = &entryData[AttributeHeaderSize]; + int ret = NdbSqlUtil::cmp(typeId, p1, p2, size1, size2); + // XXX until data format errors are handled + ndbrequire(ret != NdbSqlUtil::CmpError); + if (ret != 0) { + jam(); + return ret; + } + } else { + jam(); + // not NULL > NULL + return +1; } } else { jam(); - /* - NULL is bigger than any bound, thus the boundary is always to the - left of NULL - */ - return -1; + if (! entryData.ah().isNULL()) { + jam(); + // NULL < not NULL + return -1; + } } - data1 += AttributeHeaderSize + data1.ah().getDataSize(); - data2 += AttributeHeaderSize + data2.ah().getDataSize(); + boundInfo += AttributeHeaderSize + boundInfo.ah().getDataSize(); + entryData += AttributeHeaderSize + entryData.ah().getDataSize(); + boundCount -= 1; } - ndbassert(ret == 0); if (dir == 0) { jam(); /* - Looking for the lower bound. If strict lower bound then the boundary is - to the right of the compared key and otherwise (equal included in range) - then the boundary is to the left of the key. - */ + * Looking for the lower bound. If strict lower bound then the + * boundary is to the right of the compared key and otherwise (equal + * included in range) then the boundary is to the left of the key. + */ if (type == 1) { jam(); return +1; @@ -233,10 +235,11 @@ Dbtux::cmpScanBound(const Frag& frag, const BoundPar boundPar) } else { jam(); /* - Looking for the upper bound. If strict upper bound then the boundary is - to the left of all equal keys and otherwise (equal included in the - range) then the boundary is to the right of all equal keys. - */ + * Looking for the upper bound. If strict upper bound then the + * boundary is to the left of all equal keys and otherwise (equal + * included in the range) then the boundary is to the right of all + * equal keys. + */ if (type == 3) { jam(); return -1; @@ -245,3 +248,72 @@ Dbtux::cmpScanBound(const Frag& frag, const BoundPar boundPar) } } +/* + * Scan bound vs tree entry. + */ +int +Dbtux::cmpScanBound(const Frag& frag, unsigned dir, ConstData boundInfo, unsigned boundCount, TableData entryKey) +{ + const DescEnt& descEnt = getDescEnt(frag.m_descPage, frag.m_descOff); + // direction 0-lower 1-upper + ndbrequire(dir <= 1); + // initialize type to equality + unsigned type = 4; + while (boundCount != 0) { + // get and skip bound type + type = boundInfo[0]; + boundInfo += 1; + if (! boundInfo.ah().isNULL()) { + if (*entryKey != 0) { + jam(); + // current attribute + const unsigned index = boundInfo.ah().getAttributeId(); + const DescAttr& descAttr = descEnt.m_descAttr[index]; + const unsigned typeId = descAttr.m_typeId; + // full data size + const unsigned size1 = AttributeDescriptor::getSizeInWords(descAttr.m_attrDesc); + // compare + const Uint32* const p1 = &boundInfo[AttributeHeaderSize]; + const Uint32* const p2 = *entryKey; + int ret = NdbSqlUtil::cmp(typeId, p1, p2, size1, size1); + // XXX until data format errors are handled + ndbrequire(ret != NdbSqlUtil::CmpError); + if (ret != 0) { + jam(); + return ret; + } + } else { + jam(); + // not NULL > NULL + return +1; + } + } else { + jam(); + if (*entryKey != 0) { + jam(); + // NULL < not NULL + return -1; + } + } + boundInfo += AttributeHeaderSize + boundInfo.ah().getDataSize(); + entryKey += 1; + boundCount -= 1; + } + if (dir == 0) { + // lower bound + jam(); + if (type == 1) { + jam(); + return +1; + } + return -1; + } else { + // upper bound + jam(); + if (type == 3) { + jam(); + return -1; + } + return +1; + } +} diff --git a/ndb/src/kernel/blocks/dbtux/DbtuxDebug.cpp b/ndb/src/kernel/blocks/dbtux/DbtuxDebug.cpp index c4931685305..11f4f12b7f6 100644 --- a/ndb/src/kernel/blocks/dbtux/DbtuxDebug.cpp +++ b/ndb/src/kernel/blocks/dbtux/DbtuxDebug.cpp @@ -137,16 +137,17 @@ Dbtux::printNode(Signal* signal, Frag& frag, NdbOut& out, TupLoc loc, PrintPar& par.m_ok = false; } } + static const char* const sep = " *** "; // check child-parent links if (node.getLink(2) != par.m_parent) { par.m_ok = false; - out << par.m_path << " *** "; + out << par.m_path << sep; out << "parent loc " << hex << node.getLink(2); out << " should be " << hex << par.m_parent << endl; } if (node.getSide() != par.m_side) { par.m_ok = false; - out << par.m_path << " *** "; + out << par.m_path << sep; out << "side " << dec << node.getSide(); out << " should be " << dec << par.m_side << endl; } @@ -154,26 +155,26 @@ Dbtux::printNode(Signal* signal, Frag& frag, NdbOut& out, TupLoc loc, PrintPar& const int balance = -cpar[0].m_depth + cpar[1].m_depth; if (node.getBalance() != balance) { par.m_ok = false; - out << par.m_path << " *** "; + out << par.m_path << sep; out << "balance " << node.getBalance(); out << " should be " << balance << endl; } if (abs(node.getBalance()) > 1) { par.m_ok = false; - out << par.m_path << " *** "; + out << par.m_path << sep; out << "balance " << node.getBalance() << " is invalid" << endl; } // check occupancy - if (node.getOccup() > tree.m_maxOccup) { + if (node.getOccup() == 0 || node.getOccup() > tree.m_maxOccup) { par.m_ok = false; - out << par.m_path << " *** "; + out << par.m_path << sep; out << "occupancy " << node.getOccup(); - out << " greater than max " << tree.m_maxOccup << endl; + out << " zero or greater than max " << tree.m_maxOccup << endl; } // check for occupancy of interior node if (node.getChilds() == 2 && node.getOccup() < tree.m_minOccup) { par.m_ok = false; - out << par.m_path << " *** "; + out << par.m_path << sep; out << "occupancy " << node.getOccup() << " of interior node"; out << " less than min " << tree.m_minOccup << endl; } @@ -183,13 +184,74 @@ Dbtux::printNode(Signal* signal, Frag& frag, NdbOut& out, TupLoc loc, PrintPar& node.getLink(1 - i) == NullTupLoc && node.getOccup() + cpar[i].m_occup <= tree.m_maxOccup) { par.m_ok = false; - out << par.m_path << " *** "; + out << par.m_path << sep; out << "missed merge with child " << i << endl; } } + // check inline prefix + { ConstData data1 = node.getPref(); + Uint32 data2[MaxPrefSize]; + memset(data2, DataFillByte, MaxPrefSize << 2); + readKeyAttrs(frag, node.getMinMax(0), 0, c_searchKey); + copyAttrs(frag, c_searchKey, data2, tree.m_prefSize); + for (unsigned n = 0; n < tree.m_prefSize; n++) { + if (data1[n] != data2[n]) { + par.m_ok = false; + out << par.m_path << sep; + out << "inline prefix mismatch word " << n; + out << " value " << hex << data1[n]; + out << " should be " << hex << data2[n] << endl; + break; + } + } + } + // check ordering within node + for (unsigned j = 1; j < node.getOccup(); j++) { + unsigned start = 0; + const TreeEnt ent1 = node.getEnt(j - 1); + const TreeEnt ent2 = node.getEnt(j); + if (j == 1) { + readKeyAttrs(frag, ent1, start, c_searchKey); + } else { + memcpy(c_searchKey, c_entryKey, frag.m_numAttrs << 2); + } + readKeyAttrs(frag, ent2, start, c_entryKey); + int ret = cmpSearchKey(frag, start, c_searchKey, c_entryKey); + if (ret == 0) + ret = ent1.cmp(ent2); + if (ret != -1) { + par.m_ok = false; + out << par.m_path << sep; + out << " disorder within node at pos " << j << endl; + } + } + // check ordering wrt subtrees + for (unsigned i = 0; i <= 1; i++) { + if (node.getLink(i) == NullTupLoc) + continue; + const TreeEnt ent1 = cpar[i].m_minmax[1 - i]; + const TreeEnt ent2 = node.getMinMax(i); + unsigned start = 0; + readKeyAttrs(frag, ent1, start, c_searchKey); + readKeyAttrs(frag, ent2, start, c_entryKey); + int ret = cmpSearchKey(frag, start, c_searchKey, c_entryKey); + if (ret == 0) + ret = ent1.cmp(ent2); + if (ret != (i == 0 ? -1 : +1)) { + par.m_ok = false; + out << par.m_path << sep; + out << " disorder wrt subtree " << i << endl; + } + } // return values par.m_depth = 1 + max(cpar[0].m_depth, cpar[1].m_depth); par.m_occup = node.getOccup(); + for (unsigned i = 0; i <= 1; i++) { + if (node.getLink(i) == NullTupLoc) + par.m_minmax[i] = node.getMinMax(i); + else + par.m_minmax[i] = cpar[i].m_minmax[i]; + } } NdbOut& @@ -355,20 +417,19 @@ operator<<(NdbOut& out, const Dbtux::NodeHandle& node) out << " [acc " << dec << node.m_acc << "]"; out << " [node " << *node.m_node << "]"; if (node.m_acc >= Dbtux::AccPref) { - for (unsigned i = 0; i <= 1; i++) { - out << " [pref " << dec << i; - const Uint32* data = (const Uint32*)node.m_node + Dbtux::NodeHeadSize + i * tree.m_prefSize; - for (unsigned j = 0; j < node.m_frag.m_tree.m_prefSize; j++) - out << " " << hex << data[j]; - out << "]"; - } + const Uint32* data; + out << " [pref"; + data = (const Uint32*)node.m_node + Dbtux::NodeHeadSize; + for (unsigned j = 0; j < tree.m_prefSize; j++) + out << " " << hex << data[j]; + out << "]"; out << " [entList"; unsigned numpos = node.m_node->m_occup; if (node.m_acc < Dbtux::AccFull && numpos > 2) { numpos = 2; out << "(" << dec << numpos << ")"; } - const Uint32* data = (const Uint32*)node.m_node + Dbtux::NodeHeadSize + 2 * tree.m_prefSize; + data = (const Uint32*)node.m_node + Dbtux::NodeHeadSize + tree.m_prefSize; const Dbtux::TreeEnt* entList = (const Dbtux::TreeEnt*)data; for (unsigned pos = 0; pos < numpos; pos++) out << " " << entList[pos]; diff --git a/ndb/src/kernel/blocks/dbtux/DbtuxGen.cpp b/ndb/src/kernel/blocks/dbtux/DbtuxGen.cpp index 93a5c78338c..f6f1610c8c1 100644 --- a/ndb/src/kernel/blocks/dbtux/DbtuxGen.cpp +++ b/ndb/src/kernel/blocks/dbtux/DbtuxGen.cpp @@ -26,8 +26,13 @@ Dbtux::Dbtux(const Configuration& conf) : #ifdef VM_TRACE debugFile(0), debugOut(*new NullOutputStream()), + // until ndb_mgm supports dump +#ifdef DBTUX_DEBUG_TREE + debugFlags(DebugTree), +#else debugFlags(0), #endif +#endif c_internalStartPhase(0), c_typeOfStart(NodeState::ST_ILLEGAL_TYPE), c_dataBuffer(0) @@ -187,6 +192,7 @@ Dbtux::execREAD_CONFIG_REQ(Signal* signal) IndexPtr indexPtr; while (1) { jam(); + refresh_watch_dog(); c_indexPool.seize(indexPtr); if (indexPtr.i == RNIL) { jam(); @@ -241,37 +247,14 @@ Dbtux::readKeyAttrs(const Frag& frag, TreeEnt ent, unsigned start, TableData key } void -Dbtux::copyAttrs(Data dst, ConstData src, CopyPar& copyPar) +Dbtux::readTablePk(const Frag& frag, TreeEnt ent, unsigned& pkSize, Data pkData) { - CopyPar c = copyPar; - c.m_numitems = 0; - c.m_numwords = 0; - while (c.m_numitems < c.m_items) { - jam(); - if (c.m_headers) { - unsigned i = 0; - while (i < AttributeHeaderSize) { - if (c.m_numwords >= c.m_maxwords) { - copyPar = c; - return; - } - dst[c.m_numwords++] = src[i++]; - } - } - unsigned size = src.ah().getDataSize(); - src += AttributeHeaderSize; - unsigned i = 0; - while (i < size) { - if (c.m_numwords >= c.m_maxwords) { - copyPar = c; - return; - } - dst[c.m_numwords++] = src[i++]; - } - src += size; - c.m_numitems++; - } - copyPar = c; + const Uint32 tableFragPtrI = frag.m_tupTableFragPtrI[ent.m_fragBit]; + const TupLoc tupLoc = ent.m_tupLoc; + Uint32 size = 0; + c_tup->tuxReadKeys(tableFragPtrI, tupLoc.m_pageId, tupLoc.m_pageOffset, &size, pkData); + ndbrequire(size != 0); + pkSize = size; } /* @@ -314,6 +297,9 @@ Dbtux::copyAttrs(const Frag& frag, TableData data1, Data data2, unsigned maxlen2 keyAttrs += 1; data1 += 1; } +#ifdef VM_TRACE + memset(data2, DataFillByte, len2 << 2); +#endif } BLOCK_FUNCTIONS(Dbtux); diff --git a/ndb/src/kernel/blocks/dbtux/DbtuxMaint.cpp b/ndb/src/kernel/blocks/dbtux/DbtuxMaint.cpp index fc72611a273..24b030bf8ec 100644 --- a/ndb/src/kernel/blocks/dbtux/DbtuxMaint.cpp +++ b/ndb/src/kernel/blocks/dbtux/DbtuxMaint.cpp @@ -82,8 +82,8 @@ Dbtux::execTUX_MAINT_REQ(Signal* signal) ent.m_fragBit = fragBit; // read search key readKeyAttrs(frag, ent, 0, c_searchKey); - // check if all keys are null - { + if (! frag.m_storeNullKey) { + // check if all keys are null const unsigned numAttrs = frag.m_numAttrs; bool allNull = true; for (unsigned i = 0; i < numAttrs; i++) { @@ -111,19 +111,18 @@ Dbtux::execTUX_MAINT_REQ(Signal* signal) debugOut << endl; } #endif - // find position in tree - TreePos treePos; - treeSearch(signal, frag, c_searchKey, ent, treePos); -#ifdef VM_TRACE - if (debugFlags & DebugMaint) { - debugOut << treePos << endl; - } -#endif // do the operation req->errorCode = 0; + TreePos treePos; switch (opCode) { case TuxMaintReq::OpAdd: jam(); + searchToAdd(signal, frag, c_searchKey, ent, treePos); +#ifdef VM_TRACE + if (debugFlags & DebugMaint) { + debugOut << treePos << endl; + } +#endif if (treePos.m_match) { jam(); // there is no "Building" state so this will have to do @@ -152,6 +151,12 @@ Dbtux::execTUX_MAINT_REQ(Signal* signal) break; case TuxMaintReq::OpRemove: jam(); + searchToRemove(signal, frag, c_searchKey, ent, treePos); +#ifdef VM_TRACE + if (debugFlags & DebugMaint) { + debugOut << treePos << endl; + } +#endif if (! treePos.m_match) { jam(); // there is no "Building" state so this will have to do @@ -167,7 +172,6 @@ Dbtux::execTUX_MAINT_REQ(Signal* signal) ndbrequire(false); break; } - // commit and release nodes #ifdef VM_TRACE if (debugFlags & DebugTree) { printTree(signal, frag, debugOut); @@ -176,89 +180,3 @@ Dbtux::execTUX_MAINT_REQ(Signal* signal) // copy back *sig = *req; } - -/* - * Read index key attributes from TUP. If buffer is provided the data - * is copied to it. Otherwise pointer is set to signal data. - */ -void -Dbtux::tupReadAttrs(Signal* signal, const Frag& frag, ReadPar& readPar) -{ - // define the direct signal - const TreeEnt ent = readPar.m_ent; - TupReadAttrs* const req = (TupReadAttrs*)signal->getDataPtrSend(); - req->errorCode = RNIL; - req->requestInfo = 0; - req->tableId = frag.m_tableId; - req->fragId = frag.m_fragId | (ent.m_fragBit << frag.m_fragOff); - req->fragPtrI = frag.m_tupTableFragPtrI[ent.m_fragBit]; - req->tupAddr = (Uint32)-1; - req->tupVersion = ent.m_tupVersion; - req->pageId = ent.m_tupLoc.m_pageId; - req->pageOffset = ent.m_tupLoc.m_pageOffset; - req->bufferId = 0; - // add count and list of attribute ids - Data data = (Uint32*)req + TupReadAttrs::SignalLength; - data[0] = readPar.m_count; - data += 1; - const DescEnt& descEnt = getDescEnt(frag.m_descPage, frag.m_descOff); - for (Uint32 i = 0; i < readPar.m_count; i++) { - jam(); - const DescAttr& descAttr = descEnt.m_descAttr[readPar.m_first + i]; - data.ah() = AttributeHeader(descAttr.m_primaryAttrId, 0); - data += 1; - } - // execute - EXECUTE_DIRECT(DBTUP, GSN_TUP_READ_ATTRS, signal, TupReadAttrs::SignalLength); - jamEntry(); - ndbrequire(req->errorCode == 0); - // data is at output - if (readPar.m_data == 0) { - readPar.m_data = data; - } else { - jam(); - CopyPar copyPar; - copyPar.m_items = readPar.m_count; - copyPar.m_headers = true; - copyAttrs(readPar.m_data, data, copyPar); - } -} - -/* - * Read primary keys. Copy the data without attribute headers into the - * given buffer. Number of words is returned in ReadPar argument. - */ -void -Dbtux::tupReadKeys(Signal* signal, const Frag& frag, ReadPar& readPar) -{ - // define the direct signal - const TreeEnt ent = readPar.m_ent; - TupReadAttrs* const req = (TupReadAttrs*)signal->getDataPtrSend(); - req->errorCode = RNIL; - req->requestInfo = TupReadAttrs::ReadKeys; - req->tableId = frag.m_tableId; - req->fragId = frag.m_fragId | (ent.m_fragBit << frag.m_fragOff); - req->fragPtrI = frag.m_tupTableFragPtrI[ent.m_fragBit]; - req->tupAddr = (Uint32)-1; - req->tupVersion = RNIL; // not used - req->pageId = ent.m_tupLoc.m_pageId; - req->pageOffset = ent.m_tupLoc.m_pageOffset; - req->bufferId = 0; - // execute - EXECUTE_DIRECT(DBTUP, GSN_TUP_READ_ATTRS, signal, TupReadAttrs::SignalLength); - jamEntry(); - ndbrequire(req->errorCode == 0); - // copy out in special format - ConstData data = (Uint32*)req + TupReadAttrs::SignalLength; - const Uint32 numKeys = data[0]; - data += 1 + numKeys; - // copy out without headers - ndbrequire(readPar.m_data != 0); - CopyPar copyPar; - copyPar.m_items = numKeys; - copyPar.m_headers = false; - copyAttrs(readPar.m_data, data, copyPar); - // return counts - readPar.m_count = numKeys; - readPar.m_size = copyPar.m_numwords; -} diff --git a/ndb/src/kernel/blocks/dbtux/DbtuxMeta.cpp b/ndb/src/kernel/blocks/dbtux/DbtuxMeta.cpp index 0612f191830..b30b555ccad 100644 --- a/ndb/src/kernel/blocks/dbtux/DbtuxMeta.cpp +++ b/ndb/src/kernel/blocks/dbtux/DbtuxMeta.cpp @@ -85,6 +85,7 @@ Dbtux::execTUXFRAGREQ(Signal* signal) fragPtr.p->m_fragOff = req->fragOff; fragPtr.p->m_fragId = req->fragId; fragPtr.p->m_numAttrs = req->noOfAttr; + fragPtr.p->m_storeNullKey = true; // not yet configurable fragPtr.p->m_tupIndexFragPtrI = req->tupIndexFragPtrI; fragPtr.p->m_tupTableFragPtrI[0] = req->tupTableFragPtrI[0]; fragPtr.p->m_tupTableFragPtrI[1] = req->tupTableFragPtrI[1]; @@ -111,6 +112,7 @@ Dbtux::execTUXFRAGREQ(Signal* signal) indexPtr.p->m_tableId = req->primaryTableId; indexPtr.p->m_fragOff = req->fragOff; indexPtr.p->m_numAttrs = req->noOfAttr; + indexPtr.p->m_storeNullKey = true; // not yet configurable // allocate attribute descriptors if (! allocDescEnt(indexPtr)) { jam(); @@ -405,14 +407,15 @@ Dbtux::freeDescEnt(IndexPtr indexPtr) index2.m_descPage == pagePtr.i && index2.m_descOff == off + size); // move the entry (overlapping copy if size < size2) - for (unsigned i = 0; i < size2; i++) { + unsigned i; + for (i = 0; i < size2; i++) { jam(); data[off + i] = data[off + size + i]; } off += size2; // adjust page offset in index and all fragments index2.m_descOff -= size; - for (unsigned i = 0; i < index2.m_numFrags; i++) { + for (i = 0; i < index2.m_numFrags; i++) { jam(); Frag& frag2 = *c_fragPool.getPtr(index2.m_fragPtrI[i]); frag2.m_descOff -= size; diff --git a/ndb/src/kernel/blocks/dbtux/DbtuxNode.cpp b/ndb/src/kernel/blocks/dbtux/DbtuxNode.cpp index c969e35dc82..a1bfa2179bb 100644 --- a/ndb/src/kernel/blocks/dbtux/DbtuxNode.cpp +++ b/ndb/src/kernel/blocks/dbtux/DbtuxNode.cpp @@ -85,10 +85,9 @@ Dbtux::insertNode(Signal* signal, NodeHandle& node, AccSize acc) new (node.m_node) TreeNode(); #ifdef VM_TRACE TreeHead& tree = frag.m_tree; - memset(node.getPref(0), 0xa2, tree.m_prefSize << 2); - memset(node.getPref(1), 0xa2, tree.m_prefSize << 2); + memset(node.getPref(), DataFillByte, tree.m_prefSize << 2); TreeEnt* entList = tree.getEntList(node.m_node); - memset(entList, 0xa4, (tree.m_maxOccup + 1) * (TreeEntSize << 2)); + memset(entList, NodeFillByte, (tree.m_maxOccup + 1) * (TreeEntSize << 2)); #endif } @@ -116,12 +115,12 @@ Dbtux::deleteNode(Signal* signal, NodeHandle& node) * attribute headers for now. XXX use null mask instead */ void -Dbtux::setNodePref(Signal* signal, NodeHandle& node, unsigned i) +Dbtux::setNodePref(Signal* signal, NodeHandle& node) { const Frag& frag = node.m_frag; const TreeHead& tree = frag.m_tree; - readKeyAttrs(frag, node.getMinMax(i), 0, c_entryKey); - copyAttrs(frag, c_entryKey, node.getPref(i), tree.m_prefSize); + readKeyAttrs(frag, node.getMinMax(0), 0, c_entryKey); + copyAttrs(frag, c_entryKey, node.getPref(), tree.m_prefSize); } // node operations @@ -173,11 +172,9 @@ Dbtux::nodePushUp(Signal* signal, NodeHandle& node, unsigned pos, const TreeEnt& tmpList[pos] = ent; entList[0] = entList[occup + 1]; node.setOccup(occup + 1); - // fix prefixes + // fix prefix if (occup == 0 || pos == 0) - setNodePref(signal, node, 0); - if (occup == 0 || pos == occup) - setNodePref(signal, node, 1); + setNodePref(signal, node); } /* @@ -248,11 +245,9 @@ Dbtux::nodePopDown(Signal* signal, NodeHandle& node, unsigned pos, TreeEnt& ent) } entList[0] = entList[occup - 1]; node.setOccup(occup - 1); - // fix prefixes + // fix prefix if (occup != 1 && pos == 0) - setNodePref(signal, node, 0); - if (occup != 1 && pos == occup - 1) - setNodePref(signal, node, 1); + setNodePref(signal, node); } /* @@ -325,11 +320,9 @@ Dbtux::nodePushDown(Signal* signal, NodeHandle& node, unsigned pos, TreeEnt& ent tmpList[pos] = ent; ent = oldMin; entList[0] = entList[occup]; - // fix prefixes + // fix prefix if (true) - setNodePref(signal, node, 0); - if (occup == 1 || pos == occup - 1) - setNodePref(signal, node, 1); + setNodePref(signal, node); } /* @@ -403,11 +396,9 @@ Dbtux::nodePopUp(Signal* signal, NodeHandle& node, unsigned pos, TreeEnt& ent) } tmpList[0] = newMin; entList[0] = entList[occup]; - // fix prefixes + // fix prefix if (true) - setNodePref(signal, node, 0); - if (occup == 1 || pos == occup - 1) - setNodePref(signal, node, 1); + setNodePref(signal, node); } /* diff --git a/ndb/src/kernel/blocks/dbtux/DbtuxScan.cpp b/ndb/src/kernel/blocks/dbtux/DbtuxScan.cpp index 703b0abb683..c4c33ff931f 100644 --- a/ndb/src/kernel/blocks/dbtux/DbtuxScan.cpp +++ b/ndb/src/kernel/blocks/dbtux/DbtuxScan.cpp @@ -137,7 +137,7 @@ Dbtux::execTUX_BOUND_INFO(Signal* signal) const Uint32* const data = (Uint32*)sig + TuxBoundInfo::SignalLength; unsigned offset = 5; // walk through entries - while (offset + 2 < req->boundAiLength) { + while (offset + 2 <= req->boundAiLength) { jam(); const unsigned type = data[offset]; if (type > 4) { @@ -379,8 +379,8 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal) scanNext(signal, scanPtr); } // for reading tuple key in Current or Locked state - ReadPar keyPar; - keyPar.m_data = 0; // indicates not yet done + Data pkData = c_dataBuffer; + unsigned pkSize = 0; // indicates not yet done if (scan.m_state == ScanOp::Current) { // found an entry to return jam(); @@ -389,9 +389,7 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal) jam(); const TreeEnt ent = scan.m_scanPos.m_ent; // read tuple key - keyPar.m_ent = ent; - keyPar.m_data = c_dataBuffer; - tupReadKeys(signal, frag, keyPar); + readTablePk(frag, ent, pkSize, pkData); // get read lock or exclusive lock AccLockReq* const lockReq = (AccLockReq*)signal->getDataPtrSend(); lockReq->returnCode = RNIL; @@ -403,9 +401,9 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal) lockReq->tableId = scan.m_tableId; lockReq->fragId = frag.m_fragId | (ent.m_fragBit << frag.m_fragOff); lockReq->fragPtrI = frag.m_accTableFragPtrI[ent.m_fragBit]; - const Uint32* const buf32 = static_cast<Uint32*>(keyPar.m_data); + const Uint32* const buf32 = static_cast<Uint32*>(pkData); const Uint64* const buf64 = reinterpret_cast<const Uint64*>(buf32); - lockReq->hashValue = md5_hash(buf64, keyPar.m_size); + lockReq->hashValue = md5_hash(buf64, pkSize); lockReq->tupAddr = getTupAddr(frag, ent); lockReq->transId1 = scan.m_transId1; lockReq->transId2 = scan.m_transId2; @@ -480,11 +478,9 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal) const TreeEnt ent = scan.m_scanPos.m_ent; if (scan.m_keyInfo) { jam(); - if (keyPar.m_data == 0) { + if (pkSize == 0) { jam(); - keyPar.m_ent = ent; - keyPar.m_data = c_dataBuffer; - tupReadKeys(signal, frag, keyPar); + readTablePk(frag, ent, pkSize, pkData); } } // conf signal @@ -510,10 +506,10 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal) // add key info if (scan.m_keyInfo) { jam(); - conf->keyLength = keyPar.m_size; + conf->keyLength = pkSize; // piggy-back first 4 words of key data for (unsigned i = 0; i < 4; i++) { - conf->key[i] = i < keyPar.m_size ? keyPar.m_data[i] : 0; + conf->key[i] = i < pkSize ? pkData[i] : 0; } signalLength = 11; } @@ -525,18 +521,18 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal) EXECUTE_DIRECT(blockNo, GSN_NEXT_SCANCONF, signal, signalLength); } // send rest of key data - if (scan.m_keyInfo && keyPar.m_size > 4) { + if (scan.m_keyInfo && pkSize > 4) { unsigned total = 4; - while (total < keyPar.m_size) { + while (total < pkSize) { jam(); - unsigned length = keyPar.m_size - total; + unsigned length = pkSize - total; if (length > 20) length = 20; signal->theData[0] = scan.m_userPtr; signal->theData[1] = 0; signal->theData[2] = 0; signal->theData[3] = length; - memcpy(&signal->theData[4], &keyPar.m_data[total], length << 2); + memcpy(&signal->theData[4], &pkData[total], length << 2); sendSignal(scan.m_userRef, GSN_ACC_SCAN_INFO24, signal, 4 + length, JBB); total += length; @@ -606,6 +602,8 @@ Dbtux::execACCKEYCONF(Signal* signal) // LQH has the ball return; } + // lose the lock + scan.m_accLockOp = RNIL; // continue at ACC_ABORTCONF } @@ -648,6 +646,8 @@ Dbtux::execACCKEYREF(Signal* signal) // LQH has the ball return; } + // lose the lock + scan.m_accLockOp = RNIL; // continue at ACC_ABORTCONF } @@ -689,16 +689,9 @@ Dbtux::scanFirst(Signal* signal, ScanOpPtr scanPtr) ScanOp& scan = *scanPtr.p; Frag& frag = *c_fragPool.getPtr(scan.m_fragPtrI); TreeHead& tree = frag.m_tree; - if (tree.m_root == NullTupLoc) { - // tree may have become empty - jam(); - scan.m_state = ScanOp::Last; - return; - } - TreePos pos; - pos.m_loc = tree.m_root; - NodeHandle node(frag); - // unpack lower bound + // set up index keys for this operation + setKeyAttrs(frag); + // unpack lower bound into c_dataBuffer const ScanBound& bound = *scan.m_bound[0]; ScanBoundIterator iter; bound.first(iter); @@ -707,103 +700,22 @@ Dbtux::scanFirst(Signal* signal, ScanOpPtr scanPtr) c_dataBuffer[j] = *iter.data; bound.next(iter); } - // comparison parameters - BoundPar boundPar; - boundPar.m_data1 = c_dataBuffer; - boundPar.m_count1 = scan.m_boundCnt[0]; - boundPar.m_dir = 0; -loop: { + // search for scan start position + TreePos treePos; + searchToScan(signal, frag, c_dataBuffer, scan.m_boundCnt[0], treePos); + if (treePos.m_loc == NullTupLoc) { + // empty tree jam(); - selectNode(signal, node, pos.m_loc, AccPref); - const unsigned occup = node.getOccup(); - ndbrequire(occup != 0); - for (unsigned i = 0; i <= 1; i++) { - jam(); - // compare prefix - boundPar.m_data2 = node.getPref(i); - boundPar.m_len2 = tree.m_prefSize; - int ret = cmpScanBound(frag, boundPar); - if (ret == NdbSqlUtil::CmpUnknown) { - jam(); - // read full value - ReadPar readPar; - readPar.m_ent = node.getMinMax(i); - readPar.m_first = 0; - readPar.m_count = frag.m_numAttrs; - readPar.m_data = 0; // leave in signal data - tupReadAttrs(signal, frag, readPar); - // compare full value - boundPar.m_data2 = readPar.m_data; - boundPar.m_len2 = ZNIL; // big - ret = cmpScanBound(frag, boundPar); - ndbrequire(ret != NdbSqlUtil::CmpUnknown); - } - if (i == 0 && ret < 0) { - jam(); - const TupLoc loc = node.getLink(i); - if (loc != NullTupLoc) { - jam(); - // continue to left subtree - pos.m_loc = loc; - goto loop; - } - // start scanning this node - pos.m_pos = 0; - pos.m_match = false; - pos.m_dir = 3; - scan.m_scanPos = pos; - scan.m_state = ScanOp::Next; - linkScan(node, scanPtr); - return; - } - if (i == 1 && ret > 0) { - jam(); - const TupLoc loc = node.getLink(i); - if (loc != NullTupLoc) { - jam(); - // continue to right subtree - pos.m_loc = loc; - goto loop; - } - // start scanning upwards - pos.m_dir = 1; - scan.m_scanPos = pos; - scan.m_state = ScanOp::Next; - linkScan(node, scanPtr); - return; - } - } - // read rest of current node - accessNode(signal, node, AccFull); - // look for first entry - ndbrequire(occup >= 2); - for (unsigned j = 1; j < occup; j++) { - jam(); - ReadPar readPar; - readPar.m_ent = node.getEnt(j); - readPar.m_first = 0; - readPar.m_count = frag.m_numAttrs; - readPar.m_data = 0; // leave in signal data - tupReadAttrs(signal, frag, readPar); - // compare - boundPar.m_data2 = readPar.m_data; - boundPar.m_len2 = ZNIL; // big - int ret = cmpScanBound(frag, boundPar); - ndbrequire(ret != NdbSqlUtil::CmpUnknown); - if (ret < 0) { - jam(); - // start scanning this node - pos.m_pos = j; - pos.m_match = false; - pos.m_dir = 3; - scan.m_scanPos = pos; - scan.m_state = ScanOp::Next; - linkScan(node, scanPtr); - return; - } - } - ndbrequire(false); + scan.m_state = ScanOp::Last; + return; } + // set position and state + scan.m_scanPos = treePos; + scan.m_state = ScanOp::Next; + // link the scan to node found + NodeHandle node(frag); + selectNode(signal, node, treePos.m_loc, AccFull); + linkScan(node, scanPtr); } /* @@ -830,7 +742,9 @@ Dbtux::scanNext(Signal* signal, ScanOpPtr scanPtr) if (scan.m_state == ScanOp::Locked) { jam(); // version of a tuple locked by us cannot disappear (assert only) +#ifdef dbtux_wl_1942_is_done ndbassert(false); +#endif AccLockReq* const lockReq = (AccLockReq*)signal->getDataPtrSend(); lockReq->returnCode = RNIL; lockReq->requestInfo = AccLockReq::Unlock; @@ -841,7 +755,9 @@ Dbtux::scanNext(Signal* signal, ScanOpPtr scanPtr) scan.m_accLockOp = RNIL; scan.m_state = ScanOp::Current; } - // unpack upper bound + // set up index keys for this operation + setKeyAttrs(frag); + // unpack upper bound into c_dataBuffer const ScanBound& bound = *scan.m_bound[1]; ScanBoundIterator iter; bound.first(iter); @@ -850,11 +766,6 @@ Dbtux::scanNext(Signal* signal, ScanOpPtr scanPtr) c_dataBuffer[j] = *iter.data; bound.next(iter); } - // comparison parameters - BoundPar boundPar; - boundPar.m_data1 = c_dataBuffer; - boundPar.m_count1 = scan.m_boundCnt[1]; - boundPar.m_dir = 1; // use copy of position TreePos pos = scan.m_scanPos; // get and remember original node @@ -912,17 +823,9 @@ Dbtux::scanNext(Signal* signal, ScanOpPtr scanPtr) jam(); pos.m_ent = node.getEnt(pos.m_pos); pos.m_dir = 3; // unchanged - // XXX implement prefix optimization - ReadPar readPar; - readPar.m_ent = pos.m_ent; - readPar.m_first = 0; - readPar.m_count = frag.m_numAttrs; - readPar.m_data = 0; // leave in signal data - tupReadAttrs(signal, frag, readPar); - // compare - boundPar.m_data2 = readPar.m_data; - boundPar.m_len2 = ZNIL; // big - int ret = cmpScanBound(frag, boundPar); + // read and compare all attributes + readKeyAttrs(frag, pos.m_ent, 0, c_entryKey); + int ret = cmpScanBound(frag, 1, c_dataBuffer, scan.m_boundCnt[1], c_entryKey); ndbrequire(ret != NdbSqlUtil::CmpUnknown); if (ret < 0) { jam(); @@ -994,35 +897,25 @@ Dbtux::scanNext(Signal* signal, ScanOpPtr scanPtr) bool Dbtux::scanVisible(Signal* signal, ScanOpPtr scanPtr, TreeEnt ent) { - TupQueryTh* const req = (TupQueryTh*)signal->getDataPtrSend(); const ScanOp& scan = *scanPtr.p; const Frag& frag = *c_fragPool.getPtr(scan.m_fragPtrI); - /* Assign table, fragment, tuple address + version */ - Uint32 tableId = frag.m_tableId; Uint32 fragBit = ent.m_fragBit; + Uint32 tableFragPtrI = frag.m_tupTableFragPtrI[fragBit]; Uint32 fragId = frag.m_fragId | (fragBit << frag.m_fragOff); Uint32 tupAddr = getTupAddr(frag, ent); Uint32 tupVersion = ent.m_tupVersion; - /* Check for same tuple twice in row */ + // check for same tuple twice in row if (scan.m_lastEnt.m_tupLoc == ent.m_tupLoc && scan.m_lastEnt.m_fragBit == fragBit) { jam(); return false; } - req->tableId = tableId; - req->fragId = fragId; - req->tupAddr = tupAddr; - req->tupVersion = tupVersion; - /* Assign transaction info, trans id + savepoint id */ Uint32 transId1 = scan.m_transId1; Uint32 transId2 = scan.m_transId2; Uint32 savePointId = scan.m_savePointId; - req->transId1 = transId1; - req->transId2 = transId2; - req->savePointId = savePointId; - EXECUTE_DIRECT(DBTUP, GSN_TUP_QUERY_TH, signal, TupQueryTh::SignalLength); + bool ret = c_tup->tuxQueryTh(tableFragPtrI, tupAddr, tupVersion, transId1, transId2, savePointId); jamEntry(); - return (bool)req->returnCode; + return ret; } /* diff --git a/ndb/src/kernel/blocks/dbtux/DbtuxSearch.cpp b/ndb/src/kernel/blocks/dbtux/DbtuxSearch.cpp new file mode 100644 index 00000000000..84048b308bc --- /dev/null +++ b/ndb/src/kernel/blocks/dbtux/DbtuxSearch.cpp @@ -0,0 +1,333 @@ +/* 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 */ + +#define DBTUX_SEARCH_CPP +#include "Dbtux.hpp" + +/* + * Search for entry to add. + * + * Similar to searchToRemove (see below). + * + * TODO optimize for initial equal attrs in node min/max + */ +void +Dbtux::searchToAdd(Signal* signal, Frag& frag, TableData searchKey, TreeEnt searchEnt, TreePos& treePos) +{ + const TreeHead& tree = frag.m_tree; + const unsigned numAttrs = frag.m_numAttrs; + NodeHandle currNode(frag); + currNode.m_loc = tree.m_root; + if (currNode.m_loc == NullTupLoc) { + // empty tree + jam(); + treePos.m_match = false; + return; + } + NodeHandle glbNode(frag); // potential g.l.b of final node + /* + * In order to not (yet) change old behaviour, a position between + * 2 nodes returns the one at the bottom of the tree. + */ + NodeHandle bottomNode(frag); + while (true) { + jam(); + selectNode(signal, currNode, currNode.m_loc, AccPref); + int ret; + // compare prefix + unsigned start = 0; + ret = cmpSearchKey(frag, start, searchKey, currNode.getPref(), tree.m_prefSize); + if (ret == NdbSqlUtil::CmpUnknown) { + jam(); + // read and compare remaining attributes + ndbrequire(start < numAttrs); + readKeyAttrs(frag, currNode.getMinMax(0), start, c_entryKey); + ret = cmpSearchKey(frag, start, searchKey, c_entryKey); + ndbrequire(ret != NdbSqlUtil::CmpUnknown); + } + if (ret == 0) { + jam(); + // keys are equal, compare entry values + ret = searchEnt.cmp(currNode.getMinMax(0)); + } + if (ret < 0) { + jam(); + const TupLoc loc = currNode.getLink(0); + if (loc != NullTupLoc) { + jam(); + // continue to left subtree + currNode.m_loc = loc; + continue; + } + if (! glbNode.isNull()) { + jam(); + // move up to the g.l.b but remember the bottom node + bottomNode = currNode; + currNode = glbNode; + } + } else if (ret > 0) { + jam(); + const TupLoc loc = currNode.getLink(1); + if (loc != NullTupLoc) { + jam(); + // save potential g.l.b + glbNode = currNode; + // continue to right subtree + currNode.m_loc = loc; + continue; + } + } else { + jam(); + treePos.m_loc = currNode.m_loc; + treePos.m_pos = 0; + treePos.m_match = true; + return; + } + break; + } + // access rest of current node + accessNode(signal, currNode, AccFull); + for (unsigned j = 0, occup = currNode.getOccup(); j < occup; j++) { + jam(); + int ret; + // read and compare attributes + unsigned start = 0; + readKeyAttrs(frag, currNode.getEnt(j), start, c_entryKey); + ret = cmpSearchKey(frag, start, searchKey, c_entryKey); + ndbrequire(ret != NdbSqlUtil::CmpUnknown); + if (ret == 0) { + jam(); + // keys are equal, compare entry values + ret = searchEnt.cmp(currNode.getEnt(j)); + } + if (ret <= 0) { + jam(); + treePos.m_loc = currNode.m_loc; + treePos.m_pos = j; + treePos.m_match = (ret == 0); + return; + } + } + if (! bottomNode.isNull()) { + jam(); + // backwards compatible for now + treePos.m_loc = bottomNode.m_loc; + treePos.m_pos = 0; + treePos.m_match = false; + return; + } + treePos.m_loc = currNode.m_loc; + treePos.m_pos = currNode.getOccup(); + treePos.m_match = false; +} + +/* + * Search for entry to remove. + * + * Compares search key to each node min. A move to right subtree can + * overshoot target node. The last such node is saved. The final node + * is a half-leaf or leaf. If search key is less than final node min + * then the saved node is the g.l.b of the final node and we move back + * to it. + */ +void +Dbtux::searchToRemove(Signal* signal, Frag& frag, TableData searchKey, TreeEnt searchEnt, TreePos& treePos) +{ + const TreeHead& tree = frag.m_tree; + const unsigned numAttrs = frag.m_numAttrs; + NodeHandle currNode(frag); + currNode.m_loc = tree.m_root; + if (currNode.m_loc == NullTupLoc) { + // empty tree + jam(); + treePos.m_match = false; + return; + } + NodeHandle glbNode(frag); // potential g.l.b of final node + while (true) { + jam(); + selectNode(signal, currNode, currNode.m_loc, AccPref); + int ret; + // compare prefix + unsigned start = 0; + ret = cmpSearchKey(frag, start, searchKey, currNode.getPref(), tree.m_prefSize); + if (ret == NdbSqlUtil::CmpUnknown) { + jam(); + // read and compare remaining attributes + ndbrequire(start < numAttrs); + readKeyAttrs(frag, currNode.getMinMax(0), start, c_entryKey); + ret = cmpSearchKey(frag, start, searchKey, c_entryKey); + ndbrequire(ret != NdbSqlUtil::CmpUnknown); + } + if (ret == 0) { + jam(); + // keys are equal, compare entry values + ret = searchEnt.cmp(currNode.getMinMax(0)); + } + if (ret < 0) { + jam(); + const TupLoc loc = currNode.getLink(0); + if (loc != NullTupLoc) { + jam(); + // continue to left subtree + currNode.m_loc = loc; + continue; + } + if (! glbNode.isNull()) { + jam(); + // move up to the g.l.b + currNode = glbNode; + } + } else if (ret > 0) { + jam(); + const TupLoc loc = currNode.getLink(1); + if (loc != NullTupLoc) { + jam(); + // save potential g.l.b + glbNode = currNode; + // continue to right subtree + currNode.m_loc = loc; + continue; + } + } else { + jam(); + treePos.m_loc = currNode.m_loc; + treePos.m_pos = 0; + treePos.m_match = true; + return; + } + break; + } + // access rest of current node + accessNode(signal, currNode, AccFull); + // pos 0 was handled above + for (unsigned j = 1, occup = currNode.getOccup(); j < occup; j++) { + jam(); + // compare only the entry + if (searchEnt.eq(currNode.getEnt(j))) { + jam(); + treePos.m_loc = currNode.m_loc; + treePos.m_pos = j; + treePos.m_match = true; + return; + } + } + treePos.m_loc = currNode.m_loc; + treePos.m_pos = currNode.getOccup(); + treePos.m_match = false; +} + +/* + * Search for scan start position. + * + * Similar to searchToAdd. + */ +void +Dbtux::searchToScan(Signal* signal, Frag& frag, ConstData boundInfo, unsigned boundCount, TreePos& treePos) +{ + const TreeHead& tree = frag.m_tree; + NodeHandle currNode(frag); + currNode.m_loc = tree.m_root; + if (currNode.m_loc == NullTupLoc) { + // empty tree + jam(); + treePos.m_match = false; + return; + } + NodeHandle glbNode(frag); // potential g.l.b of final node + NodeHandle bottomNode(frag); + while (true) { + jam(); + selectNode(signal, currNode, currNode.m_loc, AccPref); + int ret; + // compare prefix + ret = cmpScanBound(frag, 0, boundInfo, boundCount, currNode.getPref(), tree.m_prefSize); + if (ret == NdbSqlUtil::CmpUnknown) { + jam(); + // read and compare all attributes + readKeyAttrs(frag, currNode.getMinMax(0), 0, c_entryKey); + ret = cmpScanBound(frag, 0, boundInfo, boundCount, c_entryKey); + ndbrequire(ret != NdbSqlUtil::CmpUnknown); + } + if (ret < 0) { + jam(); + const TupLoc loc = currNode.getLink(0); + if (loc != NullTupLoc) { + jam(); + // continue to left subtree + currNode.m_loc = loc; + continue; + } + if (! glbNode.isNull()) { + jam(); + // move up to the g.l.b but remember the bottom node + bottomNode = currNode; + currNode = glbNode; + } else { + // start scanning this node + treePos.m_loc = currNode.m_loc; + treePos.m_pos = 0; + treePos.m_match = false; + treePos.m_dir = 3; + return; + } + } else if (ret > 0) { + jam(); + const TupLoc loc = currNode.getLink(1); + if (loc != NullTupLoc) { + jam(); + // save potential g.l.b + glbNode = currNode; + // continue to right subtree + currNode.m_loc = loc; + continue; + } + } else { + ndbassert(false); + } + break; + } + // access rest of current node + accessNode(signal, currNode, AccFull); + for (unsigned j = 0, occup = currNode.getOccup(); j < occup; j++) { + jam(); + int ret; + // read and compare attributes + readKeyAttrs(frag, currNode.getEnt(j), 0, c_entryKey); + ret = cmpScanBound(frag, 0, boundInfo, boundCount, c_entryKey); + ndbrequire(ret != NdbSqlUtil::CmpUnknown); + if (ret < 0) { + // start scanning from current entry + treePos.m_loc = currNode.m_loc; + treePos.m_pos = j; + treePos.m_match = false; + treePos.m_dir = 3; + return; + } + } + if (! bottomNode.isNull()) { + jam(); + // start scanning the l.u.b + treePos.m_loc = bottomNode.m_loc; + treePos.m_pos = 0; + treePos.m_match = false; + treePos.m_dir = 3; + return; + } + // start scanning upwards (pretend we came from right child) + treePos.m_loc = currNode.m_loc; + treePos.m_dir = 1; +} diff --git a/ndb/src/kernel/blocks/dbtux/DbtuxTree.cpp b/ndb/src/kernel/blocks/dbtux/DbtuxTree.cpp index 7c3f5fa36b8..3baa62998db 100644 --- a/ndb/src/kernel/blocks/dbtux/DbtuxTree.cpp +++ b/ndb/src/kernel/blocks/dbtux/DbtuxTree.cpp @@ -18,112 +18,6 @@ #include "Dbtux.hpp" /* - * Search for entry. - * - * Search key is index attribute data and tree entry value. Start from - * root node and compare the key to min/max of each node. Use linear - * search on the final (bounding) node. Initial attributes which are - * same in min/max need not be checked. - */ -void -Dbtux::treeSearch(Signal* signal, Frag& frag, TableData searchKey, TreeEnt searchEnt, TreePos& treePos) -{ - const TreeHead& tree = frag.m_tree; - const unsigned numAttrs = frag.m_numAttrs; - treePos.m_loc = tree.m_root; - if (treePos.m_loc == NullTupLoc) { - // empty tree - jam(); - treePos.m_pos = 0; - treePos.m_match = false; - return; - } - NodeHandle node(frag); -loop: { - jam(); - selectNode(signal, node, treePos.m_loc, AccPref); - const unsigned occup = node.getOccup(); - ndbrequire(occup != 0); - // number of equal initial attributes in bounding node - unsigned start = ZNIL; - for (unsigned i = 0; i <= 1; i++) { - jam(); - unsigned start1 = 0; - // compare prefix - int ret = cmpSearchKey(frag, start1, searchKey, node.getPref(i), tree.m_prefSize); - if (ret == NdbSqlUtil::CmpUnknown) { - jam(); - // read and compare remaining attributes - readKeyAttrs(frag, node.getMinMax(i), start1, c_entryKey); - ret = cmpSearchKey(frag, start1, searchKey, c_entryKey); - ndbrequire(ret != NdbSqlUtil::CmpUnknown); - } - if (start > start1) - start = start1; - if (ret == 0) { - jam(); - // keys are equal, compare entry values - ret = searchEnt.cmp(node.getMinMax(i)); - } - if (i == 0 ? (ret < 0) : (ret > 0)) { - jam(); - const TupLoc loc = node.getLink(i); - if (loc != NullTupLoc) { - jam(); - // continue to left/right subtree - treePos.m_loc = loc; - goto loop; - } - // position is immediately before/after this node - treePos.m_pos = (i == 0 ? 0 : occup); - treePos.m_match = false; - return; - } - if (ret == 0) { - jam(); - // position is at first/last entry - treePos.m_pos = (i == 0 ? 0 : occup - 1); - treePos.m_match = true; - return; - } - } - // access rest of the bounding node - accessNode(signal, node, AccFull); - // position is strictly within the node - ndbrequire(occup >= 2); - const unsigned numWithin = occup - 2; - for (unsigned j = 1; j <= numWithin; j++) { - jam(); - int ret = 0; - if (start < numAttrs) { - jam(); - // read and compare remaining attributes - unsigned start1 = start; - readKeyAttrs(frag, node.getEnt(j), start1, c_entryKey); - ret = cmpSearchKey(frag, start1, searchKey, c_entryKey); - ndbrequire(ret != NdbSqlUtil::CmpUnknown); - } - if (ret == 0) { - jam(); - // keys are equal, compare entry values - ret = searchEnt.cmp(node.getEnt(j)); - } - if (ret <= 0) { - jam(); - // position is before or at this entry - treePos.m_pos = j; - treePos.m_match = (ret == 0); - return; - } - } - // position is before last entry - treePos.m_pos = occup - 1; - treePos.m_match = false; - return; - } -} - -/* * Add entry. */ void @@ -283,7 +177,8 @@ Dbtux::treeRemove(Signal* signal, Frag& frag, TreePos treePos) nodePopDown(signal, node, pos, ent); ndbrequire(node.getChilds() <= 1); // handle half-leaf - for (unsigned i = 0; i <= 1; i++) { + unsigned i; + for (i = 0; i <= 1; i++) { jam(); TupLoc childLoc = node.getLink(i); if (childLoc != NullTupLoc) { @@ -297,7 +192,7 @@ Dbtux::treeRemove(Signal* signal, Frag& frag, TreePos treePos) // get parent if any TupLoc parentLoc = node.getLink(2); NodeHandle parentNode(frag); - unsigned i = node.getSide(); + i = node.getSide(); // move all that fits into parent if (parentLoc != NullTupLoc) { jam(); diff --git a/ndb/src/kernel/blocks/dbtux/Makefile.am b/ndb/src/kernel/blocks/dbtux/Makefile.am index 0b48ad5724f..7d012924522 100644 --- a/ndb/src/kernel/blocks/dbtux/Makefile.am +++ b/ndb/src/kernel/blocks/dbtux/Makefile.am @@ -7,6 +7,7 @@ libdbtux_a_SOURCES = \ DbtuxNode.cpp \ DbtuxTree.cpp \ DbtuxScan.cpp \ + DbtuxSearch.cpp \ DbtuxCmp.cpp \ DbtuxDebug.cpp diff --git a/ndb/src/kernel/blocks/dbtux/Times.txt b/ndb/src/kernel/blocks/dbtux/Times.txt index 16c4102249b..c4744a23c07 100644 --- a/ndb/src/kernel/blocks/dbtux/Times.txt +++ b/ndb/src/kernel/blocks/dbtux/Times.txt @@ -1,17 +1,32 @@ -index maintenance overhead -========================== +ordered index performance +========================= "mc02" 2x1700 MHz linux-2.4.9 gcc-2.96 -O3 one db-node -case a: index on Unsigned -testOIBasic -case u -table 1 -index 1 -fragtype small -threads 10 -rows 100000 -subloop 1 -nologging +case a: maintenance: index on Unsigned +testOIBasic -case u -table 1 -index 2 -fragtype small -threads 10 -rows 100000 -subloop 1 -nologging -case b: index on Varchar(5) + Varchar(5) + Varchar(20) + Unsigned -testOIBasic -case u -table 2 -index 4 -fragtype small -threads 10 -rows 100000 -subloop 1 -nologging +case b: maintenance: index on Varchar(5) + Varchar(5) + Varchar(20) + Unsigned +testOIBasic -case u -table 2 -index 5 -fragtype small -threads 10 -rows 100000 -subloop 1 -nologging +case c: full scan: index on PK Unsigned +testOIBasic -case v -table 1 -index 1 -fragtype small -threads 10 -rows 100000 -subloop 1 -nologging + +case d: scan 1 tuple via EQ: index on PK Unsigned +testOIBasic -case w -table 1 -index 1 -fragtype small -threads 10 -rows 100000 -samples 10000 -subloop 1 -nologging -v2 + +a, b 1 million rows, pk update without index, pk update with index shows ms / 1000 rows for each and pct overhead -the figures are based on single run on idle machine + +c +1 million rows, index on PK, full table scan, full index scan +shows ms / 1000 rows for each and index time overhead + +d +1 million rows, index on PK, read table via each pk, scan index for each pk +shows ms / 1000 rows for each and index time overhead +samples 10% of all PKs (100,000 pk reads, 100,000 scans) 040616 mc02/a 40 ms 87 ms 114 pct mc02/b 51 ms 128 ms 148 pct @@ -49,4 +64,22 @@ optim 10 mc02/a 44 ms 65 ms 46 pct optim 11 mc02/a 43 ms 63 ms 46 pct mc02/b 52 ms 86 ms 63 pct +optim 12 mc02/a 38 ms 55 ms 43 pct + mc02/b 47 ms 77 ms 63 pct + mc02/c 10 ms 14 ms 47 pct + mc02/d 176 ms 281 ms 59 pct + +optim 13 mc02/a 40 ms 57 ms 42 pct + mc02/b 47 ms 77 ms 61 pct + mc02/c 9 ms 13 ms 50 pct + mc02/d 170 ms 256 ms 50 pct + +after wl-1884 store all-NULL keys (the tests have pctnull=10 per column) +[ what happened to PK read performance? ] + +optim 13 mc02/a 39 ms 59 ms 50 pct + mc02/b 47 ms 77 ms 61 pct + mc02/c 9 ms 12 ms 44 pct + mc02/d 246 ms 289 ms 17 pct + vim: set et: diff --git a/ndb/src/kernel/blocks/dbutil/DbUtil.cpp b/ndb/src/kernel/blocks/dbutil/DbUtil.cpp index 92410e1a784..ecaead3ba5a 100644 --- a/ndb/src/kernel/blocks/dbutil/DbUtil.cpp +++ b/ndb/src/kernel/blocks/dbutil/DbUtil.cpp @@ -2581,3 +2581,5 @@ DbUtil::execUTIL_DESTORY_LOCK_REQ(Signal* signal){ sendSignal(req.senderRef, GSN_UTIL_DESTROY_LOCK_REF, signal, UtilDestroyLockRef::SignalLength, JBB); } + +template class ArrayPool<DbUtil::Page32>; diff --git a/ndb/src/kernel/blocks/grep/Grep.cpp b/ndb/src/kernel/blocks/grep/Grep.cpp index ee506ce922a..8b93ef9cd20 100644 --- a/ndb/src/kernel/blocks/grep/Grep.cpp +++ b/ndb/src/kernel/blocks/grep/Grep.cpp @@ -73,7 +73,7 @@ Grep::getNodeGroupMembers(Signal* signal) { c_noNodesInGroup++; } } - ndbrequire(c_noNodesInGroup >= 0); // at least 1 node in the nodegroup + ndbrequire(c_noNodesInGroup > 0); // at least 1 node in the nodegroup #ifdef NODEFAIL_DEBUG for (Uint32 i = 0; i < c_noNodesInGroup; i++) { @@ -253,7 +253,8 @@ Grep::execREAD_NODESCONF(Signal* signal) /****************************** * Check which REP nodes exist ******************************/ - for (Uint32 i = 1; i < MAX_NODES; i++) + Uint32 i; + for (i = 1; i < MAX_NODES; i++) { jam(); #if 0 @@ -279,7 +280,7 @@ Grep::execREAD_NODESCONF(Signal* signal) m_aliveNodes.clear(); Uint32 count = 0; - for(Uint32 i = 0; i<MAX_NDB_NODES; i++) + for(i = 0; i<MAX_NDB_NODES; i++) { if (NodeBitmask::get(conf->allNodes, i)) { diff --git a/ndb/src/kernel/blocks/grep/Grep.hpp b/ndb/src/kernel/blocks/grep/Grep.hpp index ba8f5780522..eeabac36966 100644 --- a/ndb/src/kernel/blocks/grep/Grep.hpp +++ b/ndb/src/kernel/blocks/grep/Grep.hpp @@ -148,7 +148,7 @@ private: */ class Grep : public SimulatedBlock //GrepParticipant { - //BLOCK_DEFINES(Grep); + BLOCK_DEFINES(Grep); public: Grep(const Configuration & conf); @@ -519,19 +519,6 @@ public: typedef void (Grep::* ExecSignalLocal1) (Signal* signal); typedef void (Grep::PSCoord::* ExecSignalLocal2) (Signal* signal); typedef void (Grep::PSPart::* ExecSignalLocal4) (Signal* signal); - - void - addRecSignal(GlobalSignalNumber gsn, ExecSignalLocal1 f, bool force = false){ - addRecSignalImpl(gsn, (ExecFunction)f, force); - } - void - addRecSignal(GlobalSignalNumber gsn, ExecSignalLocal2 f, bool force = false){ - addRecSignalImpl(gsn, (ExecFunction)f, force); - } - void - addRecSignal(GlobalSignalNumber gsn, ExecSignalLocal4 f, bool force = false){ - addRecSignalImpl(gsn, (ExecFunction)f, force); - } }; diff --git a/ndb/src/kernel/blocks/grep/GrepInit.cpp b/ndb/src/kernel/blocks/grep/GrepInit.cpp index 70bf6678754..cfb454a1f9b 100644 --- a/ndb/src/kernel/blocks/grep/GrepInit.cpp +++ b/ndb/src/kernel/blocks/grep/GrepInit.cpp @@ -132,7 +132,7 @@ Grep::~Grep() { } -//BLOCK_FUNCTIONS(Grep); +BLOCK_FUNCTIONS(Grep); Grep::PSPart::PSPart(Grep * sb) : BlockComponent(sb), diff --git a/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp b/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp index 06453155f33..ff4876b1506 100644 --- a/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp +++ b/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp @@ -554,11 +554,13 @@ Ndbcntr::execCNTR_START_REP(Signal* signal){ } if(cmasterNodeId != getOwnNodeId()){ + jam(); c_start.reset(); return; } if(c_start.m_waiting.isclear()){ + jam(); c_start.reset(); return; } @@ -597,6 +599,7 @@ Ndbcntr::execCNTR_START_REQ(Signal * signal){ ndbrequire(false); case NodeState::SL_STARTING: case NodeState::SL_STARTED: + jam(); break; case NodeState::SL_STOPPING_1: @@ -616,9 +619,11 @@ Ndbcntr::execCNTR_START_REQ(Signal * signal){ c_start.m_waiting.set(nodeId); switch(st){ case NodeState::ST_INITIAL_START: + jam(); c_start.m_withoutLog.set(nodeId); break; case NodeState::ST_SYSTEM_RESTART: + jam(); c_start.m_withLog.set(nodeId); if(starting && lastGci > c_start.m_lastGci){ jam(); @@ -631,6 +636,7 @@ Ndbcntr::execCNTR_START_REQ(Signal * signal){ return; } if(starting){ + jam(); Uint32 i = c_start.m_logNodesCount++; c_start.m_logNodes[i].m_nodeId = nodeId; c_start.m_logNodes[i].m_lastGci = req->lastGci; @@ -652,11 +658,12 @@ Ndbcntr::execCNTR_START_REQ(Signal * signal){ } if(starting){ + jam(); trySystemRestart(signal); } else { + jam(); startWaitingNodes(signal); } - return; } @@ -670,6 +677,7 @@ Ndbcntr::startWaitingNodes(Signal * signal){ NodeState::StartType nrType = NodeState::ST_NODE_RESTART; if(c_start.m_withoutLog.get(nodeId)){ + jam(); nrType = NodeState::ST_INITIAL_NODE_RESTART; } @@ -706,6 +714,7 @@ Ndbcntr::startWaitingNodes(Signal * signal){ char buf[100]; if(!c_start.m_withLog.isclear()){ + jam(); ndbout_c("Starting nodes w/ log: %s", c_start.m_withLog.getText(buf)); NodeReceiverGroup rg(NDBCNTR, c_start.m_withLog); @@ -716,6 +725,7 @@ Ndbcntr::startWaitingNodes(Signal * signal){ } if(!c_start.m_withoutLog.isclear()){ + jam(); ndbout_c("Starting nodes wo/ log: %s", c_start.m_withoutLog.getText(buf)); NodeReceiverGroup rg(NDBCNTR, c_start.m_withoutLog); conf->startType = NodeState::ST_INITIAL_NODE_RESTART; @@ -777,6 +787,7 @@ Ndbcntr::trySystemRestart(Signal* signal){ jam(); return false; } + jam(); srType = NodeState::ST_INITIAL_START; c_start.m_starting = c_start.m_withoutLog; // Used for starting... c_start.m_withoutLog.clear(); @@ -793,13 +804,11 @@ Ndbcntr::trySystemRestart(Signal* signal){ // If we lose with all nodes, then we're in trouble ndbrequire(!allNodes); return false; - break; case CheckNodeGroups::Partitioning: jam(); bool allowPartition = (c_start.m_startPartitionedTimeout != (Uint64)~0); if(allNodes){ - jam(); if(allowPartition){ jam(); break; @@ -1043,8 +1052,10 @@ void Ndbcntr::ph5ALab(Signal* signal) return; case NodeState::ST_NODE_RESTART: case NodeState::ST_INITIAL_NODE_RESTART: + jam(); break; case NodeState::ST_ILLEGAL_TYPE: + jam(); break; } ndbrequire(false); @@ -1602,6 +1613,7 @@ void Ndbcntr::startInsertTransactions(Signal* signal) ckey = 1; ctransidPhase = ZTRUE; + signal->theData[0] = 0; signal->theData[1] = reference(); sendSignal(DBTC_REF, GSN_TCSEIZEREQ, signal, 2, JBB); return; @@ -1661,7 +1673,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 @@ -1729,6 +1741,7 @@ void Ndbcntr::crSystab8Lab(Signal* signal) }//if signal->theData[0] = ctcConnectionP; signal->theData[1] = reference(); + signal->theData[2] = 0; sendSignal(DBTC_REF, GSN_TCRELEASEREQ, signal, 2, JBB); return; }//Ndbcntr::crSystab8Lab() @@ -2313,6 +2326,18 @@ void Ndbcntr::execWAIT_GCP_REF(Signal* signal){ void Ndbcntr::execWAIT_GCP_CONF(Signal* signal){ jamEntry(); + ndbrequire(StopReq::getSystemStop(c_stopRec.stopReq.requestInfo)); + NodeState newState(NodeState::SL_STOPPING_3, true); + + /** + * Inform QMGR so that arbitrator won't kill us + */ + NodeStateRep * rep = (NodeStateRep *)&signal->theData[0]; + rep->nodeState = newState; + rep->nodeState.masterNodeId = cmasterNodeId; + rep->nodeState.setNodeGroup(c_nodeGroup); + EXECUTE_DIRECT(QMGR, GSN_NODE_STATE_REP, signal, NodeStateRep::SignalLength); + if(StopReq::getPerformRestart(c_stopRec.stopReq.requestInfo)){ jam(); StartOrd * startOrd = (StartOrd *)&signal->theData[0]; diff --git a/ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp b/ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp index 7ba7d0d25c6..18e46d2d004 100644 --- a/ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp +++ b/ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp @@ -108,8 +108,8 @@ AsyncFile::AsyncFile() : } void -AsyncFile::doStart(const char * filesystemPath) { - theFileName.init(filesystemPath); +AsyncFile::doStart(Uint32 nodeId, const char * filesystemPath) { + theFileName.init(nodeId, filesystemPath); // Stacksize for filesystem threads // An 8k stack should be enough @@ -229,7 +229,7 @@ AsyncFile::run() endReq(); return; default: - THREAD_REQUIRE(false, "Using default switch in AsyncFile::run"); + abort(); break; }//switch theReportTo->writeChannel(request); diff --git a/ndb/src/kernel/blocks/ndbfs/AsyncFile.hpp b/ndb/src/kernel/blocks/ndbfs/AsyncFile.hpp index caa03e52d0c..9a405bc1580 100644 --- a/ndb/src/kernel/blocks/ndbfs/AsyncFile.hpp +++ b/ndb/src/kernel/blocks/ndbfs/AsyncFile.hpp @@ -181,7 +181,7 @@ public: void execute( Request* request ); - void doStart(const char * fspath); + void doStart(Uint32 nodeId, const char * fspath); // its a thread so its always running void run(); diff --git a/ndb/src/kernel/blocks/ndbfs/Filename.cpp b/ndb/src/kernel/blocks/ndbfs/Filename.cpp index 494c9c74eb9..660fe6eee94 100644 --- a/ndb/src/kernel/blocks/ndbfs/Filename.cpp +++ b/ndb/src/kernel/blocks/ndbfs/Filename.cpp @@ -46,7 +46,7 @@ Filename::Filename() : } void -Filename::init(const char * pFileSystemPath){ +Filename::init(Uint32 nodeid, const char * pFileSystemPath){ if (pFileSystemPath == NULL) { ERROR_SET(fatal, AFS_ERROR_NOPATH, ""," Filename::init()"); return; @@ -75,8 +75,15 @@ Filename::init(const char * pFileSystemPath){ DIR_SEPARATOR) != 0) strcat(theBaseDirectory, DIR_SEPARATOR); -} + snprintf(buf2, sizeof(buf2), "ndb_%u_fs%s", nodeid, DIR_SEPARATOR); + strcat(theBaseDirectory, buf2); +#ifdef NDB_WIN32 + CreateDirectory(theBaseDirectory, 0); +#else + mkdir(theBaseDirectory, S_IRUSR | S_IWUSR | S_IXUSR | S_IXGRP | S_IRGRP); +#endif +} Filename::~Filename(){ } diff --git a/ndb/src/kernel/blocks/ndbfs/Filename.hpp b/ndb/src/kernel/blocks/ndbfs/Filename.hpp index 29aba79c9dc..25c06092436 100644 --- a/ndb/src/kernel/blocks/ndbfs/Filename.hpp +++ b/ndb/src/kernel/blocks/ndbfs/Filename.hpp @@ -68,7 +68,7 @@ public: int levels() const; const char* c_str() const; - void init(const char * fileSystemPath); + void init(Uint32 nodeid, const char * fileSystemPath); private: int theLevelDepth; diff --git a/ndb/src/kernel/blocks/ndbfs/MemoryChannel.hpp b/ndb/src/kernel/blocks/ndbfs/MemoryChannel.hpp index 435a6a6b208..03911d195ec 100644 --- a/ndb/src/kernel/blocks/ndbfs/MemoryChannel.hpp +++ b/ndb/src/kernel/blocks/ndbfs/MemoryChannel.hpp @@ -120,8 +120,7 @@ template <class T> void MemoryChannel<T>::writeChannel( T *t) { NdbMutex_Lock(theMutexPtr); - REQUIRE(!full(theWriteIndex, theReadIndex), "Memory Channel Full"); - REQUIRE(theChannel != NULL, "Memory Channel Full"); + if(full(theWriteIndex, theReadIndex) || theChannel == NULL) abort(); theChannel[theWriteIndex]= t; ++theWriteIndex; NdbMutex_Unlock(theMutexPtr); diff --git a/ndb/src/kernel/blocks/ndbfs/Ndbfs.cpp b/ndb/src/kernel/blocks/ndbfs/Ndbfs.cpp index fe737fc584b..3b8cb20fe5c 100644 --- a/ndb/src/kernel/blocks/ndbfs/Ndbfs.cpp +++ b/ndb/src/kernel/blocks/ndbfs/Ndbfs.cpp @@ -559,7 +559,7 @@ Ndbfs::createAsyncFile(){ } AsyncFile* file = new AsyncFile; - file->doStart(theFileSystemPath); + file->doStart(getOwnNodeId(), theFileSystemPath); // Put the file in list of all files theFiles.push_back(file); @@ -1010,3 +1010,7 @@ Ndbfs::execDUMP_STATE_ORD(Signal* signal) BLOCK_FUNCTIONS(Ndbfs); +template class Vector<AsyncFile*>; +template class Vector<OpenFiles::OpenFileItem>; +template class MemoryChannel<Request>; +template class Pool<Request>; diff --git a/ndb/src/kernel/blocks/ndbfs/Pool.hpp b/ndb/src/kernel/blocks/ndbfs/Pool.hpp index a26fa730727..0410673af6f 100644 --- a/ndb/src/kernel/blocks/ndbfs/Pool.hpp +++ b/ndb/src/kernel/blocks/ndbfs/Pool.hpp @@ -215,7 +215,6 @@ protected: T** tList = theList; int i; theList = new T*[aSize+theCurrentSize]; - REQUIRE(theList != 0, "Allocate in Pool.hpp failed"); // allocate full list for (i = 0; i < theTop; i++) { theList[i] = tList[i]; diff --git a/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp b/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp index f2d2edb615d..6017365a463 100644 --- a/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp +++ b/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp @@ -258,7 +258,6 @@ void Qmgr::execCONNECT_REP(Signal* signal) { const Uint32 nodeId = signal->theData[0]; c_connectedNodes.set(nodeId); - NodeRecPtr nodePtr; nodePtr.i = getOwnNodeId(); ptrCheckGuard(nodePtr, MAX_NODES, nodeRec); @@ -679,7 +678,6 @@ void Qmgr::execCM_REGREF(Signal* signal) UintR TaddNodeno = signal->theData[1]; UintR TrefuseReason = signal->theData[2]; Uint32 candidate = signal->theData[3]; - DEBUG_START3(signal, TrefuseReason); if(candidate != cpresidentCandidate){ @@ -768,7 +766,6 @@ void Qmgr::execCM_REGREF(Signal* signal) Uint64 now = NdbTick_CurrentMillisecond(); if((c_regReqReqRecv == cnoOfNodes) || now > c_stopElectionTime){ jam(); - electionWon(); sendSttorryLab(signal); @@ -1704,6 +1701,7 @@ void Qmgr::sendApiFailReq(Signal* signal, Uint16 failedNodeNo) sendSignal(DBTC_REF, GSN_API_FAILREQ, signal, 2, JBA); sendSignal(DBDICT_REF, GSN_API_FAILREQ, signal, 2, JBA); sendSignal(SUMA_REF, GSN_API_FAILREQ, signal, 2, JBA); + /** * GREP also need the information that an API node * (actually a REP node) has failed. @@ -1978,8 +1976,10 @@ void Qmgr::execAPI_REGREQ(Signal* signal) apiRegConf->nodeState.dynamicId = -dynamicId; } } + apiRegConf->nodeState.m_connected_nodes.assign(c_connectedNodes); + sendSignal(ref, GSN_API_REGCONF, signal, ApiRegConf::SignalLength, JBB); - + if ((getNodeState().startLevel == NodeState::SL_STARTED || getNodeState().getSingleUserMode()) && apiNodePtr.p->phase == ZAPI_INACTIVE) { @@ -2138,7 +2138,8 @@ void Qmgr::execPREP_FAILREQ(Signal* signal) Uint16 TfailureNr = prepFail->failNo; cnoPrepFailedNodes = prepFail->noOfNodes; UintR arrayIndex = 0; - for (Uint32 Tindex = 0; Tindex < MAX_NDB_NODES; Tindex++) { + Uint32 Tindex; + for (Tindex = 0; Tindex < MAX_NDB_NODES; Tindex++) { if (NodeBitmask::get(prepFail->theNodes, Tindex)){ cprepFailedNodes[arrayIndex] = Tindex; arrayIndex++; @@ -2166,7 +2167,7 @@ void Qmgr::execPREP_FAILREQ(Signal* signal) guard0 = cnoPrepFailedNodes - 1; arrGuard(guard0, MAX_NDB_NODES); - for (Uint32 Tindex = 0; Tindex <= guard0; Tindex++) { + for (Tindex = 0; Tindex <= guard0; Tindex++) { jam(); failReport(signal, cprepFailedNodes[Tindex], @@ -2308,6 +2309,15 @@ void Qmgr::execPREP_FAILCONF(Signal* signal) * Continues via sendCommitFailReq() if successful. */ arbitRec.failureNr = cfailureNr; + const NodeState & s = getNodeState(); + if(s.startLevel == NodeState::SL_STOPPING_3 && s.stopping.systemShutdown){ + jam(); + /** + * We're performing a system shutdown, + * don't let artibtrator shut us down + */ + return; + } handleArbitCheck(signal); return; }//Qmgr::execPREP_FAILCONF() diff --git a/ndb/src/kernel/blocks/suma/Suma.cpp b/ndb/src/kernel/blocks/suma/Suma.cpp index 9718845de43..24e264291e7 100644 --- a/ndb/src/kernel/blocks/suma/Suma.cpp +++ b/ndb/src/kernel/blocks/suma/Suma.cpp @@ -267,6 +267,40 @@ Suma::execREAD_NODESCONF(Signal* signal){ sendSTTORRY(signal); } +#if 0 +void +Suma::execREAD_CONFIG_REQ(Signal* signal) +{ + const ReadConfigReq * req = (ReadConfigReq*)signal->getDataPtr(); + Uint32 ref = req->senderRef; + Uint32 senderData = req->senderData; + ndbrequire(req->noOfParameters == 0); + + jamEntry(); + + const ndb_mgm_configuration_iterator * p = + theConfiguration.getOwnConfigIterator(); + ndbrequire(p != 0); + + ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_DB_NO_REDOLOG_FILES, + &cnoLogFiles)); + ndbrequire(cnoLogFiles > 0); + + ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_LQH_FRAG, &cfragrecFileSize)); + ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_LQH_TABLE, &ctabrecFileSize)); + ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_LQH_TC_CONNECT, + &ctcConnectrecFileSize)); + clogFileFileSize = 4 * cnoLogFiles; + ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_LQH_SCAN, &cscanrecFileSize)); + cmaxAccOps = cscanrecFileSize * MAX_PARALLEL_SCANS_PER_FRAG; + + initRecords(); + initialiseRecordsLab(signal, 0, ref, senderData); + + return; +}//Dblqh::execSIZEALT_REP() +#endif + void Suma::sendSTTORRY(Signal* signal){ signal->theData[0] = 0; @@ -581,34 +615,33 @@ Suma::execDUMP_STATE_ORD(Signal* signal){ jamEntry(); Uint32 tCase = signal->theData[0]; - if(tCase < 8000 || tCase > 8004) - return; - - SubscriptionPtr subPtr; - c_subscriptions.getPtr(subPtr, g_subPtrI); - - Ptr<SyncRecord> syncPtr; - c_syncPool.getPtr(syncPtr, subPtr.p->m_syncPtrI); - - if(tCase == 8000){ - syncPtr.p->startMeta(signal); - } - - if(tCase == 8001){ - syncPtr.p->startScan(signal); - } - - if(tCase == 8002){ - syncPtr.p->startTrigger(signal); - } + if(tCase >= 8000 && tCase <= 8003){ + SubscriptionPtr subPtr; + c_subscriptions.getPtr(subPtr, g_subPtrI); + + Ptr<SyncRecord> syncPtr; + c_syncPool.getPtr(syncPtr, subPtr.p->m_syncPtrI); + + if(tCase == 8000){ + syncPtr.p->startMeta(signal); + } + + if(tCase == 8001){ + syncPtr.p->startScan(signal); + } - if(tCase == 8003){ - subPtr.p->m_subscriptionType = SubCreateReq::SingleTableScan; - LocalDataBuffer<15> attrs(c_dataBufferPool, syncPtr.p->m_attributeList); - Uint32 tab = 0; - Uint32 att[] = { 0, 1, 1 }; - syncPtr.p->m_tableList.append(&tab, 1); - attrs.append(att, 3); + if(tCase == 8002){ + syncPtr.p->startTrigger(signal); + } + + if(tCase == 8003){ + subPtr.p->m_subscriptionType = SubCreateReq::SingleTableScan; + LocalDataBuffer<15> attrs(c_dataBufferPool, syncPtr.p->m_attributeList); + Uint32 tab = 0; + Uint32 att[] = { 0, 1, 1 }; + syncPtr.p->m_tableList.append(&tab, 1); + attrs.append(att, 3); + } } if(tCase == 8004){ @@ -1229,6 +1262,9 @@ SumaParticipant::parseTable(Signal* signal, GetTabInfoConf* conf, Uint32 tableId if(!tabPtr.isNull() && tabPtr.p->m_schemaVersion != tableDesc.TableVersion){ jam(); + + tabPtr.p->release(* this); + // oops wrong schema version in stored tabledesc // we need to find all subscriptions with old table desc // and all subscribers to this @@ -3972,3 +4008,6 @@ Suma::execSUMA_HANDOVER_CONF(Signal* signal) { } } } + +template void append(DataBuffer<11>&,SegmentedSectionPtr,SectionSegmentPool&); + diff --git a/ndb/src/kernel/blocks/trix/Trix.cpp b/ndb/src/kernel/blocks/trix/Trix.cpp index f058433840c..4088d55c76d 100644 --- a/ndb/src/kernel/blocks/trix/Trix.cpp +++ b/ndb/src/kernel/blocks/trix/Trix.cpp @@ -814,8 +814,8 @@ void Trix::executeInsertTransaction(Signal* signal, for(Uint32 i = 0; i < headerPtr.sz; i++) { AttributeHeader* keyAttrHead = (AttributeHeader *) headerBuffer + i; - // Filter out single NULL attributes - if (keyAttrHead->isNULL() && (i == (Uint32)0) && (headerPtr.sz == (Uint32)2)) + // Filter out NULL attributes + if (keyAttrHead->isNULL()) return; if (i < subRec->noOfIndexColumns) @@ -965,3 +965,5 @@ void Trix::checkParallelism(Signal* signal, SubscriptionRecord* subRec) } BLOCK_FUNCTIONS(Trix); + +template void append(DataBuffer<15>&,SegmentedSectionPtr,SectionSegmentPool&); diff --git a/ndb/src/kernel/error/ErrorReporter.cpp b/ndb/src/kernel/error/ErrorReporter.cpp index 20a9dd8a993..f1320c44e09 100644 --- a/ndb/src/kernel/error/ErrorReporter.cpp +++ b/ndb/src/kernel/error/ErrorReporter.cpp @@ -27,6 +27,8 @@ #include <NdbConfig.h> #include <Configuration.hpp> +#include <NdbAutoPtr.hpp> + #define MESSAGE_LENGTH 400 const char* errorType[] = { @@ -66,23 +68,23 @@ ErrorReporter::formatTimeStampString(){ return (const char *)&theDateTimeString; } -void -ErrorReporter::formatTraceFileName(char* theName, int maxLen){ +int +ErrorReporter::get_trace_no(){ FILE *stream; unsigned int traceFileNo; - char fileNameBuf[255]; - char buf[255]; + + char *file_name= NdbConfig_NextTraceFileName(globalData.ownId); + NdbAutoPtr<char> tmp_aptr(file_name); - NdbConfig_HomePath(fileNameBuf, 255); - strncat(fileNameBuf, "NextTraceFileNo.log", 255); /* * Read last number from tracefile */ - stream = fopen(fileNameBuf, "r+"); + stream = fopen(file_name, "r+"); if (stream == NULL){ traceFileNo = 1; } else { + char buf[255]; fgets(buf, 255, stream); const int scan = sscanf(buf, "%u", &traceFileNo); if(scan != 1){ @@ -103,16 +105,13 @@ ErrorReporter::formatTraceFileName(char* theName, int maxLen){ /** * Save new number to the file */ - stream = fopen(fileNameBuf, "w"); + stream = fopen(file_name, "w"); if(stream != NULL){ fprintf(stream, "%u", traceFileNo); fclose(stream); } - /** - * Format trace file name - */ - snprintf(theName, maxLen, "%sNDB_TraceFile_%u.trace", - NdbConfig_HomePath(fileNameBuf, 255), traceFileNo); + + return traceFileNo; } @@ -214,16 +213,22 @@ WriteMessage(ErrorCategory thrdType, int thrdMessageID, unsigned offset; unsigned long maxOffset; // Maximum size of file. char theMessage[MESSAGE_LENGTH]; - char theTraceFileName[255]; - char theErrorFileName[255]; - ErrorReporter::formatTraceFileName(theTraceFileName, 255); + + /** + * Format trace file name + */ + int file_no= ErrorReporter::get_trace_no(); + char *theTraceFileName= NdbConfig_TraceFileName(globalData.ownId, file_no); + NdbAutoPtr<char> tmp_aptr1(theTraceFileName); // The first 69 bytes is info about the current offset Uint32 noMsg = globalEmulatorData.theConfiguration->maxNoOfErrorLogs(); maxOffset = (69 + (noMsg * MESSAGE_LENGTH)); - NdbConfig_ErrorFileName(theErrorFileName, 255); + char *theErrorFileName= (char *)NdbConfig_ErrorFileName(globalData.ownId); + NdbAutoPtr<char> tmp_aptr2(theErrorFileName); + stream = fopen(theErrorFileName, "r+"); if (stream == NULL) { /* If the file could not be opened. */ diff --git a/ndb/src/kernel/error/ErrorReporter.hpp b/ndb/src/kernel/error/ErrorReporter.hpp index b43b30f1873..2c79f242eea 100644 --- a/ndb/src/kernel/error/ErrorReporter.hpp +++ b/ndb/src/kernel/error/ErrorReporter.hpp @@ -23,35 +23,6 @@ #include "Error.hpp" #include <Emulator.hpp> - -#ifdef ASSERT -#undef ASSERT -#endif - -#define REQUIRE(trueToContinue, message) \ - if ( (trueToContinue) ) { } else { \ - ErrorReporter::handleAssert(message, __FILE__, __LINE__); } - -#define THREAD_REQUIRE(trueToContinue, message) \ - if ( (trueToContinue) ) { } else { \ - ErrorReporter::handleThreadAssert(message, __FILE__, __LINE__); } - -#ifdef NDEBUG -#define NDB_ASSERT(trueToContinue, message) -#else -#define NDB_ASSERT(trueToContinue, message) \ - if ( !(trueToContinue) ) { \ - ErrorReporter::handleAssert(message, __FILE__, __LINE__); } -#endif - - // Description: - // This macro is used to report programming errors. - // Parameters: - // trueToContinue IN An expression. If it evaluates to 0 - // execution is stopped. - // message IN A message from the programmer - // explaining what went wrong. - class ErrorReporter { public: @@ -81,7 +52,7 @@ public: const char* theNameOfTheTraceFile, char* messptr); - static void formatTraceFileName(char* theName, int maxLen); + static int get_trace_no(); static const char* formatTimeStampString(); diff --git a/ndb/src/kernel/Main.cpp b/ndb/src/kernel/main.cpp index 7bd4e75ca18..4d3a0afe6ed 100644 --- a/ndb/src/kernel/Main.cpp +++ b/ndb/src/kernel/main.cpp @@ -20,7 +20,7 @@ #include "Configuration.hpp" #include <TransporterRegistry.hpp> -#include "SimBlockList.hpp" +#include "vm/SimBlockList.hpp" #include "ThreadConfig.hpp" #include <SignalLoggerManager.hpp> #include <NdbOut.hpp> @@ -31,20 +31,19 @@ #include <LogLevel.hpp> #include <EventLogger.hpp> -#include <NodeState.hpp> + +#include <NdbAutoPtr.hpp> #if defined NDB_SOLARIS // ok #include <sys/processor.h> // For system informatio #endif -#if !defined NDB_SOFTOSE && !defined NDB_OSE -#include <signal.h> // For process signals -#endif - extern EventLogger g_eventLogger; void catchsigs(bool ignore); // for process signal handling -extern "C" void handler(int signo); // for process signal handling + +extern "C" void handler_shutdown(int signum); // for process signal handling +extern "C" void handler_error(int signum); // for process signal handling // Shows system information void systemInfo(const Configuration & conf, @@ -68,18 +67,16 @@ NDB_MAIN(ndb_kernel){ } { // Do configuration - theConfig->setupConfiguration(); + signal(SIGPIPE, SIG_IGN); + theConfig->fetch_configuration(); } - - // Get NDB_HOME path - char homePath[255]; - NdbConfig_HomePath(homePath, 255); - + if (theConfig->getDaemonMode()) { // Become a daemon - char lockfile[255], logfile[255]; - snprintf(lockfile, 255, "%snode%d.pid", homePath, globalData.ownId); - snprintf(logfile, 255, "%snode%d.out", homePath, globalData.ownId); + char *lockfile= NdbConfig_PidFileName(globalData.ownId); + char *logfile= NdbConfig_StdoutFileName(globalData.ownId); + NdbAutoPtr<char> tmp_aptr1(lockfile), tmp_aptr2(logfile); + if (NdbDaemon_Make(lockfile, logfile, 0) == -1) { ndbout << "Cannot become daemon: " << NdbDaemon_ErrorText << endl; return 1; @@ -132,24 +129,26 @@ NDB_MAIN(ndb_kernel){ exit(0); } g_eventLogger.info("Ndb has terminated (pid %d) restarting", child); + theConfig->fetch_configuration(); } g_eventLogger.info("Angel pid: %d ndb pid: %d", getppid(), getpid()); + theConfig->setupConfiguration(); systemInfo(* theConfig, * theConfig->m_logLevel); - + // Load blocks globalEmulatorData.theSimBlockList->load(* theConfig); // Set thread concurrency for Solaris' light weight processes int status; status = NdbThread_SetConcurrencyLevel(30); - NDB_ASSERT(status == 0, "Can't set appropriate concurrency level."); + assert(status == 0); #ifdef VM_TRACE // Create a signal logger - char buf[255]; - strcpy(buf, homePath); - FILE * signalLog = fopen(strncat(buf,"Signal.log", 255), "a"); + char *buf= NdbConfig_SignalLogFileName(globalData.ownId); + NdbAutoPtr<char> tmp_aptr(buf); + FILE * signalLog = fopen(buf, "a"); globalSignalLoggers.setOwnNodeId(globalData.ownId); globalSignalLoggers.setOutputStream(signalLog); #endif @@ -168,16 +167,38 @@ NDB_MAIN(ndb_kernel){ globalEmulatorData.theThreadConfig->doStart(NodeState::SL_STARTING); break; default: - NDB_ASSERT(0, "Illegal state globalData.theRestartFlag"); + assert("Illegal state globalData.theRestartFlag" == 0); } + SocketServer socket_server; + globalTransporterRegistry.startSending(); globalTransporterRegistry.startReceiving(); + if (!globalTransporterRegistry.start_service(socket_server)){ + ndbout_c("globalTransporterRegistry.start_service() failed"); + exit(-1); + } + + if (!globalTransporterRegistry.start_clients()){ + ndbout_c("globalTransporterRegistry.start_clients() failed"); + exit(-1); + } + globalEmulatorData.theWatchDog->doStart(); + socket_server.startServer(); + + // theConfig->closeConfiguration(); + globalEmulatorData.theThreadConfig->ipControlLoop(); NdbShutdown(NST_Normal); + + socket_server.stopServer(); + socket_server.stopSessions(); + + globalTransporterRegistry.stop_clients(); + return NRT_Default; } @@ -229,74 +250,91 @@ systemInfo(const Configuration & config, const LogLevel & logLevel){ } +#define handler_register(signum, handler, ignore)\ +{\ + if (ignore) {\ + if(signum != SIGCHLD)\ + signal(signum, SIG_IGN);\ + } else\ + signal(signum, handler);\ +} + void catchsigs(bool ignore){ #if ! defined NDB_SOFTOSE && !defined NDB_OSE -#if defined SIGRTMIN - #define MAX_SIG_CATCH SIGRTMIN -#elif defined NSIG - #define MAX_SIG_CATCH NSIG -#else - #error "neither SIGRTMIN or NSIG is defined on this platform, please report bug at bugs.mysql.com" + static const int signals_shutdown[] = { +#ifdef SIGBREAK + SIGBREAK, #endif - - // Makes the main process catch process signals, eg installs a - // handler named "handler". "handler" will then be called is instead - // of the defualt process signal handler) - if(ignore){ - for(int i = 1; i < MAX_SIG_CATCH; i++){ - if(i != SIGCHLD) - signal(i, SIG_IGN); - } - } else { - for(int i = 1; i < MAX_SIG_CATCH; i++){ - signal(i, handler); - } - } + SIGHUP, + SIGINT, +#if defined SIGPWR + SIGPWR, +#elif defined SIGINFO + SIGINFO, #endif -} - -extern "C" -void -handler(int sig){ - switch(sig){ - case SIGHUP: /* 1 - Hang up */ - case SIGINT: /* 2 - Interrupt */ - case SIGQUIT: /* 3 - Quit */ - case SIGTERM: /* 15 - Terminate */ -#ifdef SIGPWR - case SIGPWR: /* 19 - Power fail */ + SIGQUIT, + SIGTERM, +#ifdef SIGTSTP + SIGTSTP, +#endif + SIGTTIN, + SIGTTOU + }; + + static const int signals_error[] = { + SIGABRT, + SIGALRM, +#ifdef SIGBUS + SIGBUS, +#endif + SIGCHLD, + SIGFPE, + SIGILL, +#ifdef SIGIO + SIGIO, #endif #ifdef SIGPOLL - case SIGPOLL: /* 22 */ + SIGPOLL, #endif - case SIGSTOP: /* 23 */ - case SIGTSTP: /* 24 */ - case SIGTTIN: /* 26 */ - case SIGTTOU: /* 27 */ - globalData.theRestartFlag = perform_stop; - break; -#ifdef SIGWINCH - case SIGWINCH: + SIGSEGV, +#ifdef SIGTRAP + SIGTRAP #endif - case SIGPIPE: - /** - * Can happen in TCP Transporter - * - * Just ignore - */ - break; - default: - // restart the system - char errorData[40]; - snprintf(errorData, 40, "Signal %d received", sig); - ERROR_SET(fatal, 0, errorData, __FILE__); - break; - } + }; +#endif + + static const int signals_ignore[] = { + SIGPIPE + }; + + size_t i; + for(i = 0; i < sizeof(signals_shutdown)/sizeof(signals_shutdown[0]); i++) + handler_register(signals_shutdown[i], handler_shutdown, ignore); + for(i = 0; i < sizeof(signals_error)/sizeof(signals_error[0]); i++) + handler_register(signals_error[i], handler_error, ignore); + for(i = 0; i < sizeof(signals_ignore)/sizeof(signals_ignore[0]); i++) + handler_register(signals_ignore[i], SIG_IGN, ignore); +} + +extern "C" +void +handler_shutdown(int signum){ + g_eventLogger.info("Received signal %d. Performing stop.", signum); + globalData.theRestartFlag = perform_stop; +} + +extern "C" +void +handler_error(int signum){ + g_eventLogger.info("Received signal %d. Running error handler.", signum); + // restart the system + char errorData[40]; + snprintf(errorData, 40, "Signal %d received", signum); + ERROR_SET(fatal, 0, errorData, __FILE__); } - diff --git a/ndb/src/kernel/vm/ArrayPool.hpp b/ndb/src/kernel/vm/ArrayPool.hpp index 4fc6bb97f73..924ed51ee15 100644 --- a/ndb/src/kernel/vm/ArrayPool.hpp +++ b/ndb/src/kernel/vm/ArrayPool.hpp @@ -148,24 +148,6 @@ public: void releaseList(Uint32 n, Uint32 first, Uint32 last); //private: - /** - * Print - * (Run operator NdbOut<< on every element) - */ - void print(NdbOut & out){ - out << "FirstFree = " << firstFree << endl; - for(Uint32 i = 0; i<size; i++){ -#ifdef ARRAY_GUARD - if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i)) - out << "A "; - else - out << "F "; -#endif - out << i << ": " << theArray[i] << " "; - } - out << endl; - } - #ifdef DEBUG Uint32 getNoOfFree2() const { Uint32 c2 = size; diff --git a/ndb/src/kernel/vm/Configuration.cpp b/ndb/src/kernel/vm/Configuration.cpp index c97ad951cf3..257b7a098e0 100644 --- a/ndb/src/kernel/vm/Configuration.cpp +++ b/ndb/src/kernel/vm/Configuration.cpp @@ -35,6 +35,7 @@ #include <ndb_limits.h> #include "pc.hpp" #include <LogLevel.hpp> +#include <NdbSleep.h> extern "C" { void ndbSetOwnVersion(); @@ -49,7 +50,7 @@ Configuration::init(int argc, const char** argv){ /** * Default values for arguments */ - int _start = 1; + int _no_start = 0; int _initial = 0; const char* _connect_str = NULL; int _deamon = 0; @@ -59,14 +60,18 @@ Configuration::init(int argc, const char** argv){ /** * Arguments to NDB process */ - struct getargs args[] = { - { "version", 'v', arg_flag, &_print_version, "Print version", "" }, - { "start", 's', arg_flag, &_start, "Start ndb immediately", "" }, - { "nostart", 'n', arg_negative_flag, &_start, "Don't start ndb immediately", "" }, - { "deamon", 'd', arg_flag, &_deamon, "Start ndb as deamon", "" }, - { "initial", 'i', arg_flag, &_initial, "Start ndb immediately", "" }, - { "connect-string", 'c', arg_string, &_connect_str, "\"nodeid=<id>;host=<hostname:port>\"\n", "constr" }, + struct getargs args[] = { + { "version", 'v', arg_flag, &_print_version, "Print ndbd version", "" }, + { "nostart", 'n', arg_flag, &_no_start, + "Don't start ndbd immediately. Ndbd will await command from ndb_mgmd", "" }, + { "daemon", 'd', arg_flag, &_deamon, "Start ndbd as daemon", "" }, + { "initial", 'i', arg_flag, &_initial, + "Perform initial start of ndbd, including cleaning the file system. Consult documentation before using this", "" }, + + { "connect-string", 'c', arg_string, &_connect_str, + "Set connect string for connecting to ndb_mgmd. <constr>=\"host=<hostname:port>[;nodeid=<id>]\". Overides specifying entries in NDB_CONNECTSTRING and config file", + "<constr>" }, { "usage", '?', arg_flag, &_help, "Print help", "" } }; int num_args = sizeof(args) / sizeof(args[0]); @@ -80,7 +85,7 @@ Configuration::init(int argc, const char** argv){ } #if 0 - ndbout << "start=" <<_start<< endl; + ndbout << "no_start=" <<_no_start<< endl; ndbout << "initial=" <<_initial<< endl; ndbout << "deamon=" <<_deamon<< endl; ndbout << "connect_str="<<_connect_str<<endl; @@ -96,27 +101,18 @@ Configuration::init(int argc, const char** argv){ } // Check the start flag - if (_start) - globalData.theRestartFlag = perform_start; - else + if (_no_start) globalData.theRestartFlag = initial_state; + else + globalData.theRestartFlag = perform_start; // Check the initial flag if (_initial) _initialStart = true; // Check connectstring - if (_connect_str){ - - if(_connect_str[0] == '-' || - strstr(_connect_str, "host") == 0 || - strstr(_connect_str, "nodeid") == 0) { - ndbout << "Illegal/empty connectString: " << _connect_str << endl; - arg_printusage(args, num_args, argv[0], desc); - return false; - } + if (_connect_str) _connectString = strdup(_connect_str); - } // Check deamon flag if (_deamon) @@ -138,6 +134,7 @@ Configuration::Configuration() _fsPath = 0; _initialStart = false; _daemonMode = false; + m_config_retriever= 0; } Configuration::~Configuration(){ @@ -146,37 +143,97 @@ Configuration::~Configuration(){ if(_fsPath != NULL) free(_fsPath); + + if (m_config_retriever) { + delete m_config_retriever; + } } void -Configuration::setupConfiguration(){ +Configuration::closeConfiguration(){ + if (m_config_retriever) { + delete m_config_retriever; + } + m_config_retriever= 0; +} + +void +Configuration::fetch_configuration(){ /** * Fetch configuration from management server */ - ConfigRetriever cr; - cr.setConnectString(_connectString); - stopOnError(true); - ndb_mgm_configuration * p = cr.getConfig(NDB_VERSION, NODE_TYPE_DB); + if (m_config_retriever) { + delete m_config_retriever; + } + + m_config_retriever= new ConfigRetriever(NDB_VERSION, NODE_TYPE_DB); + m_config_retriever->setConnectString(_connectString ? _connectString : ""); + if(m_config_retriever->init() == -1 || + m_config_retriever->do_connect() == -1){ + + const char * s = m_config_retriever->getErrorString(); + if(s == 0) + s = "No error given!"; + + /* Set stop on error to true otherwise NDB will + go into an restart loop... + */ + ERROR_SET(fatal, ERR_INVALID_CONFIG, "Could connect to ndb_mgmd", s); + } + + ConfigRetriever &cr= *m_config_retriever; + + if((globalData.ownId = cr.allocNodeId()) == 0){ + for(Uint32 i = 0; i<3; i++){ + NdbSleep_SecSleep(3); + if(globalData.ownId = cr.allocNodeId()) + break; + } + } + + if(globalData.ownId == 0){ + ERROR_SET(fatal, ERR_INVALID_CONFIG, + "Unable to alloc node id", m_config_retriever->getErrorString()); + } + + ndb_mgm_configuration * p = cr.getConfig(); if(p == 0){ const char * s = cr.getErrorString(); if(s == 0) s = "No error given!"; - + /* Set stop on error to true otherwise NDB will go into an restart loop... - */ - + */ + ERROR_SET(fatal, ERR_INVALID_CONFIG, "Could not fetch configuration" "/invalid configuration", s); } + if(m_clusterConfig) + free(m_clusterConfig); + + m_clusterConfig = p; + + ndb_mgm_configuration_iterator iter(* p, CFG_SECTION_NODE); + if (iter.find(CFG_NODE_ID, globalData.ownId)){ + ERROR_SET(fatal, ERR_INVALID_CONFIG, "Invalid configuration fetched", "DB missing"); + } + + if(iter.get(CFG_DB_STOP_ON_ERROR, &_stopOnError)){ + ERROR_SET(fatal, ERR_INVALID_CONFIG, "Invalid configuration fetched", + "StopOnError missing"); + } +} - Uint32 nodeId = globalData.ownId = cr.getOwnNodeId(); +void +Configuration::setupConfiguration(){ + ndb_mgm_configuration * p = m_clusterConfig; /** * Configure transporters */ { - int res = IPCConfig::configureTransporters(nodeId, + int res = IPCConfig::configureTransporters(globalData.ownId, * p, globalTransporterRegistry); if(res <= 0){ @@ -238,11 +295,6 @@ Configuration::setupConfiguration(){ } } - if(iter.get(CFG_DB_STOP_ON_ERROR, &_stopOnError)){ - ERROR_SET(fatal, ERR_INVALID_CONFIG, "Invalid configuration fetched", - "StopOnError missing"); - } - if(iter.get(CFG_DB_STOP_ON_ERROR_INSERT, &m_restartOnErrorInsert)){ ERROR_SET(fatal, ERR_INVALID_CONFIG, "Invalid configuration fetched", "RestartOnErrorInsert missing"); @@ -259,7 +311,6 @@ Configuration::setupConfiguration(){ ConfigValues* cf = ConfigValuesFactory::extractCurrentSection(iter.m_config); - m_clusterConfig = p; m_clusterConfigIter = ndb_mgm_create_configuration_iterator (p, CFG_SECTION_NODE); @@ -501,7 +552,7 @@ Configuration::calcSizeAlt(ConfigValues * ownConfig){ // The remainder are allowed for use by the scan processes. /*-----------------------------------------------------------------------*/ cfg.put(CFG_ACC_OP_RECS, - noOfReplicas*((16 * noOfOperations) / 10 + 50) + + ((11 * noOfOperations) / 10 + 50) + (noOfLocalScanRecords * MAX_PARALLEL_SCANS_PER_FRAG) + NODE_RECOVERY_SCAN_OP_RECORDS); @@ -526,18 +577,9 @@ Configuration::calcSizeAlt(ConfigValues * ownConfig){ */ cfg.put(CFG_DICT_ATTRIBUTE, noOfAttributes); - - cfg.put(CFG_DICT_CONNECT, - noOfOperations + 32); - - cfg.put(CFG_DICT_FRAG_CONNECT, - NO_OF_FRAG_PER_NODE * noOfDBNodes * noOfReplicas); cfg.put(CFG_DICT_TABLE, noOfTables); - - cfg.put(CFG_DICT_TC_CONNECT, - 2* noOfOperations); } { @@ -548,7 +590,7 @@ Configuration::calcSizeAlt(ConfigValues * ownConfig){ 2 * noOfTransactions); cfg.put(CFG_DIH_CONNECT, - noOfOperations + 46); + noOfOperations + noOfTransactions + 46); cfg.put(CFG_DIH_FRAG_CONNECT, NO_OF_FRAG_PER_NODE * noOfTables * noOfDBNodes); @@ -578,18 +620,12 @@ Configuration::calcSizeAlt(ConfigValues * ownConfig){ cfg.put(CFG_LQH_FRAG, NO_OF_FRAG_PER_NODE * noOfTables * noOfReplicas); - cfg.put(CFG_LQH_CONNECT, - noOfReplicas*((11 * noOfOperations) / 10 + 50)); - cfg.put(CFG_LQH_TABLE, noOfTables); cfg.put(CFG_LQH_TC_CONNECT, - noOfReplicas*((16 * noOfOperations) / 10 + 50)); + (11 * noOfOperations) / 10 + 50); - cfg.put(CFG_LQH_REPLICAS, - noOfReplicas); - cfg.put(CFG_LQH_SCAN, noOfLocalScanRecords); } @@ -602,7 +638,7 @@ Configuration::calcSizeAlt(ConfigValues * ownConfig){ 3 * noOfTransactions); cfg.put(CFG_TC_TC_CONNECT, - noOfOperations + 16 + noOfTransactions); + (2 * noOfOperations) + 16 + noOfTransactions); cfg.put(CFG_TC_TABLE, noOfTables); @@ -622,7 +658,7 @@ Configuration::calcSizeAlt(ConfigValues * ownConfig){ 2 * NO_OF_FRAG_PER_NODE * noOfTables* noOfReplicas); cfg.put(CFG_TUP_OP_RECS, - noOfReplicas*((16 * noOfOperations) / 10 + 50)); + (11 * noOfOperations) / 10 + 50); cfg.put(CFG_TUP_PAGE, noOfDataPages); diff --git a/ndb/src/kernel/vm/Configuration.hpp b/ndb/src/kernel/vm/Configuration.hpp index 1706ad05867..bd91f3fa74b 100644 --- a/ndb/src/kernel/vm/Configuration.hpp +++ b/ndb/src/kernel/vm/Configuration.hpp @@ -20,6 +20,8 @@ #include <mgmapi.h> #include <ndb_types.h> +class ConfigRetriever; + class Configuration { public: Configuration(); @@ -30,7 +32,9 @@ public: */ bool init(int argc, const char** argv); + void fetch_configuration(); void setupConfiguration(); + void closeConfiguration(); bool lockPagesInMainMemory() const; @@ -78,6 +82,8 @@ private: ndb_mgm_configuration_iterator * m_clusterConfigIter; ndb_mgm_configuration_iterator * m_ownConfigIterator; + ConfigRetriever *m_config_retriever; + /** * arguments to NDB process */ diff --git a/ndb/src/kernel/vm/DataBuffer.hpp b/ndb/src/kernel/vm/DataBuffer.hpp index 7dc89aa638c..7f553898eb5 100644 --- a/ndb/src/kernel/vm/DataBuffer.hpp +++ b/ndb/src/kernel/vm/DataBuffer.hpp @@ -33,7 +33,7 @@ public: Uint32 data[sz]; NdbOut& print(NdbOut& out){ out << "[DataBuffer<" << sz << ">::Segment this=" - << hex << (Uint32)this << dec << " nextPool= " + << this << dec << " nextPool= " << nextPool << " ]"; return out; } diff --git a/ndb/src/kernel/vm/Emulator.cpp b/ndb/src/kernel/vm/Emulator.cpp index 07998794d01..75aea2bda7f 100644 --- a/ndb/src/kernel/vm/Emulator.cpp +++ b/ndb/src/kernel/vm/Emulator.cpp @@ -35,8 +35,6 @@ #include <NdbSleep.h> #include <new> -#include <signal.h> // For process signals - extern "C" { extern void (* ndb_new_handler)(); } @@ -202,7 +200,7 @@ NdbShutdown(NdbShutdownType type, if(type != NST_Normal && type != NST_Restart){ ndbout << "Error handler shutdown completed - " << exitAbort << endl; -#if defined VM_TRACE && ( ! ( defined NDB_OSE || defined NDB_SOFTOSE) ) +#if ( defined VM_TRACE || defined ERROR_INSERT ) && ( ! ( defined NDB_OSE || defined NDB_SOFTOSE) ) signal(6, SIG_DFL); abort(); #else diff --git a/ndb/src/kernel/vm/MetaData.cpp b/ndb/src/kernel/vm/MetaData.cpp index bcde6c63272..51afbf21503 100644 --- a/ndb/src/kernel/vm/MetaData.cpp +++ b/ndb/src/kernel/vm/MetaData.cpp @@ -47,7 +47,7 @@ MetaData::MetaData(SimulatedBlock* block) : MetaData::~MetaData() { for (int i = false; i <= true; i++) { - NDB_ASSERT(m_common.m_lock[i] >= m_lock[i], "invalid lock count"); + assert(m_common.m_lock[i] >= m_lock[i]); m_common.m_lock[i] -= m_lock[i]; m_lock[i] = 0; } diff --git a/ndb/src/kernel/vm/SimulatedBlock.cpp b/ndb/src/kernel/vm/SimulatedBlock.cpp index a6a8a6242cd..18b7f474ddc 100644 --- a/ndb/src/kernel/vm/SimulatedBlock.cpp +++ b/ndb/src/kernel/vm/SimulatedBlock.cpp @@ -104,6 +104,11 @@ SimulatedBlock::SimulatedBlock(BlockNumber blockNumber, UpgradeStartup::installEXEC(this); CLEAR_ERROR_INSERT_VALUE; + +#ifdef VM_TRACE + m_global_variables = new Ptr<void> * [1]; + m_global_variables[0] = 0; +#endif } SimulatedBlock::~SimulatedBlock() @@ -112,6 +117,10 @@ SimulatedBlock::~SimulatedBlock() #ifdef VM_TRACE_TIME printTimes(stdout); #endif + +#ifdef VM_TRACE + delete [] m_global_variables; +#endif } void @@ -136,12 +145,12 @@ SimulatedBlock::installSimulatedBlockFunctions(){ void SimulatedBlock::addRecSignalImpl(GlobalSignalNumber gsn, ExecFunction f, bool force){ - REQUIRE(gsn <= MAX_GSN, "Illegal signal added in block (GSN too high)"); - char probData[255]; - snprintf(probData, 255, - "Signal (%d) already added in block", - gsn); - REQUIRE(force || theExecArray[gsn] == 0, probData); + if(gsn > MAX_GSN || (!force && theExecArray[gsn] != 0)){ + char errorMsg[255]; + snprintf(errorMsg, 255, + "Illeagal signal (%d %d)", gsn, MAX_GSN); + ERROR_SET(fatal, ERR_ERROR_PRGERR, errorMsg, errorMsg); + } theExecArray[gsn] = f; } @@ -636,12 +645,12 @@ SimulatedBlock::getBatSize(Uint16 blockNo){ } void* -SimulatedBlock::allocRecord(const char * type, size_t s, size_t n) const +SimulatedBlock::allocRecord(const char * type, size_t s, size_t n, bool clear) { - void* p = NULL; + void * p = NULL; size_t size = n*s; - + refresh_watch_dog(); if (size > 0){ #ifdef VM_TRACE_MEM ndbout_c("%s::allocRecord(%s, %u, %u) = %u bytes", @@ -656,43 +665,31 @@ SimulatedBlock::allocRecord(const char * type, size_t s, size_t n) const char buf1[255]; char buf2[255]; snprintf(buf1, sizeof(buf1), "%s could not allocate memory for %s", - getBlockName(number()), type); - snprintf(buf2, sizeof(buf2), "Requested: %ux%u = %u bytes", (Uint32)s, (Uint32)n, (Uint32)size); + getBlockName(number()), type); + snprintf(buf2, sizeof(buf2), "Requested: %ux%u = %u bytes", + (Uint32)s, (Uint32)n, (Uint32)size); ERROR_SET(fatal, ERR_MEMALLOC, buf1, buf2); } - - - // Set the allocated memory to zero -#ifndef NDB_PURIFY -#if defined NDB_OSE - int pages = (size / 4096); - if ((size % 4096)!=0) - pages++; - - char* p2 =(char*) p; - for (int i = 0; i < pages; i++){ - memset(p2, 0, 4096); - p2 = p2 + 4096; + + if(clear){ + char * ptr = (char*)p; + const Uint32 chunk = 128 * 1024; + while(size > chunk){ + refresh_watch_dog(); + memset(ptr, 0, chunk); + ptr += chunk; + size -= chunk; + } + refresh_watch_dog(); + memset(ptr, 0, size); } -#elif 1 - /** - * This code should be enabled in order to find logical errors and not - * initalised errors in the kernel. - * - * NOTE! It's not just "uninitialised errors" that are found by doing this - * it will also find logical errors that have been hidden by all the zeros. - */ - - memset(p, 0xF1, size); -#endif -#endif } return p; } void SimulatedBlock::deallocRecord(void ** ptr, - const char * type, size_t s, size_t n) const { + const char * type, size_t s, size_t n){ (void)type; (void)s; (void)n; @@ -704,6 +701,12 @@ SimulatedBlock::deallocRecord(void ** ptr, } void +SimulatedBlock::refresh_watch_dog() +{ + globalData.incrementWatchDogCounter(1); +} + +void SimulatedBlock::progError(int line, int err_code, const char* extra) const { jamLine(line); @@ -1005,7 +1008,8 @@ SimulatedBlock::assembleFragments(Signal * signal){ /** * FragInfo == 2 or 3 */ - for(Uint32 i = 0; i<secs; i++){ + Uint32 i; + for(i = 0; i<secs; i++){ Uint32 sectionNo = secNos[i]; ndbassert(sectionNo < 3); Uint32 sectionPtrI = signal->m_sectionPtr[i].i; @@ -1027,7 +1031,6 @@ SimulatedBlock::assembleFragments(Signal * signal){ /** * fragInfo = 3 */ - Uint32 i; for(i = 0; i<3; i++){ Uint32 ptrI = fragPtr.p->m_sectionPtrI[i]; if(ptrI != RNIL){ @@ -1777,3 +1780,25 @@ SimulatedBlock::execUPGRADE(Signal* signal){ break; } } + +#ifdef VM_TRACE +void +SimulatedBlock::clear_global_variables(){ + Ptr<void> ** tmp = m_global_variables; + while(* tmp != 0){ + (* tmp)->i = RNIL; + (* tmp)->p = 0; + tmp++; + } +} + +void +SimulatedBlock::init_globals_list(void ** tmp, size_t cnt){ + m_global_variables = new Ptr<void> * [cnt+1]; + for(size_t i = 0; i<cnt; i++){ + m_global_variables[i] = (Ptr<void>*)tmp[i]; + } + m_global_variables[cnt] = 0; +} + +#endif diff --git a/ndb/src/kernel/vm/SimulatedBlock.hpp b/ndb/src/kernel/vm/SimulatedBlock.hpp index 491d432625e..6d46e9cc377 100644 --- a/ndb/src/kernel/vm/SimulatedBlock.hpp +++ b/ndb/src/kernel/vm/SimulatedBlock.hpp @@ -96,7 +96,7 @@ protected: * Handling of execFunctions */ typedef void (SimulatedBlock::* ExecFunction)(Signal* signal); - void addRecSignalImpl(GlobalSignalNumber g, ExecFunction fun, bool f = false); + void addRecSignalImpl(GlobalSignalNumber g, ExecFunction fun, bool f =false); void installSimulatedBlockFunctions(); ExecFunction theExecArray[MAX_GSN+1]; public: @@ -304,7 +304,13 @@ protected: BlockNumber number() const; BlockReference reference() const; NodeId getOwnNodeId() const; - + + /** + * Refresh Watch Dog in initialising code + * + */ + void refresh_watch_dog(); + /** * Prog error * This function should be called when this node should be shutdown @@ -344,14 +350,14 @@ protected: * Allocates memory for the datastructures where ndb keeps the data * */ - void* allocRecord(const char * type, size_t s, size_t n) const ; + void* allocRecord(const char * type, size_t s, size_t n, bool clear = true); /** * Deallocate record * * NOTE: Also resets pointer */ - void deallocRecord(void **, const char * type, size_t s, size_t n) const ; + void deallocRecord(void **, const char * type, size_t s, size_t n); /** * General info event (sent to cluster log) @@ -441,6 +447,12 @@ public: } m_timeTrace[MAX_GSN+1]; Uint32 m_currentGsn; #endif + +#ifdef VM_TRACE + Ptr<void> **m_global_variables; + void clear_global_variables(); + void init_globals_list(void ** tmp, size_t cnt); +#endif }; inline @@ -448,6 +460,9 @@ void SimulatedBlock::executeFunction(GlobalSignalNumber gsn, Signal* signal){ ExecFunction f = theExecArray[gsn]; if(gsn <= MAX_GSN && f != 0){ +#ifdef VM_TRACE + clear_global_variables(); +#endif (this->*f)(signal); return; } @@ -458,11 +473,11 @@ SimulatedBlock::executeFunction(GlobalSignalNumber gsn, Signal* signal){ char errorMsg[255]; if (!(gsn <= MAX_GSN)) { snprintf(errorMsg, 255, "Illegal signal received (GSN %d too high)", gsn); - REQUIRE(false, errorMsg); + ERROR_SET(fatal, ERR_ERROR_PRGERR, errorMsg, errorMsg); } if (!(theExecArray[gsn] != 0)) { snprintf(errorMsg, 255, "Illegal signal received (GSN %d not added)", gsn); - REQUIRE(false, errorMsg); + ERROR_SET(fatal, ERR_ERROR_PRGERR, errorMsg, errorMsg); } ndbrequire(false); } @@ -673,6 +688,5 @@ BLOCK::addRecSignal(GlobalSignalNumber gsn, ExecSignalLocal f, bool force){ \ addRecSignalImpl(gsn, (ExecFunction)f, force);\ } - #endif diff --git a/ndb/src/kernel/vm/ThreadConfig.cpp b/ndb/src/kernel/vm/ThreadConfig.cpp index d18b20a5bb5..4844bb9a477 100644 --- a/ndb/src/kernel/vm/ThreadConfig.cpp +++ b/ndb/src/kernel/vm/ThreadConfig.cpp @@ -147,8 +147,8 @@ void ThreadConfig::ipControlLoop() // plus checking for any received messages. //-------------------------------------------------------------------- if (i++ >= 20) { + globalTransporterRegistry.update_connections(); globalData.incrementWatchDogCounter(5); - globalTransporterRegistry.checkConnections(); i = 0; }//if diff --git a/ndb/src/kernel/vm/TransporterCallback.cpp b/ndb/src/kernel/vm/TransporterCallback.cpp index eb7d138895c..158de64c87f 100644 --- a/ndb/src/kernel/vm/TransporterCallback.cpp +++ b/ndb/src/kernel/vm/TransporterCallback.cpp @@ -434,5 +434,28 @@ reportDisconnect(void * callbackObj, NodeId nodeId, Uint32 errNo){ globalScheduler.execute(&signal, JBA, CMVMI, GSN_DISCONNECT_REP); } - +void +SignalLoggerManager::printSegmentedSection(FILE * output, + const SignalHeader & sh, + const SegmentedSectionPtr ptr[3], + unsigned i) +{ + fprintf(output, "SECTION %u type=segmented", i); + if (i >= 3) { + fprintf(output, " *** invalid ***\n"); + return; + } + const Uint32 len = ptr[i].sz; + SectionSegment * ssp = ptr[i].p; + Uint32 pos = 0; + fprintf(output, " size=%u\n", (unsigned)len); + while (pos < len) { + if (pos > 0 && pos % SectionSegment::DataLength == 0) { + ssp = g_sectionSegmentPool.getPtr(ssp->m_nextSegment); + } + printDataWord(output, pos, ssp->theData[pos % SectionSegment::DataLength]); + } + if (len > 0) + putc('\n', output); +} diff --git a/ndb/src/mgmapi/Makefile.am b/ndb/src/mgmapi/Makefile.am index e4fa1d449c6..0f0e1cea5d8 100644 --- a/ndb/src/mgmapi/Makefile.am +++ b/ndb/src/mgmapi/Makefile.am @@ -9,5 +9,7 @@ DEFS_LOC = -DNO_DEBUG_MESSAGES include $(top_srcdir)/ndb/config/common.mk.am include $(top_srcdir)/ndb/config/type_util.mk.am +#ndbtest_PROGRAMS = ndb_test_mgmapi + # Don't update the files from bitkeeper %::SCCS/s.% diff --git a/ndb/src/mgmapi/mgmapi.cpp b/ndb/src/mgmapi/mgmapi.cpp index bb4b6be8221..e78b0d41cf2 100644 --- a/ndb/src/mgmapi/mgmapi.cpp +++ b/ndb/src/mgmapi/mgmapi.cpp @@ -24,6 +24,7 @@ #include <NdbOut.hpp> #include <SocketServer.hpp> +#include <SocketClient.hpp> #include <Parser.hpp> #include <OutputStream.hpp> #include <InputStream.hpp> @@ -63,7 +64,7 @@ 0, \ 0, 0 } -class ParserDummy : SocketServer::Session +class ParserDummy : private SocketServer::Session { public: ParserDummy(NDB_SOCKET_TYPE sock); @@ -282,6 +283,7 @@ ndb_mgm_call(NdbMgmHandle handle, const ParserRow<ParserDummy> *command_reply, while((name = iter.next()) != NULL) { PropertiesType t; Uint32 val_i; + Uint64 val_64; BaseString val_s; cmd_args->getTypeOf(name, &t); @@ -290,11 +292,15 @@ ndb_mgm_call(NdbMgmHandle handle, const ParserRow<ParserDummy> *command_reply, cmd_args->get(name, &val_i); out.println("%s: %d", name, val_i); break; + case PropertiesType_Uint64: + cmd_args->get(name, &val_64); + out.println("%s: %Ld", name, val_64); + break; case PropertiesType_char: cmd_args->get(name, val_s); out.println("%s: %s", name, val_s.c_str()); break; - default: + case PropertiesType_Properties: /* Ignore */ break; } @@ -318,8 +324,8 @@ ndb_mgm_call(NdbMgmHandle handle, const ParserRow<ParserDummy> *command_reply, /** * Print some info about why the parser returns NULL */ -// ndbout << " status=" << ctx.m_status << ", curr=" -// << ctx.m_currentToken << endl; + //ndbout << " status=" << ctx.m_status << ", curr=" + //<< ctx.m_currentToken << endl; } #ifdef MGMAPI_LOG else { @@ -362,30 +368,11 @@ ndb_mgm_connect(NdbMgmHandle handle, const char * mgmsrv) /** * Do connect */ - const NDB_SOCKET_TYPE sockfd = socket(AF_INET, SOCK_STREAM, 0); - if (sockfd == NDB_INVALID_SOCKET) { - SET_ERROR(handle, NDB_MGM_ILLEGAL_SOCKET, ""); - return -1; - } - - struct sockaddr_in servaddr; - memset(&servaddr, 0, sizeof(servaddr)); - servaddr.sin_family = AF_INET; - servaddr.sin_port = htons(handle->port); - // Convert ip address presentation format to numeric format - const int res1 = Ndb_getInAddr(&servaddr.sin_addr, handle->hostname); - if (res1 != 0) { - DEBUG("Ndb_getInAddr(...) == -1"); - setError(handle, EINVAL, __LINE__, "Invalid hostname/address"); - return -1; - } - - const int res2 = connect(sockfd, (struct sockaddr*) &servaddr, - sizeof(servaddr)); - if (res2 == -1) { - NDB_CLOSE_SOCKET(sockfd); - setError(handle, NDB_MGM_COULD_NOT_CONNECT_TO_SOCKET, __LINE__, "Unable to connect to %s", - mgmsrv); + SocketClient s(handle->hostname, handle->port); + const NDB_SOCKET_TYPE sockfd = s.connect(); + if (sockfd < 0) { + setError(handle, NDB_MGM_COULD_NOT_CONNECT_TO_SOCKET, __LINE__, + "Unable to connect to %s", mgmsrv); return -1; } @@ -491,11 +478,12 @@ extern "C" const char * ndb_mgm_get_node_status_string(enum ndb_mgm_node_status status) { - for(int i = 0; i<no_of_status_values; i++) + int i; + for(i = 0; i<no_of_status_values; i++) if(status_values[i].value == status) return status_values[i].str; - for(int i = 0; i<no_of_status_values; i++) + for(i = 0; i<no_of_status_values; i++) if(status_values[i].value == NDB_MGM_NODE_STATUS_UNKNOWN) return status_values[i].str; @@ -562,7 +550,7 @@ ndb_mgm_get_status(NdbMgmHandle handle) buf[strlen(buf)-1] = '\0'; if(strcmp("node status", buf) != 0) { - SET_ERROR(handle, NDB_MGM_ILLEGAL_NODE_STATUS, ""); + SET_ERROR(handle, NDB_MGM_ILLEGAL_NODE_STATUS, buf); return NULL; } @@ -1450,11 +1438,7 @@ ndb_mgm_get_configuration(NdbMgmHandle handle, unsigned int version) { const Properties *prop; prop = ndb_mgm_call(handle, reply, "get config", &args); - - if(prop == NULL) { - SET_ERROR(handle, EIO, "Unable to fetch config"); - return 0; - } + CHECK_REPLY(prop, 0); do { const char * buf; @@ -1515,7 +1499,8 @@ ndb_mgm_get_configuration(NdbMgmHandle handle, unsigned int version) { ndbout_c("Failed to unpack buffer"); break; } - + + delete prop; return (ndb_mgm_configuration*)cvf.m_cfg; } while(0); @@ -1523,6 +1508,52 @@ ndb_mgm_get_configuration(NdbMgmHandle handle, unsigned int version) { return 0; } +extern "C" +int +ndb_mgm_alloc_nodeid(NdbMgmHandle handle, unsigned int version, unsigned *pnodeid, int nodetype) +{ + + CHECK_HANDLE(handle, 0); + CHECK_CONNECTED(handle, 0); + + Properties args; + args.put("version", version); + args.put("nodetype", nodetype); + args.put("nodeid", *pnodeid); + args.put("user", "mysqld"); + args.put("password", "mysqld"); + args.put("public key", "a public key"); + + const ParserRow<ParserDummy> reply[]= { + MGM_CMD("get nodeid reply", NULL, ""), + MGM_ARG("nodeid", Int, Optional, "Error message"), + MGM_ARG("result", String, Mandatory, "Error message"), + MGM_END() + }; + + const Properties *prop; + prop= ndb_mgm_call(handle, reply, "get nodeid", &args); + CHECK_REPLY(prop, -1); + + int res= -1; + do { + const char * buf; + if(!prop->get("result", &buf) || strcmp(buf, "Ok") != 0){ + setError(handle, NDB_MGM_COULD_NOT_CONNECT_TO_SOCKET, __LINE__, + "Could not alloc node id: %s",buf); + break; + } + if(!prop->get("nodeid", pnodeid) != 0){ + ndbout_c("ERROR Message: <nodeid Unspecified>\n"); + break; + } + res= 0; + }while(0); + + delete prop; + return res; +} + /***************************************************************************** * Global Replication ******************************************************************************/ @@ -1559,3 +1590,130 @@ ndb_mgm_rep_command(NdbMgmHandle handle, unsigned int request, delete reply; return 0; } + +extern "C" +int +ndb_mgm_set_int_parameter(NdbMgmHandle handle, + int node, + int param, + unsigned value, + struct ndb_mgm_reply*){ + CHECK_HANDLE(handle, 0); + CHECK_CONNECTED(handle, 0); + + Properties args; + args.put("node: ", node); + args.put("param: ", param); + args.put("value: ", value); + + const ParserRow<ParserDummy> reply[]= { + MGM_CMD("set parameter reply", NULL, ""), + MGM_ARG("result", String, Mandatory, "Error message"), + MGM_END() + }; + + const Properties *prop; + prop= ndb_mgm_call(handle, reply, "set parameter", &args); + CHECK_REPLY(prop, -1); + + int res= -1; + do { + const char * buf; + if(!prop->get("result", &buf) || strcmp(buf, "Ok") != 0){ + ndbout_c("ERROR Message: %s\n", buf); + break; + } + res= 0; + } while(0); + + delete prop; + return res; +} + +extern "C" +int +ndb_mgm_set_int64_parameter(NdbMgmHandle handle, + int node, + int param, + unsigned long long value, + struct ndb_mgm_reply*){ + CHECK_HANDLE(handle, 0); + CHECK_CONNECTED(handle, 0); + + Properties args; + args.put("node: ", node); + args.put("param: ", param); + args.put("value: ", value); + + const ParserRow<ParserDummy> reply[]= { + MGM_CMD("set parameter reply", NULL, ""), + MGM_ARG("result", String, Mandatory, "Error message"), + MGM_END() + }; + + const Properties *prop; + prop= ndb_mgm_call(handle, reply, "set parameter", &args); + + if(prop == NULL) { + SET_ERROR(handle, EIO, "Unable set parameter"); + return -1; + } + + int res= -1; + do { + const char * buf; + if(!prop->get("result", &buf) || strcmp(buf, "Ok") != 0){ + ndbout_c("ERROR Message: %s\n", buf); + break; + } + res= 0; + } while(0); + + delete prop; + return res; +} + +extern "C" +int +ndb_mgm_set_string_parameter(NdbMgmHandle handle, + int node, + int param, + const char * value, + struct ndb_mgm_reply*){ + CHECK_HANDLE(handle, 0); + CHECK_CONNECTED(handle, 0); + + Properties args; + args.put("node: ", node); + args.put("parameter: ", param); + args.put("value: ", value); + + const ParserRow<ParserDummy> reply[]= { + MGM_CMD("set parameter reply", NULL, ""), + MGM_ARG("result", String, Mandatory, "Error message"), + MGM_END() + }; + + const Properties *prop; + prop= ndb_mgm_call(handle, reply, "set parameter", &args); + + if(prop == NULL) { + SET_ERROR(handle, EIO, "Unable set parameter"); + return -1; + } + + int res= -1; + do { + const char * buf; + if(!prop->get("result", &buf) || strcmp(buf, "Ok") != 0){ + ndbout_c("ERROR Message: %s\n", buf); + break; + } + res= 0; + } while(0); + + delete prop; + return res; +} + +template class Vector<const ParserRow<ParserDummy>*>; diff --git a/ndb/src/mgmclient/CommandInterpreter.cpp b/ndb/src/mgmclient/CommandInterpreter.cpp index cf9d885847a..141a0be0eff 100644 --- a/ndb/src/mgmclient/CommandInterpreter.cpp +++ b/ndb/src/mgmclient/CommandInterpreter.cpp @@ -634,7 +634,8 @@ CommandInterpreter::executeHelp(char* parameters) void CommandInterpreter::executeShow(char* parameters) -{ +{ + int i; connect(); if (emptyString(parameters)) { ndbout << "Cluster Configuration" << endl @@ -648,16 +649,27 @@ CommandInterpreter::executeShow(char* parameters) } int - ndb_nodes = 0, - api_nodes = 0, - mgm_nodes = 0; - - for(int i=0; i < state->no_of_nodes; i++) { + master_id= 0, + ndb_nodes= 0, + api_nodes= 0, + mgm_nodes= 0; + + for(i=0; i < state->no_of_nodes; i++) { + if(state->node_states[i].node_type == NDB_MGM_NODE_TYPE_NDB && + state->node_states[i].version != 0){ + master_id= state->node_states[i].dynamic_id; + break; + } + } + + for(i=0; i < state->no_of_nodes; i++) { switch(state->node_states[i].node_type) { case NDB_MGM_NODE_TYPE_API: api_nodes++; break; case NDB_MGM_NODE_TYPE_NDB: + if (state->node_states[i].dynamic_id < master_id) + master_id= state->node_states[i].dynamic_id; ndb_nodes++; break; case NDB_MGM_NODE_TYPE_MGM: @@ -673,15 +685,18 @@ CommandInterpreter::executeShow(char* parameters) << " NDB Node(s)" << endl; - for(int i=0; i < state->no_of_nodes; i++) { + for(i=0; i < state->no_of_nodes; i++) { if(state->node_states[i].node_type == NDB_MGM_NODE_TYPE_NDB) { ndbout << "DB node:\t" << state->node_states[i].node_id; if(state->node_states[i].version != 0) { ndbout << " (Version: " << getMajor(state->node_states[i].version) << "." << getMinor(state->node_states[i].version) << "." - << getBuild(state->node_states[i].version) << ")" << endl; - + << getBuild(state->node_states[i].version) << "," + << " Nodegroup: " << state->node_states[i].node_group; + if (state->node_states[i].dynamic_id == master_id) + ndbout << ", Master"; + ndbout << ")" << endl; } else { ndbout << " (not connected) " << endl; @@ -691,13 +706,13 @@ CommandInterpreter::executeShow(char* parameters) } ndbout << endl; - ndbout << api_nodes - << " API Node(s)" + ndbout << mgm_nodes + << " MGM Node(s)" << endl; - for(int i=0; i < state->no_of_nodes; i++) { - if(state->node_states[i].node_type == NDB_MGM_NODE_TYPE_API) { - ndbout << "API node:\t" << state->node_states[i].node_id; + for(i=0; i < state->no_of_nodes; i++) { + if(state->node_states[i].node_type == NDB_MGM_NODE_TYPE_MGM) { + ndbout << "MGM node:\t" << state->node_states[i].node_id; if(state->node_states[i].version != 0) { ndbout << " (Version: " << getMajor(state->node_states[i].version) << "." @@ -706,19 +721,19 @@ CommandInterpreter::executeShow(char* parameters) } else { - ndbout << " (not connected) " << endl; + ndbout << " (no version information available) " << endl; } } } ndbout << endl; - - ndbout << mgm_nodes - << " MGM Node(s)" + + ndbout << api_nodes + << " API Node(s)" << endl; - for(int i=0; i < state->no_of_nodes; i++) { - if(state->node_states[i].node_type == NDB_MGM_NODE_TYPE_MGM) { - ndbout << "MGM node:\t" << state->node_states[i].node_id; + for(i=0; i < state->no_of_nodes; i++) { + if(state->node_states[i].node_type == NDB_MGM_NODE_TYPE_API) { + ndbout << "API node:\t" << state->node_states[i].node_id; if(state->node_states[i].version != 0) { ndbout << " (Version: " << getMajor(state->node_states[i].version) << "." @@ -727,11 +742,12 @@ CommandInterpreter::executeShow(char* parameters) } else { - ndbout << " (no version information available) " << endl; + ndbout << " (not connected) " << endl; } } } ndbout << endl; + // ndbout << helpTextShow; return; } else if (strcmp(parameters, "PROPERTIES") == 0 || @@ -759,6 +775,7 @@ CommandInterpreter::executeShow(char* parameters) void CommandInterpreter::executeClusterLog(char* parameters) { + int i; connect(); if (parameters != 0 && strlen(parameters) != 0) { enum ndb_mgm_clusterlog_level severity = NDB_MGM_CLUSTERLOG_ALL; @@ -846,10 +863,10 @@ CommandInterpreter::executeClusterLog(char* parameters) ndbout << "Cluster logging is disabled." << endl; - for(int i = 0; i<7;i++) + for(i = 0; i<7;i++) printf("enabled[%d] = %d\n", i, enabled[i]); ndbout << "Severities enabled: "; - for(int i = 1; i < 7; i++) { + for(i = 1; i < 7; i++) { if(enabled[i]) ndbout << names[i] << " "; } @@ -1298,14 +1315,15 @@ CommandInterpreter::executeLog(int processId, return; } int len=0; - for(Uint32 i=0; i<blocks.size(); i++) { + Uint32 i; + for(i=0; i<blocks.size(); i++) { ndbout_c("blocks %s %d",blocks[i], strlen(blocks[i])); len += strlen(blocks[i]); } len += blocks.size()*2; char * blockNames = (char*)malloc(len); - for(Uint32 i=0; i<blocks.size(); i++) { + for(i=0; i<blocks.size(); i++) { strcat(blockNames, blocks[i]); strcat(blockNames, "|"); } @@ -1478,7 +1496,7 @@ CommandInterpreter::executeSet(int /*processId*/, << endl; } else { - NDB_ASSERT(false, ""); + assert(false); } } else { @@ -1497,7 +1515,7 @@ CommandInterpreter::executeSet(int /*processId*/, } else { // The primary is not tried to write if the write of backup file fails - NDB_ASSERT(false, ""); + abort(); } } free(newpar); @@ -2020,3 +2038,5 @@ CmdBackupCallback(const MgmtSrvr::BackupEvent & event){ ndbout << str << endl; } #endif + +template class Vector<char const*>; diff --git a/ndb/src/mgmclient/CpcClient.cpp b/ndb/src/mgmclient/CpcClient.cpp index 74fa1a828ed..0291573a704 100644 --- a/ndb/src/mgmclient/CpcClient.cpp +++ b/ndb/src/mgmclient/CpcClient.cpp @@ -478,9 +478,9 @@ SimpleCpcClient::connect() { if (::connect(cpc_sock, (struct sockaddr*) &sa, sizeof(sa)) < 0) return -1; - cpc_in = new SocketInputStream(cpc_sock); + cpc_in = new SocketInputStream(cpc_sock, 60000); cpc_out = new SocketOutputStream(cpc_sock); - + return 0; } @@ -557,4 +557,6 @@ SimpleCpcClient::cpc_call(const char *cmd, SimpleCpcClient::ParserDummy::ParserDummy(NDB_SOCKET_TYPE sock) : SocketServer::Session(sock) { } - + +template class Vector<SimpleCpcClient::Process>; +template class Vector<ParserRow<SimpleCpcClient::ParserDummy> const*>; diff --git a/ndb/src/mgmclient/main.cpp b/ndb/src/mgmclient/main.cpp index 2dcadf9369d..df6659df0b1 100644 --- a/ndb/src/mgmclient/main.cpp +++ b/ndb/src/mgmclient/main.cpp @@ -24,9 +24,7 @@ #include "CommandInterpreter.hpp" -#include <signal.h> - -const char *progname = "mgmtclient"; +const char *progname = "ndb_mgm"; static CommandInterpreter* com; @@ -47,14 +45,13 @@ handler(int sig){ int main(int argc, const char** argv){ int optind = 0; - const char *_default_connectstring = "host=localhost:2200;nodeid=0"; const char *_host = 0; int _port = 0; int _help = 0; int _try_reconnect = 0; struct getargs args[] = { - { "try-reconnect", 0, arg_integer, &_try_reconnect, "", "" }, + { "try-reconnect", 't', arg_integer, &_try_reconnect, "Specify number of retries for connecting to ndb_mgmd, default infinite", "#" }, { "usage", '?', arg_flag, &_help, "Print help", "" }, }; int num_args = sizeof(args) / sizeof(args[0]); /* Number of arguments */ @@ -76,9 +73,9 @@ int main(int argc, const char** argv){ _port = atoi(argv[1]); } } else { - if(cfg.init(false, 0, 0, _default_connectstring) && cfg.items > 0 && cfg.ids[0]->type == MgmId_TCP){ - _host = cfg.ids[0]->data.tcp.remoteHost; - _port = cfg.ids[0]->data.tcp.port; + if(cfg.init(0, 0) && cfg.ids.size() > 0 && cfg.ids[0].type == MgmId_TCP){ + _host = cfg.ids[0].name.c_str(); + _port = cfg.ids[0].port; } else { cfg.printError(); cfg.printUsage(); diff --git a/ndb/src/mgmsrv/CommandInterpreter.cpp b/ndb/src/mgmsrv/CommandInterpreter.cpp index 004fc463b70..316b6d5795e 100644 --- a/ndb/src/mgmsrv/CommandInterpreter.cpp +++ b/ndb/src/mgmsrv/CommandInterpreter.cpp @@ -378,7 +378,8 @@ void CommandInterpreter::executeHelp(char* parameters) { (void)parameters; // Don't want compiler warning if (emptyString(parameters)) { - for (int i = 0; i<noOfHelpTexts; i++) { + unsigned i; + for (i = 0; i<noOfHelpTexts; i++) { ndbout << helpTexts[i] << endl; } @@ -388,7 +389,7 @@ void CommandInterpreter::executeHelp(char* parameters) { << endl; ndbout << "<category> = "; - for(Uint32 i = 0; i<EventLogger::noOfEventCategoryNames; i++){ + for(i = 0; i<EventLogger::noOfEventCategoryNames; i++){ ndbout << EventLogger::eventCategoryNames[i].name; if (i < EventLogger::noOfEventCategoryNames - 1) { ndbout << " | "; @@ -1195,11 +1196,12 @@ CommandInterpreter::jonas(int processId, const char* parameters, bool all) { data[0] = 12; data[1] = 13; - - for(Uint32 i = 0; i<70; i++) + + unsigned i; + for(i = 0; i<70; i++) sec0[i] = i; - for(Uint32 i = 0; i<123; i++) + for(i = 0; i<123; i++) sec1[i] = 70+i; signal.set(0, CMVMI, GSN_TESTSIG, 3); diff --git a/ndb/src/mgmsrv/MgmtSrvr.cpp b/ndb/src/mgmsrv/MgmtSrvr.cpp index 713433cb8e9..0936ec234cf 100644 --- a/ndb/src/mgmsrv/MgmtSrvr.cpp +++ b/ndb/src/mgmsrv/MgmtSrvr.cpp @@ -43,10 +43,12 @@ #include <DebuggerNames.hpp> #include <ndb_version.h> -#include "SocketServer.hpp" +#include <SocketServer.hpp> #include "NodeLogLevel.hpp" #include <NdbConfig.h> +#include <NdbAutoPtr.hpp> + #include <mgmapi.h> #include <mgmapi_configuration.hpp> #include <mgmapi_config_parameters.h> @@ -170,7 +172,7 @@ MgmtSrvr::signalRecvThreadRun() siglist.push_back(SigMatch(GSN_MGM_UNLOCK_CONFIG_REQ, &MgmtSrvr::handle_MGM_UNLOCK_CONFIG_REQ)); - while(1) { + while(!_isStopThread) { SigMatch *handler = NULL; NdbApiSignal *signal = NULL; if(m_signalRecvQueue.waitFor(siglist, handler, signal)) { @@ -240,23 +242,20 @@ MgmtSrvr::startEventLog() const char * tmp; BaseString logdest; - char clusterLog[MAXPATHLEN]; - NdbConfig_ClusterLogFileName(clusterLog, sizeof(clusterLog)); - - + char *clusterLog= NdbConfig_ClusterLogFileName(_ownNodeId); + NdbAutoPtr<char> tmp_aptr(clusterLog); + if(ndb_mgm_get_string_parameter(iter, CFG_LOG_DESTINATION, &tmp) == 0){ logdest.assign(tmp); } ndb_mgm_destroy_iterator(iter); - if(logdest.length()==0) { + if(logdest.length() == 0 || logdest == "") { logdest.assfmt("FILE:filename=%s,maxsize=1000000,maxfiles=6", clusterLog); } - if(!g_EventLogger.addHandler(logdest)) { - ndbout << "ERROR: cannot parse \"" << logdest << "\"" << endl; - exit(1); + ndbout << "Warning: could not add log destination \"" << logdest.c_str() << "\"" << endl; } } @@ -391,6 +390,99 @@ MgmtSrvr::getNodeCount(enum ndb_mgm_node_type type) const } int +MgmtSrvr::getPort() const { + const Properties *mgmProps; + + ndb_mgm_configuration_iterator * iter = + ndb_mgm_create_configuration_iterator(_config->m_configValues, + CFG_SECTION_NODE); + if(iter == 0) + return 0; + + if(ndb_mgm_find(iter, CFG_NODE_ID, getOwnNodeId()) != 0){ + ndbout << "Could not retrieve configuration for Node " + << getOwnNodeId() << " in config file." << endl + << "Have you set correct NodeId for this node?" << endl; + ndb_mgm_destroy_iterator(iter); + return 0; + } + + unsigned type; + if(ndb_mgm_get_int_parameter(iter, CFG_TYPE_OF_SECTION, &type) != 0 || + type != NODE_TYPE_MGM){ + ndbout << "Local node id " << getOwnNodeId() + << " is not defined as management server" << endl + << "Have you set correct NodeId for this node?" << endl; + ndb_mgm_destroy_iterator(iter); + return 0; + } + + Uint32 port = 0; + if(ndb_mgm_get_int_parameter(iter, CFG_MGM_PORT, &port) != 0){ + ndbout << "Could not find PortNumber in the configuration file." << endl; + ndb_mgm_destroy_iterator(iter); + return 0; + } + + ndb_mgm_destroy_iterator(iter); + + /***************** + * Set Stat Port * + *****************/ +#if 0 + if (!mgmProps->get("PortNumberStats", &tmp)){ + ndbout << "Could not find PortNumberStats in the configuration file." + << endl; + return false; + } + glob.port_stats = tmp; +#endif + +#if 0 + const char * host; + if(ndb_mgm_get_string_parameter(iter, mgmProps->get("ExecuteOnComputer", host)){ + ndbout << "Failed to find \"ExecuteOnComputer\" for my node" << endl; + ndbout << "Unable to verify own hostname" << endl; + return false; + } + + const char * hostname; + { + const Properties * p; + char buf[255]; + snprintf(buf, sizeof(buf), "Computer_%s", host.c_str()); + if(!glob.cluster_config->get(buf, &p)){ + ndbout << "Failed to find computer " << host << " in config" << endl; + ndbout << "Unable to verify own hostname" << endl; + return false; + } + if(!p->get("HostName", &hostname)){ + ndbout << "Failed to find \"HostName\" for computer " << host + << " in config" << endl; + ndbout << "Unable to verify own hostname" << endl; + return false; + } + if(NdbHost_GetHostName(buf) != 0){ + ndbout << "Unable to get own hostname" << endl; + ndbout << "Unable to verify own hostname" << endl; + return false; + } + } + + const char * ip_address; + if(mgmProps->get("IpAddress", &ip_address)){ + glob.use_specific_ip = true; + glob.interface_name = strdup(ip_address); + return true; + } + + glob.interface_name = strdup(hostname); +#endif + + return port; +} + +int MgmtSrvr::getStatPort() const { #if 0 const Properties *mgmProps; @@ -417,9 +509,9 @@ MgmtSrvr::MgmtSrvr(NodeId nodeId, _ownReference(0), theSignalIdleList(NULL), theWaitState(WAIT_SUBSCRIBE_CONF), - theConfCount(0) { + theConfCount(0), + m_allocated_resources(*this) { - _ownNodeId = nodeId; _config = NULL; _isStatPortActive = false; _isClusterLogStatActive = false; @@ -427,8 +519,11 @@ MgmtSrvr::MgmtSrvr(NodeId nodeId, _isStopThread = false; _logLevelThread = NULL; _logLevelThreadSleep = 500; + m_signalRecvThread = NULL; _startedNodeId = 0; + theFacade = 0; + m_newConfig = NULL; m_configFilename = configFilename; setCallback(CmdBackupCallback); @@ -486,6 +581,14 @@ MgmtSrvr::MgmtSrvr(NodeId nodeId, _clusterLogLevelList = new NodeLogLevelList(); _props = NULL; + + _ownNodeId= 0; + NodeId tmp= nodeId; + if (!alloc_node_id(&tmp, NDB_MGM_NODE_TYPE_MGM, 0, 0)){ + ndbout << "Unable to obtain requested nodeid " << nodeId; + exit(-1); + } + _ownNodeId = tmp; } @@ -510,8 +613,7 @@ MgmtSrvr::start() return false; } theFacade = TransporterFacade::start_instance - (_ownNodeId, - (ndb_mgm_configuration*)_config->m_configValues); + (_ownNodeId,(ndb_mgm_configuration*)_config->m_configValues); if(theFacade == 0) { DEBUG("MgmtSrvr.cpp: theFacade is NULL."); @@ -573,8 +675,7 @@ MgmtSrvr::~MgmtSrvr() stopEventLog(); - NdbCondition_Destroy(theMgmtWaitForResponseCondPtr); - NdbMutex_Destroy(m_configMutex); + NdbCondition_Destroy(theMgmtWaitForResponseCondPtr); NdbMutex_Destroy(m_configMutex); if(m_newConfig != NULL) free(m_newConfig); @@ -593,6 +694,11 @@ MgmtSrvr::~MgmtSrvr() NdbThread_WaitFor(_logLevelThread, &res); NdbThread_Destroy(&_logLevelThread); } + + if (m_signalRecvThread != NULL) { + NdbThread_WaitFor(m_signalRecvThread, &res); + NdbThread_Destroy(&m_signalRecvThread); + } } //**************************************************************************** @@ -818,7 +924,7 @@ MgmtSrvr::restart(bool nostart, bool initalStart, bool abort, return 0; } - TransporterFacade::instance()->lock_mutex(); + theFacade->lock_mutex(); int waitTime = timeOut/m_stopRec.sentCount; if (receiveOptimisedResponse(waitTime) != 0) { m_stopRec.inUse = false; @@ -985,16 +1091,15 @@ MgmtSrvr::version(int * stopCount, bool abort, m_versionRec.callback = callback; m_versionRec.inUse = true ; - - for(Uint32 i = 0; i<MAX_NODES; i++) { + Uint32 i; + for(i = 0; i<MAX_NODES; i++) { if (getNodeType(i) == NDB_MGM_NODE_TYPE_MGM) { m_versionRec.callback(i, NDB_VERSION, this,0); } } - for(Uint32 i = 0; i<MAX_NODES; i++) { + for(i = 0; i<MAX_NODES; i++) { if (getNodeType(i) == NDB_MGM_NODE_TYPE_NDB) { - node = - TransporterFacade::instance()->theClusterMgr->getNodeInfo(i); + node = theFacade->theClusterMgr->getNodeInfo(i); version = node.m_info.m_version; if(theFacade->theClusterMgr->getNodeInfo(i).connected) m_versionRec.callback(i, version, this,0); @@ -1003,7 +1108,7 @@ MgmtSrvr::version(int * stopCount, bool abort, } } - for(Uint32 i = 0; i<MAX_NODES; i++) { + for(i = 0; i<MAX_NODES; i++) { if (getNodeType(i) == NDB_MGM_NODE_TYPE_API) { return sendVersionReq(i); } @@ -1148,7 +1253,7 @@ MgmtSrvr::stop(int * stopCount, bool abort, StopCallback callback, if(m_stopRec.sentCount > 0){ if(callback == 0){ - TransporterFacade::instance()->lock_mutex(); + theFacade->lock_mutex(); receiveOptimisedResponse(timeOut / m_stopRec.sentCount); } else { return 0; @@ -1178,7 +1283,7 @@ MgmtSrvr::enterSingleUser(int * stopCount, Uint32 singleUserNodeId, for(Uint32 i = 0; i<MAX_NODES; i++) { if (getNodeType(i) == NDB_MGM_NODE_TYPE_NDB) { - node = TransporterFacade::instance()->theClusterMgr->getNodeInfo(i); + node = theFacade->theClusterMgr->getNodeInfo(i); if((node.m_state.startLevel != NodeState::SL_STARTED) && (node.m_state.startLevel != NodeState::SL_NOTHING)) { return 5063; @@ -1337,7 +1442,7 @@ MgmtSrvr::status(int processId, } const ClusterMgr::Node node = - TransporterFacade::instance()->theClusterMgr->getNodeInfo(processId); + theFacade->theClusterMgr->getNodeInfo(processId); if(!node.connected){ * _status = NDB_MGM_NODE_STATUS_NO_CONTACT; @@ -1463,7 +1568,8 @@ MgmtSrvr::setEventReportingLevelImpl(int processId, const SetLogLevelOrd & ll, bool isResend) { - for(Uint32 i = 0; i<ll.noOfEntries; i++){ + Uint32 i; + for(i = 0; i<ll.noOfEntries; i++){ // Save log level for the cluster log if (!isResend) { NodeLogLevel* n = NULL; @@ -1494,7 +1600,7 @@ MgmtSrvr::setEventReportingLevelImpl(int processId, EventSubscribeReq * dst = CAST_PTR(EventSubscribeReq, signal->getDataPtrSend()); - for(Uint32 i = 0; i<ll.noOfEntries; i++){ + for(i = 0; i<ll.noOfEntries; i++){ dst->theCategories[i] = ll.theCategories[i]; dst->theLevels[i] = ll.theLevels[i]; } @@ -1523,7 +1629,8 @@ int MgmtSrvr::setNodeLogLevel(int processId, const SetLogLevelOrd & ll, bool isResend) { - for(Uint32 i = 0; i<ll.noOfEntries; i++){ + Uint32 i; + for(i = 0; i<ll.noOfEntries; i++){ // Save log level for the cluster log if (!isResend) { NodeLogLevel* n = NULL; @@ -1554,7 +1661,7 @@ MgmtSrvr::setNodeLogLevel(int processId, const SetLogLevelOrd & ll, SetLogLevelOrd * dst = CAST_PTR(SetLogLevelOrd, signal->getDataPtrSend()); - for(Uint32 i = 0; i<ll.noOfEntries; i++){ + for(i = 0; i<ll.noOfEntries; i++){ dst->theCategories[i] = ll.theCategories[i]; dst->theLevels[i] = ll.theLevels[i]; } @@ -1698,7 +1805,7 @@ MgmtSrvr::setSignalLoggingMode(int processId, LogMode mode, logSpec = TestOrd::InputOutputSignals; break; default: - NDB_ASSERT(false, "Unexpected value, MgmtSrvr::setSignalLoggingMode"); + assert("Unexpected value, MgmtSrvr::setSignalLoggingMode" == 0); } NdbApiSignal* signal = getSignal(); @@ -1896,6 +2003,7 @@ MgmtSrvr::handleReceivedSignal(NdbApiSignal* signal) int returnCode; int gsn = signal->readSignalNumber(); + switch (gsn) { case GSN_API_VERSION_CONF: { if (theWaitState == WAIT_VERSION) { @@ -2000,8 +2108,7 @@ MgmtSrvr::handleReceivedSignal(NdbApiSignal* signal) req->senderData = 19; req->backupDataLen = 0; - int i = TransporterFacade::instance()->sendSignalUnCond(&aSignal, - aNodeId); + int i = theFacade->sendSignalUnCond(&aSignal, aNodeId); if(i == 0){ return; } @@ -2083,7 +2190,7 @@ MgmtSrvr::handleStopReply(NodeId nodeId, Uint32 errCode) bool failure = true; for(Uint32 i = 0; i<MAX_NODES; i++) { if (getNodeType(i) == NDB_MGM_NODE_TYPE_NDB) { - node = TransporterFacade::instance()->theClusterMgr->getNodeInfo(i); + node = theFacade->theClusterMgr->getNodeInfo(i); if((node.m_state.startLevel == NodeState::SL_NOTHING)) failure = true; else @@ -2187,6 +2294,89 @@ MgmtSrvr::getNodeType(NodeId nodeId) const return nodeTypes[nodeId]; } +#ifdef NDB_WIN32 +static NdbMutex & f_node_id_mutex = * NdbMutex_Create(); +#else +static NdbMutex f_node_id_mutex = NDB_MUTEX_INITIALIZER; +#endif + +bool +MgmtSrvr::alloc_node_id(NodeId * nodeId, + enum ndb_mgm_node_type type, + struct sockaddr *client_addr, + SOCKET_SIZE_TYPE *client_addr_len) +{ + Guard g(&f_node_id_mutex); +#if 0 + ndbout << "MgmtSrvr::getFreeNodeId type=" << type + << " *nodeid=" << *nodeId << endl; +#endif + + NodeBitmask connected_nodes(m_reserved_nodes); + if (theFacade && theFacade->theClusterMgr) { + for(Uint32 i = 0; i < MAX_NODES; i++) + if (getNodeType(i) == NDB_MGM_NODE_TYPE_NDB) { + const ClusterMgr::Node &node= theFacade->theClusterMgr->getNodeInfo(i); + if (node.connected) + connected_nodes.bitOR(node.m_state.m_connected_nodes); + } + } + + ndb_mgm_configuration_iterator iter(*(ndb_mgm_configuration *)_config->m_configValues, + CFG_SECTION_NODE); + for(iter.first(); iter.valid(); iter.next()) { + unsigned tmp= 0; + if(iter.get(CFG_NODE_ID, &tmp)) abort(); + if (connected_nodes.get(tmp)) + continue; + if (*nodeId && *nodeId != tmp) + continue; + unsigned type_c; + if(iter.get(CFG_TYPE_OF_SECTION, &type_c)) abort(); + if(type_c != type) + continue; + const char *config_hostname = 0; + if(iter.get(CFG_NODE_HOST, &config_hostname)) abort(); + + if (config_hostname && config_hostname[0] != 0 && client_addr) { + // check hostname compatability + struct in_addr config_addr; + const void *tmp= &(((sockaddr_in*)client_addr)->sin_addr); + if(Ndb_getInAddr(&config_addr, config_hostname) != 0 + || memcmp(&config_addr, tmp, sizeof(config_addr)) != 0) { + struct in_addr tmp_addr; + if(Ndb_getInAddr(&tmp_addr, "localhost") != 0 + || memcmp(&tmp_addr, tmp, sizeof(config_addr)) != 0) { + // not localhost +#if 0 + ndbout << "MgmtSrvr::getFreeNodeId compare failed for \"" << config_hostname + << "\" id=" << tmp << endl; +#endif + continue; + } + // connecting through localhost + // check if config_hostname match hostname + char my_hostname[256]; + if (gethostname(my_hostname, sizeof(my_hostname)) != 0) + continue; + if(Ndb_getInAddr(&tmp_addr, my_hostname) != 0 + || memcmp(&tmp_addr, &config_addr, sizeof(config_addr)) != 0) { + // no match + continue; + } + } + } + *nodeId= tmp; + m_reserved_nodes.set(tmp); +#if 0 + ndbout << "MgmtSrvr::getFreeNodeId found type=" << type + << " *nodeid=" << *nodeId << endl; +#endif + return true; + } + return false; +} + bool MgmtSrvr::getNextNodeId(NodeId * nodeId, enum ndb_mgm_node_type type) const { @@ -2573,3 +2763,128 @@ MgmtSrvr::getPrimaryNode() const { return 0; #endif } + + +MgmtSrvr::Allocated_resources::Allocated_resources(MgmtSrvr &m) + : m_mgmsrv(m) +{ +} + +MgmtSrvr::Allocated_resources::~Allocated_resources() +{ + Guard g(&f_node_id_mutex); + m_mgmsrv.m_reserved_nodes.bitANDC(m_reserved_nodes); +} + +void +MgmtSrvr::Allocated_resources::reserve_node(NodeId id) +{ + m_reserved_nodes.set(id); +} + +int +MgmtSrvr::setDbParameter(int node, int param, const char * value, + BaseString& msg){ + /** + * Check parameter + */ + ndb_mgm_configuration_iterator iter(* _config->m_configValues, + CFG_SECTION_NODE); + if(iter.first() != 0){ + msg.assign("Unable to find node section (iter.first())"); + return -1; + } + + Uint32 type = NODE_TYPE_DB + 1; + if(node != 0){ + if(iter.find(CFG_NODE_ID, node) != 0){ + msg.assign("Unable to find node (iter.find())"); + return -1; + } + if(iter.get(CFG_TYPE_OF_SECTION, &type) != 0){ + msg.assign("Unable to get node type(iter.get(CFG_TYPE_OF_SECTION))"); + return -1; + } + } else { + do { + if(iter.get(CFG_TYPE_OF_SECTION, &type) != 0){ + msg.assign("Unable to get node type(iter.get(CFG_TYPE_OF_SECTION))"); + return -1; + } + if(type == NODE_TYPE_DB) + break; + } while(iter.next() == 0); + } + + if(type != NODE_TYPE_DB){ + msg.assfmt("Invalid node type or no such node (%d %d)", + type, NODE_TYPE_DB); + return -1; + } + + int p_type; + unsigned val_32; + unsigned long long val_64; + const char * val_char; + do { + p_type = 0; + if(iter.get(param, &val_32) == 0){ + val_32 = atoi(value); + break; + } + + p_type++; + if(iter.get(param, &val_64) == 0){ + val_64 = strtoll(value, 0, 10); + break; + } + p_type++; + if(iter.get(param, &val_char) == 0){ + val_char = value; + break; + } + msg.assign("Could not get parameter"); + return -1; + } while(0); + + bool res = false; + do { + int ret = iter.get(CFG_TYPE_OF_SECTION, &type); + assert(ret == 0); + + if(type != NODE_TYPE_DB) + continue; + + Uint32 node; + ret = iter.get(CFG_NODE_ID, &node); + assert(ret == 0); + + ConfigValues::Iterator i2(_config->m_configValues->m_config, + iter.m_config); + switch(p_type){ + case 0: + res = i2.set(param, val_32); + ndbout_c("Updateing node %d param: %d to %d", node, param, val_32); + break; + case 1: + res = i2.set(param, val_64); + ndbout_c("Updateing node %d param: %d to %Ld", node, param, val_32); + break; + case 2: + res = i2.set(param, val_char); + ndbout_c("Updateing node %d param: %d to %s", node, param, val_char); + break; + default: + abort(); + } + assert(res); + } while(node == 0 && iter.next() == 0); + + msg.assign("Success"); + return 0; +} + +template class Vector<SigMatch>; +#if __SUNPRO_CC != 0x560 +template bool SignalQueue::waitFor<SigMatch>(Vector<SigMatch>&, SigMatch*&, NdbApiSignal*&, unsigned); +#endif diff --git a/ndb/src/mgmsrv/MgmtSrvr.hpp b/ndb/src/mgmsrv/MgmtSrvr.hpp index 1d394a14857..b26eaeb4ab9 100644 --- a/ndb/src/mgmsrv/MgmtSrvr.hpp +++ b/ndb/src/mgmsrv/MgmtSrvr.hpp @@ -68,6 +68,22 @@ public: virtual void println_statistics(const BaseString &s) = 0; }; + // some compilers need all of this + class Allocated_resources; + friend class Allocated_resources; + class Allocated_resources { + public: + Allocated_resources(class MgmtSrvr &m); + ~Allocated_resources(); + // methods to reserve/allocate resources which + // will be freed when running destructor + void reserve_node(NodeId id); + bool is_reserved(NodeId nodeId) { return m_reserved_nodes.get(nodeId);} + private: + MgmtSrvr &m_mgmsrv; + NodeBitmask m_reserved_nodes; + }; + /** * Set a reference to the socket server. */ @@ -150,10 +166,12 @@ public: enum LogMode {In, Out, InOut, Off}; /* Constructor */ + MgmtSrvr(NodeId nodeId, /* Local nodeid */ const BaseString &config_filename, /* Where to save config */ const BaseString &ndb_config_filename, /* Ndb.cfg filename */ Config * config); + NodeId getOwnNodeId() const {return _ownNodeId;}; /** * Read (initial) config file, create TransporterFacade, @@ -448,6 +466,8 @@ public: * @return false if none found */ bool getNextNodeId(NodeId * _nodeId, enum ndb_mgm_node_type type) const ; + bool alloc_node_id(NodeId * _nodeId, enum ndb_mgm_node_type type, + struct sockaddr *client_addr, SOCKET_SIZE_TYPE *client_addr_len); /** * @@ -492,8 +512,14 @@ public: * @return statistic port number. */ int getStatPort() const; + /** + * Returns the port number. + * @return port number. + */ + int getPort() const; - + int setDbParameter(int node, int parameter, const char * value, BaseString&); + //************************************************************************** private: //************************************************************************** @@ -530,13 +556,14 @@ private: BaseString m_configFilename; BaseString m_localNdbConfigFilename; Uint32 m_nextConfigGenerationNumber; + + NodeBitmask m_reserved_nodes; + Allocated_resources m_allocated_resources; int _setVarReqResult; // The result of the SET_VAR_REQ response Statistics _statistics; // handleSTATISTICS_CONF store the result here, // and getStatistics reads it. - - //************************************************************************** // Specific signal handling methods //************************************************************************** diff --git a/ndb/src/mgmsrv/MgmtSrvrConfig.cpp b/ndb/src/mgmsrv/MgmtSrvrConfig.cpp index 10316bd2851..44c2aadd1e2 100644 --- a/ndb/src/mgmsrv/MgmtSrvrConfig.cpp +++ b/ndb/src/mgmsrv/MgmtSrvrConfig.cpp @@ -288,16 +288,15 @@ MgmtSrvr::readConfig() { Config * MgmtSrvr::fetchConfig() { - ConfigRetriever cr; + ConfigRetriever cr(NDB_VERSION, NODE_TYPE_MGM); cr.setLocalConfigFileName(m_localNdbConfigFilename.c_str()); - struct ndb_mgm_configuration * tmp = cr.getConfig(NDB_VERSION, - NODE_TYPE_MGM); + struct ndb_mgm_configuration * tmp = cr.getConfig(); if(tmp != 0){ Config * conf = new Config(); conf->m_configValues = tmp; return conf; } - + return 0; } diff --git a/ndb/src/mgmsrv/Services.cpp b/ndb/src/mgmsrv/Services.cpp index 739eef90c52..7bf408583de 100644 --- a/ndb/src/mgmsrv/Services.cpp +++ b/ndb/src/mgmsrv/Services.cpp @@ -14,7 +14,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include <string.h> +#include <ndb_global.h> #include <ctype.h> #include <uucode.h> @@ -31,6 +31,8 @@ #include "Services.hpp" +extern bool g_StopServer; + static const unsigned int MAX_READ_TIMEOUT = 1000 ; static const unsigned int MAX_WRITE_TIMEOUT = 100 ; @@ -121,6 +123,15 @@ ParserRow<MgmApiSession> commands[] = { MGM_ARG("version", Int, Mandatory, "Configuration version number"), MGM_ARG("node", Int, Optional, "Node ID"), + MGM_CMD("get nodeid", &MgmApiSession::get_nodeid, ""), + MGM_ARG("version", Int, Mandatory, "Configuration version number"), + MGM_ARG("nodetype", Int, Mandatory, "Node type"), + MGM_ARG("transporter", String, Optional, "Transporter type"), + MGM_ARG("nodeid", Int, Optional, "Node ID"), + MGM_ARG("user", String, Mandatory, "Password"), + MGM_ARG("password", String, Mandatory, "Password"), + MGM_ARG("public key", String, Mandatory, "Public key"), + MGM_CMD("get version", &MgmApiSession::getVersion, ""), MGM_CMD("get status", &MgmApiSession::getStatus, ""), @@ -216,6 +227,16 @@ ParserRow<MgmApiSession> commands[] = { MGM_ARG("parameter", String, Mandatory, "Parameter"), MGM_ARG("value", String, Mandatory, "Value"), + MGM_CMD("config lock", &MgmApiSession::configLock, ""), + + MGM_CMD("config unlock", &MgmApiSession::configUnlock, ""), + MGM_ARG("commit", Int, Mandatory, "Commit changes"), + + MGM_CMD("set parameter", &MgmApiSession::setParameter, ""), + MGM_ARG("node", String, Mandatory, "Node"), + MGM_ARG("parameter", String, Mandatory, "Parameter"), + MGM_ARG("value", String, Mandatory, "Value"), + MGM_END() }; @@ -224,6 +245,19 @@ MgmApiSession::MgmApiSession(class MgmtSrvr & mgm, NDB_SOCKET_TYPE sock) m_input = new SocketInputStream(sock); m_output = new SocketOutputStream(sock); m_parser = new Parser_t(commands, *m_input, true, true, true); + m_allocated_resources= new MgmtSrvr::Allocated_resources(m_mgmsrv); +} + +MgmApiSession::~MgmApiSession() +{ + if (m_input) + delete m_input; + if (m_output) + delete m_output; + if (m_parser) + delete m_parser; + if (m_allocated_resources) + delete m_allocated_resources; } void @@ -333,6 +367,82 @@ backward(const char * base, const Properties* reply){ } void +MgmApiSession::get_nodeid(Parser_t::Context &, + const class Properties &args) +{ + const char *cmd= "get nodeid reply"; + Uint32 version, nodeid= 0, nodetype= 0xff; + const char * transporter; + const char * user; + const char * password; + const char * public_key; + + args.get("version", &version); + args.get("nodetype", &nodetype); + args.get("transporter", &transporter); + args.get("nodeid", &nodeid); + args.get("user", &user); + args.get("password", &password); + args.get("public key", &public_key); + + bool compatible; + switch (nodetype) { + case NODE_TYPE_MGM: + case NODE_TYPE_API: + compatible = ndbCompatible_mgmt_api(NDB_VERSION, version); + break; + case NODE_TYPE_DB: + compatible = ndbCompatible_mgmt_ndb(NDB_VERSION, version); + break; + default: + m_output->println(cmd); + m_output->println("result: unknown nodetype %d", nodetype); + m_output->println(""); + return; + } + + struct sockaddr addr; + SOCKET_SIZE_TYPE addrlen= sizeof(addr); + int r = getpeername(m_socket, &addr, &addrlen); + if (r != 0 ) { + m_output->println(cmd); + m_output->println("result: getpeername(%d) failed, err= %d", m_socket, r); + m_output->println(""); + return; + } + + NodeId tmp= nodeid; + if(tmp == 0 || !m_allocated_resources->is_reserved(tmp)){ + if (!m_mgmsrv.alloc_node_id(&tmp, (enum ndb_mgm_node_type)nodetype, + &addr, &addrlen)){ + m_output->println(cmd); + m_output->println("result: no free nodeid %d for nodetype %d", + nodeid, nodetype); + m_output->println(""); + return; + } + } + +#if 0 + if (!compatible){ + m_output->println(cmd); + m_output->println("result: incompatible version mgmt 0x%x and node 0x%x", + NDB_VERSION, version); + m_output->println(""); + return; + } +#endif + + m_output->println(cmd); + m_output->println("nodeid: %u", tmp); + m_output->println("result: Ok"); + m_output->println(""); + m_allocated_resources->reserve_node(tmp); + + return; +} + +void MgmApiSession::getConfig_common(Parser_t::Context &, const class Properties &args, bool compat) { @@ -432,7 +542,6 @@ MgmApiSession::getConfig_common(Parser_t::Context &, m_output->println("Content-Transfer-Encoding: base64"); m_output->println(""); m_output->println(str.c_str()); - m_output->println(""); return; } @@ -905,10 +1014,27 @@ MgmApiSession::stop(Parser<MgmApiSession>::Context &, nodes.push_back(atoi(p)); } + int stop_self= 0; + + for(size_t i=0; i < nodes.size(); i++) { + if (nodes[i] == m_mgmsrv.getOwnNodeId()) { + stop_self= 1; + if (i != nodes.size()-1) { + m_output->println("stop reply"); + m_output->println("result: server must be stopped last"); + m_output->println(""); + return; + } + } + } + int stopped = 0, result = 0; for(size_t i=0; i < nodes.size(); i++) - if((result = m_mgmsrv.stopNode(nodes[i], abort != 0)) == 0) + if (nodes[i] != m_mgmsrv.getOwnNodeId()) { + if((result = m_mgmsrv.stopNode(nodes[i], abort != 0)) == 0) + stopped++; + } else stopped++; m_output->println("stop reply"); @@ -918,6 +1044,9 @@ MgmApiSession::stop(Parser<MgmApiSession>::Context &, m_output->println("result: Ok"); m_output->println("stopped: %d", stopped); m_output->println(""); + + if (stop_self) + g_StopServer= true; } @@ -1119,7 +1248,8 @@ void MgmStatService::println_statistics(const BaseString &line){ MutexVector<NDB_SOCKET_TYPE> copy(m_sockets.size()); m_sockets.lock(); - for(int i = m_sockets.size() - 1; i >= 0; i--){ + int i; + for(i = m_sockets.size() - 1; i >= 0; i--){ if(println_socket(m_sockets[i], MAX_WRITE_TIMEOUT, line.c_str()) == -1){ copy.push_back(m_sockets[i]); m_sockets.erase(i, false); @@ -1127,7 +1257,7 @@ MgmStatService::println_statistics(const BaseString &line){ } m_sockets.unlock(); - for(int i = copy.size() - 1; i >= 0; i--){ + for(i = copy.size() - 1; i >= 0; i--){ NDB_CLOSE_SOCKET(copy[i]); copy.erase(i); } @@ -1142,5 +1272,28 @@ MgmStatService::stopSessions(){ NDB_CLOSE_SOCKET(m_sockets[i]); m_sockets.erase(i); } +} + +void +MgmApiSession::setParameter(Parser_t::Context &, + Properties const &args) { + BaseString node, param, value; + args.get("node", node); + args.get("parameter", param); + args.get("value", value); + BaseString result; + int ret = m_mgmsrv.setDbParameter(atoi(node.c_str()), + atoi(param.c_str()), + value.c_str(), + result); + + m_output->println("set parameter reply"); + m_output->println("message: %s", result.c_str()); + m_output->println("result: %d", ret); + m_output->println(""); } + +template class MutexVector<int>; +template class Vector<ParserRow<MgmApiSession> const*>; +template class Vector<unsigned short>; diff --git a/ndb/src/mgmsrv/Services.hpp b/ndb/src/mgmsrv/Services.hpp index 3690f1a5a93..9cf8b59be8f 100644 --- a/ndb/src/mgmsrv/Services.hpp +++ b/ndb/src/mgmsrv/Services.hpp @@ -36,6 +36,7 @@ private: InputStream *m_input; OutputStream *m_output; Parser_t *m_parser; + MgmtSrvr::Allocated_resources *m_allocated_resources; void getConfig_common(Parser_t::Context &ctx, const class Properties &args, @@ -43,6 +44,7 @@ private: public: MgmApiSession(class MgmtSrvr & mgm, NDB_SOCKET_TYPE sock); + virtual ~MgmApiSession(); void runSession(); void getStatPort(Parser_t::Context &ctx, const class Properties &args); @@ -51,6 +53,7 @@ public: void getConfig_old(Parser_t::Context &ctx); #endif /* MGM_GET_CONFIG_BACKWARDS_COMPAT */ + void get_nodeid(Parser_t::Context &ctx, const class Properties &args); void getVersion(Parser_t::Context &ctx, const class Properties &args); void getStatus(Parser_t::Context &ctx, const class Properties &args); void getInfoClusterLog(Parser_t::Context &ctx, const class Properties &args); @@ -79,6 +82,8 @@ public: void configUnlock(Parser_t::Context &ctx, const class Properties &args); void configChange(Parser_t::Context &ctx, const class Properties &args); + void setParameter(Parser_t::Context &ctx, const class Properties &args); + void repCommand(Parser_t::Context &ctx, const class Properties &args); }; diff --git a/ndb/src/mgmsrv/main.cpp b/ndb/src/mgmsrv/main.cpp index d9eb0001c44..719226b51df 100644 --- a/ndb/src/mgmsrv/main.cpp +++ b/ndb/src/mgmsrv/main.cpp @@ -16,11 +16,9 @@ #include <ndb_global.h> -#include <signal.h> - #include "MgmtSrvr.hpp" #include "EventLogger.hpp" -#include "Config.hpp" +#include <Config.hpp> #include "InitConfigFileParser.hpp" #include <SocketServer.hpp> #include "Services.hpp" @@ -37,6 +35,8 @@ #include <mgmapi_config_parameters.h> #include <getarg.h> +#include <NdbAutoPtr.hpp> + #if defined NDB_OSE || defined NDB_SOFTOSE #include <efs.h> #else @@ -88,7 +88,6 @@ static MgmGlobals glob; ******************************************************************************/ static bool readLocalConfig(); static bool readGlobalConfig(); -static bool setPortNo(); /** * Global variables @@ -100,16 +99,16 @@ extern int global_mgmt_server_check; int _print_version = 0; struct getargs args[] = { - { "version", 0, arg_flag, &_print_version, - "Print versions"}, - { NULL, 'c', arg_string, &glob.config_filename, - "Running cluster configuration file", "filename" }, - { NULL, 'd', arg_flag, &glob.daemon, - "Daemon mode" }, + { "version", 'v', arg_flag, &_print_version, + "Print ndb_mgmd version"}, + { "config-file", 'c', arg_string, &glob.config_filename, + "Specify cluster configuration file", "filename" }, + { "daemon", 'd', arg_flag, &glob.daemon, + "Run ndb_mgmd in daemon mode" }, { NULL, 'l', arg_string, &glob.local_config_filename, - "Local configuration file (Ndb.cfg)", + "Specify configuration file connect string (will default use Ndb.cfg if available)", "filename" }, - { NULL, 'n', arg_flag, &glob.non_interactive, + { "nodaemon", 'n', arg_flag, &glob.non_interactive, "Don't run as daemon, but don't read from stdin", "non-interactive" } }; @@ -146,7 +145,9 @@ NDB_MAIN(mgmsrv){ exit(1); } glob.socketServer = new SocketServer(); + MgmApiService * mapi = new MgmApiService(); + MgmStatService * mstat = new MgmStatService(); /**************************** @@ -157,16 +158,34 @@ NDB_MAIN(mgmsrv){ if (!readGlobalConfig()) goto error_end; - if (!setPortNo()) + glob.mgmObject = new MgmtSrvr(glob.localNodeId, + BaseString(glob.config_filename), + BaseString(glob.local_config_filename == 0 ? + "" : glob.local_config_filename), + glob.cluster_config); + + glob.cluster_config = 0; + glob.localNodeId= glob.mgmObject->getOwnNodeId(); + + if (glob.localNodeId == 0) { goto error_end; - + } + + glob.port= glob.mgmObject->getPort(); + + if (glob.port == 0) + goto error_end; + + glob.interface_name = 0; + glob.use_specific_ip = false; + if(!glob.use_specific_ip){ if(!glob.socketServer->tryBind(glob.port, glob.interface_name)){ ndbout_c("Unable to setup port: %s:%d!\n" "Please check if the port is already used,\n" "(perhaps a mgmtsrvr is already running),\n" "and if you are executing on the correct computer", - glob.interface_name, glob.port); + (glob.interface_name ? glob.interface_name : "*"), glob.port); goto error_end; } free(glob.interface_name); @@ -190,31 +209,25 @@ NDB_MAIN(mgmsrv){ goto error_end; } - glob.mgmObject = new MgmtSrvr(glob.localNodeId, - BaseString(glob.config_filename), - BaseString(glob.local_config_filename == 0 ? "" : glob.local_config_filename), - glob.cluster_config); - - glob.cluster_config = 0; - if(!glob.mgmObject->check_start()){ - ndbout_c("Unable to start management server."); + ndbout_c("Unable to check start management server."); ndbout_c("Probably caused by illegal initial configuration file."); goto error_end; } if (glob.daemon) { // Become a daemon - char homePath[255],lockfile[255], logfile[255]; - NdbConfig_HomePath(homePath, 255); - snprintf(lockfile, 255, "%snode%d.pid", homePath, glob.localNodeId); - snprintf(logfile, 255, "%snode%d.out", homePath, glob.localNodeId); + char *lockfile= NdbConfig_PidFileName(glob.localNodeId); + char *logfile= NdbConfig_StdoutFileName(glob.localNodeId); + NdbAutoPtr<char> tmp_aptr1(lockfile), tmp_aptr2(logfile); + if (NdbDaemon_Make(lockfile, logfile, 0) == -1) { ndbout << "Cannot become daemon: " << NdbDaemon_ErrorText << endl; return 1; } } + signal(SIGPIPE, SIG_IGN); if(!glob.mgmObject->start()){ ndbout_c("Unable to start management server."); ndbout_c("Probably caused by illegal initial configuration file."); @@ -233,8 +246,8 @@ NDB_MAIN(mgmsrv){ ndbout_c(msg); g_EventLogger.info(msg); - snprintf(msg, 256, "Command port: %d, Statistics port: %d", - glob.port, glob.port_stats); + snprintf(msg, 256, "Id: %d, Command port: %d, Statistics port: %d", + glob.localNodeId, glob.port, glob.port_stats); ndbout_c(msg); g_EventLogger.info(msg); @@ -298,14 +311,11 @@ MgmGlobals::~MgmGlobals(){ static bool readLocalConfig(){ // Read local config file - ConfigRetriever cr; - cr.setLocalConfigFileName(glob.local_config_filename); - int nodeid = cr.init(true); - if(nodeid == -1){ + LocalConfig lc; + if(!lc.init(glob.local_config_filename)) return false; - } - glob.localNodeId = (NodeId)nodeid; + glob.localNodeId = lc._ownNodeId; return true; } @@ -328,123 +338,7 @@ readGlobalConfig() { InitConfigFileParser parser; glob.cluster_config = parser.parseConfig(glob.config_filename); if(glob.cluster_config == 0){ - /** - * Try to get configuration from other MGM server - * Note: Only new format - */ - glob.cluster_config = new Config(); - - ConfigRetriever cr; - cr.setLocalConfigFileName(glob.local_config_filename); - glob.cluster_config->m_configValues = cr.getConfig(NDB_VERSION, - NODE_TYPE_MGM); - if (glob.cluster_config->m_configValues == NULL) - return false; - } - return true; -} - -/** - * @fn setPortNo - * @param glob : Global variables - * @return true if success, false otherwise. - * - * Port number: - * 2. Use port number from global configuration file - * 4. Use port number for statistics from global configuration file - */ -static bool -setPortNo(){ - const Properties *mgmProps; - - ndb_mgm_configuration_iterator * iter = - ndb_mgm_create_configuration_iterator(glob.cluster_config->m_configValues, - CFG_SECTION_NODE); - if(iter == 0) - return false; - - if(ndb_mgm_find(iter, CFG_NODE_ID, glob.localNodeId) != 0){ - ndbout << "Could not retrieve configuration for Node " - << glob.localNodeId << " in config file." << endl - << "Have you set correct NodeId for this node?" << endl; - ndb_mgm_destroy_iterator(iter); - return false; - } - - unsigned type; - if(ndb_mgm_get_int_parameter(iter, CFG_TYPE_OF_SECTION, &type) != 0 || - type != NODE_TYPE_MGM){ - ndbout << "Local node id " << glob.localNodeId - << " is not defined as management server" << endl - << "Have you set correct NodeId for this node?" << endl; - return false; - } - - /************ - * Set Port * - ************/ - Uint32 tmp = 0; - if(ndb_mgm_get_int_parameter(iter, CFG_MGM_PORT, &tmp) != 0){ - ndbout << "Could not find PortNumber in the configuration file." << endl; - return false; - } - glob.port = tmp; - - /***************** - * Set Stat Port * - *****************/ -#if 0 - if (!mgmProps->get("PortNumberStats", &tmp)){ - ndbout << "Could not find PortNumberStats in the configuration file." - << endl; return false; } - glob.port_stats = tmp; -#endif - -#if 0 - const char * host; - if(ndb_mgm_get_string_parameter(iter, mgmProps->get("ExecuteOnComputer", host)){ - ndbout << "Failed to find \"ExecuteOnComputer\" for my node" << endl; - ndbout << "Unable to verify own hostname" << endl; - return false; - } - - const char * hostname; - { - const Properties * p; - char buf[255]; - snprintf(buf, sizeof(buf), "Computer_%s", host.c_str()); - if(!glob.cluster_config->get(buf, &p)){ - ndbout << "Failed to find computer " << host << " in config" << endl; - ndbout << "Unable to verify own hostname" << endl; - return false; - } - if(!p->get("HostName", &hostname)){ - ndbout << "Failed to find \"HostName\" for computer " << host - << " in config" << endl; - ndbout << "Unable to verify own hostname" << endl; - return false; - } - if(NdbHost_GetHostName(buf) != 0){ - ndbout << "Unable to get own hostname" << endl; - ndbout << "Unable to verify own hostname" << endl; - return false; - } - } - - const char * ip_address; - if(mgmProps->get("IpAddress", &ip_address)){ - glob.use_specific_ip = true; - glob.interface_name = strdup(ip_address); - return true; - } - - glob.interface_name = strdup(hostname); -#endif - - glob.interface_name = 0; - glob.use_specific_ip = false; - return true; } diff --git a/ndb/src/ndbapi/ClusterMgr.cpp b/ndb/src/ndbapi/ClusterMgr.cpp index b26d550fe31..b9947fcf0e7 100644 --- a/ndb/src/ndbapi/ClusterMgr.cpp +++ b/ndb/src/ndbapi/ClusterMgr.cpp @@ -295,6 +295,7 @@ ClusterMgr::execAPI_REGREQ(const Uint32 * theData){ } int global_mgmt_server_check = 0; // set to one in mgmtsrvr main; + void ClusterMgr::execAPI_REGCONF(const Uint32 * theData){ const ApiRegConf * const apiRegConf = (ApiRegConf *)&theData[0]; @@ -309,6 +310,7 @@ ClusterMgr::execAPI_REGCONF(const Uint32 * theData){ Node & node = theNodes[nodeId]; assert(node.defined == true); assert(node.connected == true); + if(node.m_info.m_version != apiRegConf->version){ node.m_info.m_version = apiRegConf->version; if (global_mgmt_server_check == 1) diff --git a/ndb/src/ndbapi/DictCache.cpp b/ndb/src/ndbapi/DictCache.cpp index f6f2106f2aa..5f620f77906 100644 --- a/ndb/src/ndbapi/DictCache.cpp +++ b/ndb/src/ndbapi/DictCache.cpp @@ -157,6 +157,7 @@ GlobalDictCache::put(const char * name, NdbTableImpl * tab) void GlobalDictCache::drop(NdbTableImpl * tab) { + unsigned i; const Uint32 len = strlen(tab->m_internalName.c_str()); Vector<TableVersion> * vers = m_tableHash.getData(tab->m_internalName.c_str(), len); @@ -173,7 +174,7 @@ GlobalDictCache::drop(NdbTableImpl * tab) abort(); } - for(unsigned i = 0; i < sz; i++){ + for(i = 0; i < sz; i++){ TableVersion & ver = (* vers)[i]; if(ver.m_impl == tab){ if(ver.m_refCount == 0 || ver.m_status == RETREIVING || @@ -193,7 +194,7 @@ GlobalDictCache::drop(NdbTableImpl * tab) } } - for(unsigned i = 0; i<sz; i++){ + for(i = 0; i<sz; i++){ TableVersion & ver = (* vers)[i]; ndbout_c("%d: version: %d refCount: %d status: %d impl: %p", i, ver.m_version, ver.m_refCount, ver.m_status, ver.m_impl); @@ -204,6 +205,7 @@ GlobalDictCache::drop(NdbTableImpl * tab) void GlobalDictCache::release(NdbTableImpl * tab){ + unsigned i; const Uint32 len = strlen(tab->m_internalName.c_str()); Vector<TableVersion> * vers = m_tableHash.getData(tab->m_internalName.c_str(), len); @@ -220,7 +222,7 @@ GlobalDictCache::release(NdbTableImpl * tab){ abort(); } - for(unsigned i = 0; i < sz; i++){ + for(i = 0; i < sz; i++){ TableVersion & ver = (* vers)[i]; if(ver.m_impl == tab){ if(ver.m_refCount == 0 || ver.m_status == RETREIVING || @@ -235,7 +237,7 @@ GlobalDictCache::release(NdbTableImpl * tab){ } } - for(unsigned i = 0; i<sz; i++){ + for(i = 0; i<sz; i++){ TableVersion & ver = (* vers)[i]; ndbout_c("%d: version: %d refCount: %d status: %d impl: %p", i, ver.m_version, ver.m_refCount, ver.m_status, ver.m_impl); @@ -244,3 +246,4 @@ GlobalDictCache::release(NdbTableImpl * tab){ abort(); } +template class Vector<GlobalDictCache::TableVersion>; diff --git a/ndb/src/ndbapi/Makefile.am b/ndb/src/ndbapi/Makefile.am index 2ec58ab6e85..14badb0c62f 100644 --- a/ndb/src/ndbapi/Makefile.am +++ b/ndb/src/ndbapi/Makefile.am @@ -23,9 +23,7 @@ libndbapi_la_SOURCES = \ NdbOperationDefine.cpp \ NdbOperationExec.cpp \ NdbResultSet.cpp \ - NdbCursorOperation.cpp \ - NdbScanReceiver.cpp NdbScanOperation.cpp \ - NdbScanFilter.cpp \ + NdbScanOperation.cpp NdbScanFilter.cpp \ NdbIndexOperation.cpp \ NdbEventOperation.cpp \ NdbEventOperationImpl.cpp \ diff --git a/ndb/src/ndbapi/Makefile_old b/ndb/src/ndbapi/Makefile_old index c2bb0189a7f..54de9ba96f4 100644 --- a/ndb/src/ndbapi/Makefile_old +++ b/ndb/src/ndbapi/Makefile_old @@ -34,31 +34,24 @@ 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 NdbBlob.cpp include $(NDB_TOP)/Epilogue.mk diff --git a/ndb/src/ndbapi/Ndb.cpp b/ndb/src/ndbapi/Ndb.cpp index fe7260c4693..f09a7481d2d 100644 --- a/ndb/src/ndbapi/Ndb.cpp +++ b/ndb/src/ndbapi/Ndb.cpp @@ -154,26 +154,22 @@ Ndb::NDB_connect(Uint32 tNode) tNdbCon->Status(NdbConnection::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() == NdbConnection::Connected)) { //************************************************ // Send and receive was successful @@ -463,9 +459,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) { @@ -473,44 +469,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 @@ -522,7 +507,7 @@ Ndb::closeTransaction(NdbConnection* aConnection) #endif return; } - + if (aConnection->theReleaseOnClose == false) { /** * Put it back in idle list for that node @@ -729,9 +714,10 @@ Ndb::getNodeId() } /**************************************************************************** -Uint64 getTupleIdFromNdb( Uint32 aTableId ); +Uint64 getTupleIdFromNdb( Uint32 aTableId, Uint32 cacheSize ); Parameters: aTableId : The TableId. + cacheSize: Prefetch this many values Remark: Returns a new TupleId to the application. The TupleId comes from SYSTAB_0 where SYSKEY_0 = TableId. It is initialized to (TableId << 48) + 1 in NdbcntrMain.cpp. @@ -750,8 +736,19 @@ Ndb::getAutoIncrementValue(const char* aTableName, Uint32 cacheSize) return tupleId; } +Uint64 +Ndb::getAutoIncrementValue(NdbDictionary::Table * aTable, Uint32 cacheSize) +{ + DEBUG_TRACE("getAutoIncrementValue"); + if (aTable == 0) + return ~0; + const NdbTableImpl* table = & NdbTableImpl::getImpl(*aTable); + Uint64 tupleId = getTupleIdFromNdb(table->m_tableId, cacheSize); + return tupleId; +} + Uint64 -Ndb::getTupleIdFromNdb(const char* aTableName, Uint32 cacheSize ) +Ndb::getTupleIdFromNdb(const char* aTableName, Uint32 cacheSize) { const NdbTableImpl* table = theDictionary->getTable(aTableName); if (table == 0) @@ -760,7 +757,7 @@ Ndb::getTupleIdFromNdb(const char* aTableName, Uint32 cacheSize ) } Uint64 -Ndb::getTupleIdFromNdb(Uint32 aTableId, Uint32 cacheSize ) +Ndb::getTupleIdFromNdb(Uint32 aTableId, Uint32 cacheSize) { if ( theFirstTupleId[aTableId] != theLastTupleId[aTableId] ) { @@ -773,31 +770,90 @@ Ndb::getTupleIdFromNdb(Uint32 aTableId, Uint32 cacheSize ) } } +Uint64 +Ndb::readAutoIncrementValue(const char* aTableName) +{ + DEBUG_TRACE("readtAutoIncrementValue"); + const NdbTableImpl* table = theDictionary->getTable(aTableName); + if (table == 0) + return ~0; + Uint64 tupleId = readTupleIdFromNdb(table->m_tableId); + return tupleId; +} + +Uint64 +Ndb::readAutoIncrementValue(NdbDictionary::Table * aTable) +{ + DEBUG_TRACE("readtAutoIncrementValue"); + if (aTable == 0) + return ~0; + const NdbTableImpl* table = & NdbTableImpl::getImpl(*aTable); + Uint64 tupleId = readTupleIdFromNdb(table->m_tableId); + return tupleId; +} + +Uint64 +Ndb::readTupleIdFromNdb(Uint32 aTableId) +{ + if ( theFirstTupleId[aTableId] == theLastTupleId[aTableId] ) + // Cache is empty, check next in database + return opTupleIdOnNdb(aTableId, 0, 3); + + return theFirstTupleId[aTableId] + 1; +} + bool -Ndb::setAutoIncrementValue(const char* aTableName, Uint64 val) +Ndb::setAutoIncrementValue(const char* aTableName, Uint64 val, bool increase) { DEBUG_TRACE("setAutoIncrementValue " << val); const NdbTableImpl* table = theDictionary->getTable(aTableName); if (table == 0) return false; - return setTupleIdInNdb(table->m_tableId, val); + return setTupleIdInNdb(table->m_tableId, val, increase); +} + +bool +Ndb::setAutoIncrementValue(NdbDictionary::Table * aTable, Uint64 val, bool increase) +{ + DEBUG_TRACE("setAutoIncrementValue " << val); + if (aTable == 0) + return ~0; + const NdbTableImpl* table = & NdbTableImpl::getImpl(*aTable); + return setTupleIdInNdb(table->m_tableId, val, increase); } bool -Ndb::setTupleIdInNdb(const char* aTableName, Uint64 val ) +Ndb::setTupleIdInNdb(const char* aTableName, Uint64 val, bool increase ) { DEBUG_TRACE("setTupleIdInNdb"); const NdbTableImpl* table = theDictionary->getTable(aTableName); if (table == 0) return false; - return setTupleIdInNdb(table->m_tableId, val); + return setTupleIdInNdb(table->m_tableId, val, increase); } bool -Ndb::setTupleIdInNdb(Uint32 aTableId, Uint64 val ) +Ndb::setTupleIdInNdb(Uint32 aTableId, Uint64 val, bool increase ) { DEBUG_TRACE("setTupleIdInNdb"); - return (opTupleIdOnNdb(aTableId, val, 1) == val); + if (increase) + { + if (theFirstTupleId[aTableId] != theLastTupleId[aTableId]) + { + // We have a cache sequence + if (val <= theFirstTupleId[aTableId]+1) + return false; + if (val <= theLastTupleId[aTableId]) + { + theFirstTupleId[aTableId] = val - 1; + return true; + } + // else continue; + } + return (opTupleIdOnNdb(aTableId, val, 2) == val); + } + else + return (opTupleIdOnNdb(aTableId, val, 1) == val); } Uint64 @@ -809,7 +865,7 @@ Ndb::opTupleIdOnNdb(Uint32 aTableId, Uint64 opValue, Uint32 op) NdbOperation* tOperation; Uint64 tValue; NdbRecAttr* tRecAttrResult; - + int result; Uint64 ret; CHECK_STATUS_MACRO_ZERO; @@ -835,15 +891,7 @@ Ndb::opTupleIdOnNdb(Uint32 aTableId, Uint64 opValue, Uint32 op) case 0: tOperation->interpretedUpdateTuple(); tOperation->equal("SYSKEY_0", aTableId ); - { -#ifdef WORDS_BIGENDIAN - Uint64 cacheSize64 = opValue; // XXX interpreter bug on Uint32 - tOperation->incValue("NEXTID", cacheSize64); -#else - Uint32 cacheSize32 = opValue; // XXX for little-endian - tOperation->incValue("NEXTID", cacheSize32); -#endif - } + tOperation->incValue("NEXTID", opValue); tRecAttrResult = tOperation->getValue("NEXTID"); if (tConnection->execute( Commit ) == -1 ) @@ -863,10 +911,40 @@ Ndb::opTupleIdOnNdb(Uint32 aTableId, Uint64 opValue, Uint32 op) if (tConnection->execute( Commit ) == -1 ) goto error_handler; - theFirstTupleId[aTableId] = ~0; - theLastTupleId[aTableId] = ~0; + theFirstTupleId[aTableId] = ~(Uint64)0; + theLastTupleId[aTableId] = ~(Uint64)0; ret = opValue; break; + case 2: + tOperation->interpretedUpdateTuple(); + tOperation->equal("SYSKEY_0", aTableId ); + tOperation->load_const_u64(1, opValue); + tOperation->read_attr("NEXTID", 2); + tOperation->branch_le(2, 1, 0); + tOperation->write_attr("NEXTID", 1); + tOperation->interpret_exit_ok(); + tOperation->def_label(0); + tOperation->interpret_exit_nok(9999); + + if ( (result = tConnection->execute( Commit )) == -1 ) + goto error_handler; + + if (result == 9999) + ret = ~(Uint64)0; + else + { + theFirstTupleId[aTableId] = theLastTupleId[aTableId] = opValue - 1; + ret = opValue; + } + break; + case 3: + tOperation->readTuple(); + tOperation->equal("SYSKEY_0", aTableId ); + tRecAttrResult = tOperation->getValue("NEXTID"); + if (tConnection->execute( Commit ) == -1 ) + goto error_handler; + ret = tRecAttrResult->u_64_value(); + break; default: goto error_handler; } @@ -973,13 +1051,13 @@ Ndb::StartTransactionNodeSelectionData::init(Uint32 noOfNodes, */ { fragment2PrimaryNodeMap = new Uint32[noOfFragments]; - - for(Uint32 i = 0; i<noOfNodes; i++){ + Uint32 i; + for(i = 0; i<noOfNodes; i++){ fragment2PrimaryNodeMap[i] = nodeIds[i]; } // Sort them (bubble sort) - for(Uint32 i = 0; i<noOfNodes-1; i++) + for(i = 0; i<noOfNodes-1; i++) for(Uint32 j = i+1; j<noOfNodes; j++) if(fragment2PrimaryNodeMap[i] > fragment2PrimaryNodeMap[j]){ Uint32 tmp = fragment2PrimaryNodeMap[i]; @@ -987,7 +1065,7 @@ Ndb::StartTransactionNodeSelectionData::init(Uint32 noOfNodes, fragment2PrimaryNodeMap[j] = tmp; } - for(Uint32 i = 0; i<noOfNodes; i++){ + for(i = 0; i<noOfNodes; i++){ fragment2PrimaryNodeMap[i+noOfNodes] = fragment2PrimaryNodeMap[i]; } } diff --git a/ndb/src/ndbapi/NdbApiSignal.cpp b/ndb/src/ndbapi/NdbApiSignal.cpp index a44937cd398..6f5e1e50d2c 100644 --- a/ndb/src/ndbapi/NdbApiSignal.cpp +++ b/ndb/src/ndbapi/NdbApiSignal.cpp @@ -15,18 +15,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/****************************************************************************** -Name: NdbApiSignal.C -Include: -Link: -Author: UABMNST Mona Natterkvist UAB/B/SD -Date: 970829 -Version: 0.1 -Description: Interface between TIS and NDB -Documentation: -Adjust: 971114 UABMNST First version. - 000705 QABANAB Update of Protocol2 -******************************************************************************/ #include "API.hpp" #include "NdbApiSignal.hpp" @@ -46,6 +34,7 @@ Adjust: 971114 UABMNST First version. #include <signaldata/IndxKeyInfo.hpp> #include <signaldata/IndxAttrInfo.hpp> #include <signaldata/TcHbRep.hpp> +#include <signaldata/ScanTab.hpp> #include <NdbOut.hpp> @@ -161,7 +150,7 @@ NdbApiSignal::setSignal(int aNdbSignalType) theTrace = TestOrd::TraceAPI; theReceiversBlockNumber = DBTC; theVerId_signalNumber = GSN_TCROLLBACKREQ; - theLength = 5; + theLength = 3; } break; @@ -188,16 +177,7 @@ NdbApiSignal::setSignal(int aNdbSignalType) theTrace = TestOrd::TraceAPI; theReceiversBlockNumber = DBTC; theVerId_signalNumber = GSN_SCAN_TABREQ; - theLength = 25; - } - break; - - case GSN_SCAN_TABINFO: - { - theTrace = TestOrd::TraceAPI; - theReceiversBlockNumber = DBTC; - theVerId_signalNumber = GSN_SCAN_TABINFO; - theLength = 17; + theLength = 9; // ScanTabReq::SignalLength; } break; diff --git a/ndb/src/ndbapi/NdbBlob.cpp b/ndb/src/ndbapi/NdbBlob.cpp index 8e067f770e8..7939f54d846 100644 --- a/ndb/src/ndbapi/NdbBlob.cpp +++ b/ndb/src/ndbapi/NdbBlob.cpp @@ -14,23 +14,25 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "Ndb.hpp" -#include "NdbDictionaryImpl.hpp" -#include "NdbConnection.hpp" -#include "NdbOperation.hpp" -#include "NdbIndexOperation.hpp" -#include "NdbRecAttr.hpp" -#include "NdbBlob.hpp" +#include <Ndb.hpp> +#include <NdbDictionaryImpl.hpp> +#include <NdbConnection.hpp> +#include <NdbOperation.hpp> +#include <NdbIndexOperation.hpp> +#include <NdbRecAttr.hpp> +#include <NdbBlob.hpp> +#include <NdbScanOperation.hpp> #ifdef NDB_BLOB_DEBUG #define DBG(x) \ do { \ static const char* p = getenv("NDB_BLOB_DEBUG"); \ if (p == 0 || *p == 0 || *p == '0') break; \ - const char* cname = theColumn == NULL ? "BLOB" : theColumn->m_name.c_str(); \ - ndbout << cname << " " << __LINE__ << " " << x << " " << *this << endl; \ + static char* prefix = "BLOB"; \ + const char* cname = theColumn == NULL ? "-" : theColumn->m_name.c_str(); \ + ndbout << prefix << " " << hex << (void*)this << " " << cname; \ + ndbout << " " << dec << __LINE__ << " " << x << " " << *this << endl; \ } while (0) -#define EXE() assert(theNdbCon->executeNoBlobs(NoCommit) == 0) #else #define DBG(x) #endif @@ -48,7 +50,7 @@ ndb_blob_debug(const Uint32* data, unsigned size) /* * Reading index table directly (as a table) is faster but there are - * bugs or limitations. Keep the code but make possible to choose. + * bugs or limitations. Keep the code and make possible to choose. */ static const bool g_ndb_blob_ok_to_read_index_table = false; @@ -81,7 +83,7 @@ NdbBlob::getBlobTableName(char* btname, const NdbTableImpl* t, const NdbColumnIm { assert(t != 0 && c != 0 && c->getBlobType()); memset(btname, 0, BlobTableNameSize); - sprintf(btname, "NDB$BLOB_%d_%d_%d", (int)t->m_tableId, (int)t->m_version, (int)c->m_attrId); + sprintf(btname, "NDB$BLOB_%d_%d", (int)t->m_tableId, (int)c->m_attrId); } void @@ -115,7 +117,7 @@ NdbBlob::getBlobTable(NdbTableImpl& bt, const NdbTableImpl* t, const NdbColumnIm case NdbDictionary::Column::Blob: bc.setType(NdbDictionary::Column::Binary); break; - case NdbDictionary::Column::Clob: + case NdbDictionary::Column::Text: bc.setType(NdbDictionary::Column::Char); break; default: @@ -138,12 +140,12 @@ void NdbBlob::init() { theState = Idle; - theBlobTableName[0] = 0; theNdb = NULL; theNdbCon = NULL; theNdbOp = NULL; theTable = NULL; theAccessTable = NULL; + theBlobTable = NULL; theColumn = NULL; theFillChar = 0; theInlineSize = 0; @@ -154,11 +156,13 @@ NdbBlob::init() theSetFlag = false; theSetBuf = NULL; theGetSetBytes = 0; + thePendingBlobOps = 0; + theActiveHook = NULL; + theActiveHookArg = NULL; theHead = NULL; theInlineData = NULL; theHeadInlineRecAttr = NULL; theHeadInlineUpdateFlag = false; - theNewPartFlag = false; theNullFlag = -1; theLength = 0; thePos = 0; @@ -269,7 +273,7 @@ NdbBlob::isScanOp() inline Uint32 NdbBlob::getPartNumber(Uint64 pos) { - assert(pos >= theInlineSize); + assert(thePartSize != 0 && pos >= theInlineSize); return (pos - theInlineSize) / thePartSize; } @@ -301,7 +305,7 @@ NdbBlob::getTableKeyValue(NdbOperation* anOp) assert(c != NULL); if (c->m_pk) { unsigned len = c->m_attrSize * c->m_arraySize; - if (anOp->getValue(c, (char*)&data[pos]) == NULL) { + if (anOp->getValue_impl(c, (char*)&data[pos]) == NULL) { setErrorCode(anOp); return -1; } @@ -321,10 +325,10 @@ int NdbBlob::setTableKeyValue(NdbOperation* anOp) { const Uint32* data = (const Uint32*)theKeyBuf.data; + DBG("setTableKeyValue key=" << ndb_blob_debug(data, theTable->m_sizeOfKeysInWords)); + const unsigned columns = theTable->m_columns.size(); unsigned pos = 0; - const unsigned size = theTable->m_columns.size(); - DBG("setTableKeyValue key=" << ndb_blob_debug(data, size)); - for (unsigned i = 0; i < size; i++) { + for (unsigned i = 0; i < columns; i++) { NdbColumnImpl* c = theTable->m_columns[i]; assert(c != NULL); if (c->m_pk) { @@ -344,10 +348,10 @@ int NdbBlob::setAccessKeyValue(NdbOperation* anOp) { const Uint32* data = (const Uint32*)theAccessKeyBuf.data; + DBG("setAccessKeyValue key=" << ndb_blob_debug(data, theAccessTable->m_sizeOfKeysInWords)); + const unsigned columns = theAccessTable->m_columns.size(); unsigned pos = 0; - const unsigned size = theAccessTable->m_columns.size(); - DBG("setAccessKeyValue key=" << ndb_blob_debug(data, size)); - for (unsigned i = 0; i < size; i++) { + for (unsigned i = 0; i < columns; i++) { NdbColumnImpl* c = theAccessTable->m_columns[i]; assert(c != NULL); if (c->m_pk) { @@ -382,7 +386,7 @@ int NdbBlob::getHeadInlineValue(NdbOperation* anOp) { DBG("getHeadInlineValue"); - theHeadInlineRecAttr = anOp->getValue(theColumn, theHeadInlineBuf.data); + theHeadInlineRecAttr = anOp->getValue_impl(theColumn, theHeadInlineBuf.data); if (theHeadInlineRecAttr == NULL) { setErrorCode(anOp); return -1; @@ -478,11 +482,27 @@ NdbBlob::setValue(const void* data, Uint32 bytes) return 0; } +// activation hook + +int +NdbBlob::setActiveHook(ActiveHook activeHook, void* arg) +{ + DBG("setActiveHook hook=" << hex << (void*)activeHook << " arg=" << hex << arg); + if (theState != Prepared) { + setErrorCode(ErrState); + return -1; + } + theActiveHook = activeHook; + theActiveHookArg = arg; + return 0; +} + // misc operations int NdbBlob::getNull(bool& isNull) { + DBG("getNull"); if (theState == Prepared && theSetFlag) { isNull = (theSetBuf == NULL); return 0; @@ -519,6 +539,7 @@ NdbBlob::setNull() int NdbBlob::getLength(Uint64& len) { + DBG("getLength"); if (theState == Prepared && theSetFlag) { len = theGetSetBytes; return 0; @@ -534,17 +555,17 @@ NdbBlob::getLength(Uint64& len) int NdbBlob::truncate(Uint64 length) { - DBG("truncate kength=" << length); + DBG("truncate length=" << length); if (theNullFlag == -1) { setErrorCode(ErrState); return -1; } if (theLength > length) { - if (length >= theInlineSize) { - Uint32 part1 = getPartNumber(length); + if (length > theInlineSize) { + Uint32 part1 = getPartNumber(length - 1); Uint32 part2 = getPartNumber(theLength - 1); assert(part2 >= part1); - if (deleteParts(part1, part2 - part1) == -1) + if (part2 > part1 && deleteParts(part1 + 1, part2 - part1) == -1) return -1; } else { if (deleteParts(0, getPartCount()) == -1) @@ -559,6 +580,7 @@ NdbBlob::truncate(Uint64 length) int NdbBlob::getPos(Uint64& pos) { + DBG("getPos"); if (theNullFlag == -1) { setErrorCode(ErrState); return -1; @@ -570,6 +592,7 @@ NdbBlob::getPos(Uint64& pos) int NdbBlob::setPos(Uint64 pos) { + DBG("setPos pos=" << pos); if (theNullFlag == -1) { setErrorCode(ErrState); return -1; @@ -628,6 +651,10 @@ NdbBlob::readDataPrivate(Uint64 pos, char* buf, Uint32& bytes) len -= n; } } + if (len > 0 && thePartSize == 0) { + setErrorCode(ErrSeek); + return -1; + } if (len > 0) { assert(pos >= theInlineSize); Uint32 off = (pos - theInlineSize) % thePartSize; @@ -637,11 +664,10 @@ NdbBlob::readDataPrivate(Uint64 pos, char* buf, Uint32& bytes) Uint32 part = (pos - theInlineSize) / thePartSize; if (readParts(thePartBuf.data, part, 1) == -1) return -1; - DBG("force execute"); - if (theNdbCon->executeNoBlobs(NoCommit) == -1) { - setErrorCode(theNdbOp); + // need result now + DBG("execute pending part reads"); + if (executePendingBlobReads() == -1) return -1; - } Uint32 n = thePartSize - off; if (n > len) n = len; @@ -672,11 +698,10 @@ NdbBlob::readDataPrivate(Uint64 pos, char* buf, Uint32& bytes) Uint32 part = (pos - theInlineSize) / thePartSize; if (readParts(thePartBuf.data, part, 1) == -1) return -1; - DBG("force execute"); - if (theNdbCon->executeNoBlobs(NoCommit) == -1) { - setErrorCode(theNdbOp); + // need result now + DBG("execute pending part reads"); + if (executePendingBlobReads() == -1) return -1; - } memcpy(buf, thePartBuf.data, len); Uint32 n = len; pos += n; @@ -735,29 +760,27 @@ NdbBlob::writeDataPrivate(Uint64 pos, const char* buf, Uint32 bytes) len -= n; } } + if (len > 0 && thePartSize == 0) { + setErrorCode(ErrSeek); + return -1; + } if (len > 0) { assert(pos >= theInlineSize); Uint32 off = (pos - theInlineSize) % thePartSize; // partial first block if (off != 0) { DBG("partial first block pos=" << pos << " len=" << len); - if (theNewPartFlag) { - // must flush insert to guarantee read - DBG("force execute"); - if (theNdbCon->executeNoBlobs(NoCommit) == -1) { - setErrorCode(theNdbOp); - return -1; - } - theNewPartFlag = false; - } + // flush writes to guarantee correct read + DBG("execute pending part writes"); + if (executePendingBlobWrites() == -1) + return -1; Uint32 part = (pos - theInlineSize) / thePartSize; if (readParts(thePartBuf.data, part, 1) == -1) return -1; - DBG("force execute"); - if (theNdbCon->executeNoBlobs(NoCommit) == -1) { - setErrorCode(theNdbOp); + // need result now + DBG("execute pending part reafs"); + if (executePendingBlobReads() == -1) return -1; - } Uint32 n = thePartSize - off; if (n > len) { memset(thePartBuf.data + off + len, theFillChar, n - len); @@ -798,22 +821,16 @@ NdbBlob::writeDataPrivate(Uint64 pos, const char* buf, Uint32 bytes) assert((pos - theInlineSize) % thePartSize == 0 && len < thePartSize); Uint32 part = (pos - theInlineSize) / thePartSize; if (theLength > pos + len) { - if (theNewPartFlag) { - // must flush insert to guarantee read - DBG("force execute"); - if (theNdbCon->executeNoBlobs(NoCommit) == -1) { - setErrorCode(theNdbOp); - return -1; - } - theNewPartFlag = false; - } + // flush writes to guarantee correct read + DBG("execute pending part writes"); + if (executePendingBlobWrites() == -1) + return -1; if (readParts(thePartBuf.data, part, 1) == -1) return -1; - DBG("force execute"); - if (theNdbCon->executeNoBlobs(NoCommit) == -1) { - setErrorCode(theNdbOp); + // need result now + DBG("execute pending part reads"); + if (executePendingBlobReads() == -1) return -1; - } memcpy(thePartBuf.data, buf, len); if (updateParts(thePartBuf.data, part, 1) == -1) return -1; @@ -848,7 +865,7 @@ NdbBlob::readParts(char* buf, Uint32 part, Uint32 count) DBG("readParts part=" << part << " count=" << count); Uint32 n = 0; while (n < count) { - NdbOperation* tOp = theNdbCon->getNdbOperation(theBlobTableName); + NdbOperation* tOp = theNdbCon->getNdbOperation(theBlobTable); if (tOp == NULL || tOp->readTuple() == -1 || setPartKeyValue(tOp, part + n) == -1 || @@ -858,6 +875,8 @@ NdbBlob::readParts(char* buf, Uint32 part, Uint32 count) } buf += thePartSize; n++; + thePendingBlobOps |= (1 << NdbOperation::ReadRequest); + theNdbCon->thePendingBlobOps |= (1 << NdbOperation::ReadRequest); } return 0; } @@ -868,7 +887,7 @@ NdbBlob::insertParts(const char* buf, Uint32 part, Uint32 count) DBG("insertParts part=" << part << " count=" << count); Uint32 n = 0; while (n < count) { - NdbOperation* tOp = theNdbCon->getNdbOperation(theBlobTableName); + NdbOperation* tOp = theNdbCon->getNdbOperation(theBlobTable); if (tOp == NULL || tOp->insertTuple() == -1 || setPartKeyValue(tOp, part + n) == -1 || @@ -878,7 +897,8 @@ NdbBlob::insertParts(const char* buf, Uint32 part, Uint32 count) } buf += thePartSize; n++; - theNewPartFlag = true; + thePendingBlobOps |= (1 << NdbOperation::InsertRequest); + theNdbCon->thePendingBlobOps |= (1 << NdbOperation::InsertRequest); } return 0; } @@ -889,7 +909,7 @@ NdbBlob::updateParts(const char* buf, Uint32 part, Uint32 count) DBG("updateParts part=" << part << " count=" << count); Uint32 n = 0; while (n < count) { - NdbOperation* tOp = theNdbCon->getNdbOperation(theBlobTableName); + NdbOperation* tOp = theNdbCon->getNdbOperation(theBlobTable); if (tOp == NULL || tOp->updateTuple() == -1 || setPartKeyValue(tOp, part + n) == -1 || @@ -899,7 +919,8 @@ NdbBlob::updateParts(const char* buf, Uint32 part, Uint32 count) } buf += thePartSize; n++; - theNewPartFlag = true; + thePendingBlobOps |= (1 << NdbOperation::UpdateRequest); + theNdbCon->thePendingBlobOps |= (1 << NdbOperation::UpdateRequest); } return 0; } @@ -910,7 +931,7 @@ NdbBlob::deleteParts(Uint32 part, Uint32 count) DBG("deleteParts part=" << part << " count=" << count); Uint32 n = 0; while (n < count) { - NdbOperation* tOp = theNdbCon->getNdbOperation(theBlobTableName); + NdbOperation* tOp = theNdbCon->getNdbOperation(theBlobTable); if (tOp == NULL || tOp->deleteTuple() == -1 || setPartKeyValue(tOp, part + n) == -1) { @@ -918,6 +939,52 @@ NdbBlob::deleteParts(Uint32 part, Uint32 count) return -1; } n++; + thePendingBlobOps |= (1 << NdbOperation::DeleteRequest); + theNdbCon->thePendingBlobOps |= (1 << NdbOperation::DeleteRequest); + } + return 0; +} + +// pending ops + +int +NdbBlob::executePendingBlobReads() +{ + Uint8 flags = (1 << NdbOperation::ReadRequest); + if (thePendingBlobOps & flags) { + if (theNdbCon->executeNoBlobs(NoCommit) == -1) + return -1; + thePendingBlobOps = 0; + theNdbCon->thePendingBlobOps = 0; + } + return 0; +} + +int +NdbBlob::executePendingBlobWrites() +{ + Uint8 flags = 0xFF & ~(1 << NdbOperation::ReadRequest); + if (thePendingBlobOps & flags) { + if (theNdbCon->executeNoBlobs(NoCommit) == -1) + return -1; + thePendingBlobOps = 0; + theNdbCon->thePendingBlobOps = 0; + } + return 0; +} + +// callbacks + +int +NdbBlob::invokeActiveHook() +{ + DBG("invokeActiveHook"); + assert(theState == Active && theActiveHook != NULL); + int ret = (*theActiveHook)(this, theActiveHookArg); + DBG("invokeActiveHook ret=" << ret); + if (ret != 0) { + // no error is set on blob level + return -1; } return 0; } @@ -947,7 +1014,7 @@ NdbBlob::atPrepare(NdbConnection* aCon, NdbOperation* anOp, const NdbColumnImpl* partType = NdbDictionary::Column::Binary; theFillChar = 0x0; break; - case NdbDictionary::Column::Clob: + case NdbDictionary::Column::Text: partType = NdbDictionary::Column::Char; theFillChar = 0x20; break; @@ -959,22 +1026,21 @@ NdbBlob::atPrepare(NdbConnection* aCon, NdbOperation* anOp, const NdbColumnImpl* theInlineSize = theColumn->getInlineSize(); thePartSize = theColumn->getPartSize(); theStripeSize = theColumn->getStripeSize(); - // blob table sanity check + // sanity check assert((NDB_BLOB_HEAD_SIZE << 2) == sizeof(Head)); assert(theColumn->m_attrSize * theColumn->m_arraySize == sizeof(Head) + theInlineSize); - getBlobTableName(theBlobTableName, theTable, theColumn); - const NdbDictionary::Table* bt; - const NdbDictionary::Column* bc; - if (theInlineSize >= (1 << 16) || - thePartSize == 0 || - thePartSize >= (1 << 16) || - theStripeSize == 0 || - (bt = theNdb->theDictionary->getTable(theBlobTableName)) == NULL || - (bc = bt->getColumn("DATA")) == NULL || - bc->getType() != partType || - bc->getLength() != (int)thePartSize) { - setErrorCode(ErrTable); - return -1; + if (thePartSize > 0) { + const NdbDictionary::Table* bt = NULL; + const NdbDictionary::Column* bc = NULL; + if (theStripeSize == 0 || + (bt = theColumn->getBlobTable()) == NULL || + (bc = bt->getColumn("DATA")) == NULL || + bc->getType() != partType || + bc->getLength() != (int)thePartSize) { + setErrorCode(ErrTable); + return -1; + } + theBlobTable = &NdbTableImpl::getImpl(*bt); } // buffers theKeyBuf.alloc(theTable->m_sizeOfKeysInWords << 2); @@ -1060,7 +1126,7 @@ NdbBlob::preExecute(ExecType anExecType, bool& batch) Uint32 bytes = theGetSetBytes - theInlineSize; if (writeDataPrivate(pos, buf, bytes) == -1) return -1; - if (anExecType == Commit && theHeadInlineUpdateFlag) { + if (theHeadInlineUpdateFlag) { // add an operation to update head+inline NdbOperation* tOp = theNdbCon->getNdbOperation(theTable); if (tOp == NULL || @@ -1128,6 +1194,10 @@ NdbBlob::preExecute(ExecType anExecType, bool& batch) batch = true; } } + if (theActiveHook != NULL) { + // need blob head for callback + batch = true; + } DBG("preExecute out batch=" << batch); return 0; } @@ -1144,8 +1214,11 @@ NdbBlob::postExecute(ExecType anExecType) DBG("postExecute type=" << anExecType); if (theState == Invalid) return -1; - if (theState == Active) + if (theState == Active) { + setState(anExecType == NoCommit ? Active : Closed); + DBG("postExecute skip"); return 0; + } assert(theState == Prepared); assert(isKeyOp()); if (isIndexOp()) { @@ -1199,8 +1272,12 @@ NdbBlob::postExecute(ExecType anExecType) if (deleteParts(0, getPartCount()) == -1) return -1; } - theNewPartFlag = false; setState(anExecType == NoCommit ? Active : Closed); + // activation callback + if (theActiveHook != NULL) { + if (invokeActiveHook() == -1) + return -1; + } DBG("postExecute out"); return 0; } @@ -1250,7 +1327,7 @@ NdbBlob::atNextResult() // get primary key { Uint32* data = (Uint32*)theKeyBuf.data; unsigned size = theTable->m_sizeOfKeysInWords; - if (theNdbOp->getKeyFromKEYINFO20(data, size) == -1) { + if (((NdbScanOperation*)theNdbOp)->getKeyFromKEYINFO20(data, size) == -1) { setErrorCode(ErrUsage); return -1; } @@ -1274,20 +1351,18 @@ NdbBlob::atNextResult() Uint32 bytes = theGetSetBytes - theInlineSize; if (readDataPrivate(pos, buf, bytes) == -1) return -1; - // must also execute them - DBG("force execute"); - if (theNdbCon->executeNoBlobs(NoCommit) == -1) { - setErrorCode((NdbOperation*)0); - return -1; - } } } setState(Active); + // activation callback + if (theActiveHook != NULL) { + if (invokeActiveHook() == -1) + return -1; + } DBG("atNextResult out"); return 0; } - // misc const NdbDictionary::Column* @@ -1303,6 +1378,9 @@ NdbBlob::setErrorCode(int anErrorCode, bool invalidFlag) { DBG("setErrorCode code=" << anErrorCode); theError.code = anErrorCode; + // conditionally copy error to operation level + if (theNdbOp != NULL && theNdbOp->theError.code == 0) + theNdbOp->setErrorCode(theError.code); if (invalidFlag) setState(Invalid); } @@ -1335,11 +1413,34 @@ NdbBlob::setErrorCode(NdbConnection* aCon, bool invalidFlag) setErrorCode(code, invalidFlag); } +// info about all blobs in this operation + +NdbBlob* +NdbBlob::blobsFirstBlob() +{ + return theNdbOp->theBlobList; +} + +NdbBlob* +NdbBlob::blobsNextBlob() +{ + return theNext; +} + +// debug + #ifdef VM_TRACE +inline int +NdbBlob::getOperationType() const +{ + return theNdbOp != NULL ? theNdbOp->theOperationType : -1; +} + NdbOut& operator<<(NdbOut& out, const NdbBlob& blob) { - ndbout << dec << "s=" << blob.theState; + ndbout << dec << "o=" << blob.getOperationType(); + ndbout << dec << " s=" << blob.theState; ndbout << dec << " n=" << blob.theNullFlag;; ndbout << dec << " l=" << blob.theLength; ndbout << dec << " p=" << blob.thePos; diff --git a/ndb/src/ndbapi/NdbConnection.cpp b/ndb/src/ndbapi/NdbConnection.cpp index ad415b8acbf..9a2995a957e 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 <NdbOut.hpp> +#include <NdbConnection.hpp> +#include <NdbOperation.hpp> +#include <NdbScanOperation.hpp> +#include <NdbIndexScanOperation.hpp> +#include <NdbIndexOperation.hpp> #include "NdbApiSignal.hpp" #include "TransporterFacade.hpp" #include "API.hpp" @@ -80,18 +81,16 @@ NdbConnection::NdbConnection( Ndb* aNdb ) : theTransactionIsStarted(false), theDBnode(0), theReleaseOnClose(false), - // Cursor operations + // Scan operations m_waitForReply(true), - m_theFirstCursorOperation(NULL), - m_theLastCursorOperation(NULL), - m_firstExecutedCursorOp(NULL), + m_theFirstScanOperation(NULL), + m_theLastScanOperation(NULL), + m_firstExecutedScanOp(NULL), // Scan operations - theScanFinished(0), - theCurrentScanRec(NULL), - thePreviousScanRec(NULL), theScanningOp(NULL), theBuddyConPtr(0xFFFFFFFF), - theBlobFlag(false) + theBlobFlag(false), + thePendingBlobOps(0) { theListState = NotInList; theError.code = 0; @@ -119,7 +118,6 @@ NdbConnection::init() theListState = NotInList; theInUseState = true; theTransactionIsStarted = false; - theScanFinished = 0; theNext = NULL; theFirstOpInList = NULL; @@ -130,9 +128,6 @@ NdbConnection::init() theFirstExecOpInList = NULL; theLastExecOpInList = NULL; - theCurrentScanRec = NULL; - thePreviousScanRec = NULL; - theCompletedFirstOp = NULL; theGlobalCheckpointId = 0; @@ -148,14 +143,15 @@ 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; // theBlobFlag = false; + thePendingBlobOps = 0; }//NdbConnection::init() /***************************************************************************** @@ -203,6 +199,23 @@ NdbConnection::setErrorCode(int anErrorCode) theError.code = anErrorCode; }//NdbConnection::setErrorCode() +int +NdbConnection::restart(){ + if(theCompletionStatus == CompletedSuccess){ + releaseCompletedOperations(); + Uint64 tTransid = theNdb->theFirstTransId; + theTransactionId = tTransid; + if ((tTransid & 0xFFFFFFFF) == 0xFFFFFFFF) { + theNdb->theFirstTransId = (tTransid >> 32) << 32; + } else { + theNdb->theFirstTransId = tTransid + 1; + } + theCompletionStatus = NotCompleted; + return 0; + } + return -1; +} + /***************************************************************************** void handleExecuteCompletion(void); @@ -258,26 +271,34 @@ NdbConnection::execute(ExecType aTypeOfExec, if (! theBlobFlag) return executeNoBlobs(aTypeOfExec, abortOption, forceSend); - // execute prepared ops in batches, as requested by blobs + /* + * execute prepared ops in batches, as requested by blobs + * - blob error does not terminate execution + * - blob error sets error on operation + * - if error on operation skip blob calls + */ ExecType tExecType; NdbOperation* tPrepOp; + int ret = 0; do { tExecType = aTypeOfExec; tPrepOp = theFirstOpInList; while (tPrepOp != NULL) { - bool batch = false; - NdbBlob* tBlob = tPrepOp->theBlobList; - while (tBlob != NULL) { - if (tBlob->preExecute(tExecType, batch) == -1) - return -1; - tBlob = tBlob->theNext; - } - if (batch) { - // blob asked to execute all up to here now - tExecType = NoCommit; - break; + if (tPrepOp->theError.code == 0) { + bool batch = false; + NdbBlob* tBlob = tPrepOp->theBlobList; + while (tBlob != NULL) { + if (tBlob->preExecute(tExecType, batch) == -1) + ret = -1; + tBlob = tBlob->theNext; + } + if (batch) { + // blob asked to execute all up to here now + tExecType = NoCommit; + break; + } } tPrepOp = tPrepOp->next(); } @@ -293,26 +314,30 @@ NdbConnection::execute(ExecType aTypeOfExec, if (tExecType == Commit) { NdbOperation* tOp = theCompletedFirstOp; while (tOp != NULL) { - NdbBlob* tBlob = tOp->theBlobList; - while (tBlob != NULL) { - if (tBlob->preCommit() == -1) - return -1; - tBlob = tBlob->theNext; + if (tOp->theError.code == 0) { + NdbBlob* tBlob = tOp->theBlobList; + while (tBlob != NULL) { + if (tBlob->preCommit() == -1) + ret = -1; + tBlob = tBlob->theNext; + } } tOp = tOp->next(); } } if (executeNoBlobs(tExecType, abortOption, forceSend) == -1) - return -1; + ret = -1; { NdbOperation* tOp = theCompletedFirstOp; while (tOp != NULL) { - NdbBlob* tBlob = tOp->theBlobList; - while (tBlob != NULL) { - // may add new operations if batch - if (tBlob->postExecute(tExecType) == -1) - return -1; - tBlob = tBlob->theNext; + if (tOp->theError.code == 0) { + NdbBlob* tBlob = tOp->theBlobList; + while (tBlob != NULL) { + // may add new operations if batch + if (tBlob->postExecute(tExecType) == -1) + ret = -1; + tBlob = tBlob->theNext; + } } tOp = tOp->next(); } @@ -327,7 +352,7 @@ NdbConnection::execute(ExecType aTypeOfExec, } } while (theFirstOpInList != NULL || tExecType != aTypeOfExec); - return 0; + return ret; } int @@ -386,6 +411,7 @@ NdbConnection::executeNoBlobs(ExecType aTypeOfExec, break; } } + thePendingBlobOps = 0; return 0; }//NdbConnection::execute() @@ -414,7 +440,7 @@ NdbConnection::executeAsynchPrepare( ExecType aTypeOfExec, * Reset error.code on execute */ theError.code = 0; - NdbCursorOperation* tcOp = m_theFirstCursorOperation; + NdbScanOperation* tcOp = m_theFirstScanOperation; if (tcOp != 0){ // Execute any cursor operations while (tcOp != NULL) { @@ -423,14 +449,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; @@ -797,17 +823,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; @@ -839,8 +862,8 @@ void NdbConnection::releaseOperations() { // Release any open scans - releaseCursorOperations(m_theFirstCursorOperation); - releaseCursorOperations(m_firstExecutedCursorOp); + releaseScanOperations(m_theFirstScanOperation); + releaseScanOperations(m_firstExecutedScanOp); releaseOps(theCompletedFirstOp); releaseOps(theFirstOpInList); @@ -852,9 +875,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 @@ -865,24 +888,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); @@ -916,45 +936,6 @@ NdbConnection::getNdbOperation(const char* aTableName) }//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); Return Value Return a pointer to a NdbOperation object if getNdbOperation @@ -1014,6 +995,14 @@ NdbConnection::getNdbOperation(NdbTableImpl * tab, NdbOperation* aNextOp) return NULL; }//NdbConnection::getNdbOperation() +NdbOperation* NdbConnection::getNdbOperation(NdbDictionary::Table * table) +{ + if (table) + return getNdbOperation(& NdbTableImpl::getImpl(*table)); + else + return NULL; +}//NdbConnection::getNdbOperation() + // NdbScanOperation /***************************************************************************** NdbScanOperation* getNdbScanOperation(const char* aTableName); @@ -1033,7 +1022,7 @@ NdbConnection::getNdbScanOperation(const char* aTableName) if (tab != 0){ return getNdbScanOperation(tab); } else { - setOperationErrorCodeAbort(theNdb->theError.code); + setOperationErrorCodeAbort(theNdb->theDictionary->m_error.code); return NULL; }//if } @@ -1053,17 +1042,29 @@ 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) +{ + NdbIndexImpl* index = + theNdb->theDictionary->getIndex(anIndexName, aTableName); + NdbTableImpl* table = theNdb->theDictionary->getTable(aTableName); + + return getNdbIndexScanOperation(index, table); +} + +NdbIndexScanOperation* +NdbConnection::getNdbIndexScanOperation(NdbIndexImpl* index, + NdbTableImpl* table) { if (theCommitStatus == Started){ - NdbIndexImpl* index = - theNdb->theDictionary->getIndex(anIndexName, aTableName); - NdbTableImpl* table = theNdb->theDictionary->getTable(aTableName); - NdbTableImpl* indexTable = - theNdb->theDictionary->getIndexTable(index, table); + const NdbTableImpl * indexTable = index->getIndexTable(); if (indexTable != 0){ - return getNdbScanOperation(indexTable); + NdbIndexScanOperation* tOp = + getNdbScanOperation((NdbTableImpl *) indexTable); + tOp->m_currentTable = table; + if(tOp) tOp->m_cursor_type = NdbScanOperation::IndexCursor; + return tOp; } else { setOperationErrorCodeAbort(theNdb->theError.code); return NULL; @@ -1072,7 +1073,18 @@ NdbConnection::getNdbScanOperation(const char* anIndexName, const char* aTableNa setOperationErrorCodeAbort(4114); return NULL; -}//NdbConnection::getNdbScanOperation() +}//NdbConnection::getNdbIndexScanOperation() + +NdbIndexScanOperation* +NdbConnection::getNdbIndexScanOperation(NdbDictionary::Index * index, + NdbDictionary::Table * table) +{ + if (index && table) + return getNdbIndexScanOperation(& NdbIndexImpl::getImpl(*index), + & NdbTableImpl::getImpl(*table)); + else + return NULL; +}//NdbConnection::getNdbIndexScanOperation() /***************************************************************************** NdbScanOperation* getNdbScanOperation(int aTableId); @@ -1084,21 +1096,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) { @@ -1113,6 +1125,14 @@ getNdbOp_error1: return NULL; }//NdbConnection::getNdbScanOperation() +NdbScanOperation* +NdbConnection::getNdbScanOperation(NdbDictionary::Table * table) +{ + if (table) + return getNdbScanOperation(& NdbTableImpl::getImpl(*table)); + else + return NULL; +}//NdbConnection::getNdbScanOperation() // IndexOperation @@ -1207,6 +1227,18 @@ NdbConnection::getNdbIndexOperation(NdbIndexImpl * anIndex, return NULL; }//NdbConnection::getNdbIndexOperation() +NdbIndexOperation* +NdbConnection::getNdbIndexOperation(NdbDictionary::Index * index, + NdbDictionary::Table * table) +{ + if (index && table) + return getNdbIndexOperation(& NdbIndexImpl::getImpl(*index), + & NdbTableImpl::getImpl(*table)); + else + return NULL; +}//NdbConnection::getNdbIndexOperation() + + /******************************************************************************* int receiveDIHNDBTAMPER(NdbApiSignal* aSignal) @@ -1323,12 +1355,16 @@ Remark: int NdbConnection::receiveTC_COMMITCONF(const TcCommitConf * commitConf) { - if(theStatus != Connected){ - return -1; + if(checkState_TransId(&commitConf->transId1)){ + theCommitStatus = Committed; + theCompletionStatus = CompletedSuccess; + return 0; + } else { +#ifdef NDB_NO_DROPPED_SIGNAL + abort(); +#endif } - theCommitStatus = Committed; - theCompletionStatus = CompletedSuccess; - return 0; + return -1; }//NdbConnection::receiveTC_COMMITCONF() /****************************************************************************** @@ -1342,33 +1378,43 @@ 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; + } else { +#ifdef NDB_NO_DROPPED_SIGNAL + abort(); +#endif } - 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; + } else { +#ifdef NDB_NO_DROPPED_SIGNAL + abort(); +#endif } - theCommitStatus = Aborted; - theCompletionStatus = CompletedSuccess; - return 0; + + return -1; }//NdbConnection::receiveTCROLLBACKCONF() /******************************************************************************* @@ -1382,13 +1428,18 @@ 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; + } else { +#ifdef NDB_NO_DROPPED_SIGNAL + abort(); +#endif } - setOperationErrorCodeAbort(aSignal->readData(2)); - theCommitStatus = Aborted; - theCompletionStatus = CompletedFailure; - return 0; + + return -1; }//NdbConnection::receiveTCROLLBACKREF() /***************************************************************************** @@ -1403,36 +1454,31 @@ 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; + } else { +#ifdef NDB_NO_DROPPED_SIGNAL + abort(); +#endif + } -/**********************************************************************/ -/* 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() /******************************************************************************* @@ -1446,49 +1492,50 @@ 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; } else if ((tNoComp >= tNoSent) && (theLastExecOpInList->theCommitIndicator == 1)){ + + + if (m_abortOption == IgnoreError && theError.code != 0){ + /** + * There's always a TCKEYCONF when using IgnoreError + */ +#ifdef VM_TRACE + ndbout_c("Not completing transaction 2"); +#endif + return -1; + } /**********************************************************************/ // We sent the transaction with Commit flag set and received a CONF with // no Commit flag set. This is clearly an anomaly. @@ -1502,7 +1549,12 @@ from other transactions. return 0; // No more operations to wait for }//if // Not completed the reception yet. - }//if + } else { +#ifdef NDB_NO_DROPPED_SIGNAL + abort(); +#endif + } + return -1; }//NdbConnection::receiveTCKEYCONF() @@ -1518,50 +1570,50 @@ 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 NdbOperation::UpdateRequest: + case NdbOperation::InsertRequest: + case NdbOperation::DeleteRequest: + case NdbOperation::WriteRequest: + tOp = tOp->next(); + break; + case NdbOperation::ReadRequest: + case NdbOperation::ReadExclusive: + case NdbOperation::OpenScanRequest: + case NdbOperation::OpenRangeScanRequest: + theCompletionStatus = CompletedFailure; + setOperationErrorCodeAbort(4115); + tOp = NULL; + break; + }//if + }//while + theReleaseOnClose = true; + return 0; + } else { +#ifdef VM_TRACE + ndbout_c("Recevied TCKEY_FAILCONF wo/ operation"); +#endif + } + return -1; }//NdbConnection::receiveTCKEY_FAILCONF() /************************************************************************* @@ -1576,111 +1628,94 @@ 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. - */ - 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. + 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. */ - 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; + if (theSendStatus == NdbConnection::sendTC_ROLLBACK) { + /* + We were in the process of sending a rollback anyways. We will + report it as a success. + */ + theCompletionStatus = NdbConnection::CompletedSuccess; + } else { + theCompletionStatus = NdbConnection::CompletedFailure; + theError.code = 4031; + }//if + theReleaseOnClose = true; + theCommitStatus = NdbConnection::Aborted; + return 0; } else { - theCompletionStatus = CompletedFailure; - theError.code = 4031; - }//if - theReleaseOnClose = true; - theCommitStatus = Aborted; - return 0; +#ifdef VM_TRACE + ndbout_c("Recevied TCKEY_FAILREF wo/ operation"); +#endif + } + 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) +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) { + 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; + theCompletionStatus = NdbConnection::CompletedFailure; + theCommitStatus = NdbConnection::Aborted; return 0; }//if if (tNoComp >= tNoSent) { return 0; // No more operations to wait for }//if // Not completed the reception yet. - }//if + } else { +#ifdef NDB_NO_DROPPED_SIGNAL + abort(); +#endif + } + return -1; }//NdbConnection::receiveTCINDXCONF() @@ -1696,36 +1731,26 @@ Remark: Handles the reception of the TCINDXREF signal. int NdbConnection::receiveTCINDXREF( 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 = NdbConnection::CompletedFailure; + theCommitStatus = NdbConnection::Aborted; + return 0; + } else { +#ifdef NDB_NO_DROPPED_SIGNAL + abort(); +#endif + } -/**********************************************************************/ -/* 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() /******************************************************************************* @@ -1741,7 +1766,7 @@ NdbConnection::OpCompleteFailure() { Uint32 tNoComp = theNoOfOpCompleted; Uint32 tNoSent = theNoOfOpSent; - theCompletionStatus = CompletedFailure; + theCompletionStatus = NdbConnection::CompletedFailure; tNoComp++; theNoOfOpCompleted = tNoComp; if (tNoComp == tNoSent) { @@ -1752,8 +1777,18 @@ NdbConnection::OpCompleteFailure() //operation is not really part of that transaction. //------------------------------------------------------------------------ if (theSimpleState == 1) { - theCommitStatus = Aborted; + theCommitStatus = NdbConnection::Aborted; }//if + if (m_abortOption == IgnoreError){ + /** + * There's always a TCKEYCONF when using IgnoreError + */ +#ifdef VM_TRACE + ndbout_c("Not completing transaction"); +#endif + return -1; + } + return 0; // Last operation received } else if (tNoComp > tNoSent) { setOperationErrorCodeAbort(4113); // Too many operations, @@ -1780,7 +1815,7 @@ NdbConnection::OpCompleteSuccess() theNoOfOpCompleted = tNoComp; if (tNoComp == tNoSent) { // Last operation completed if (theSimpleState == 1) { - theCommitStatus = Committed; + theCommitStatus = NdbConnection::Committed; }//if return 0; } else if (tNoComp < tNoSent) { @@ -1788,7 +1823,7 @@ NdbConnection::OpCompleteSuccess() } else { setOperationErrorCodeAbort(4113); // Too many operations, // stop waiting for more - theCompletionStatus = CompletedFailure; + theCompletionStatus = NdbConnection::CompletedFailure; return 0; }//if }//NdbConnection::OpCompleteSuccess() @@ -1801,7 +1836,7 @@ Remark: Get global checkpoint identity of the transaction int NdbConnection::getGCI() { - if (theCommitStatus == Committed) { + if (theCommitStatus == NdbConnection::Committed) { return theGlobalCheckpointId; }//if return 0; diff --git a/ndb/src/ndbapi/NdbConnectionScan.cpp b/ndb/src/ndbapi/NdbConnectionScan.cpp index 962acc0bdac..0c4490015ff 100644 --- a/ndb/src/ndbapi/NdbConnectionScan.cpp +++ b/ndb/src/ndbapi/NdbConnectionScan.cpp @@ -33,7 +33,6 @@ #include <NdbConnection.hpp> #include <NdbOperation.hpp> #include <NdbScanOperation.hpp> -#include "NdbScanReceiver.hpp" #include "NdbApiSignal.hpp" #include "TransporterFacade.hpp" #include "NdbUtil.hpp" @@ -44,304 +43,6 @@ #include <NdbOut.hpp> -// time out for next scan result (-1 is infinite) -// XXX should change default only if non-trivial interpreted program is used -#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("<<fetchAllowed<<")"<<endl - << " theTransactionIsStarted = " << theTransactionIsStarted << endl - << " theScanFinished = " << theScanFinished << endl - << " theCommitStatus = " << theCommitStatus << endl - << " theStatus = " << theStatus << endl - << " theCompletionStatus = " << theCompletionStatus << endl - << " theNoOfOpCompleted = " << theNoOfOpCompleted << endl - << " theNoOfOpFetched = " << theNoOfOpFetched << endl - << " theScanningOp = " << theScanningOp << endl - << " theNoOfSCANTABCONFRecv = "<< theNoOfSCANTABCONFRecv << endl - << " theNdb->theWaiter.m_node = " <<theNdb->theWaiter.m_node<<endl - << " theNdb->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 +53,24 @@ 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; - } - 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; + const ScanTabRef * ref = CAST_CONSTPTR(ScanTabRef, aSignal->getDataPtr()); + + if(checkState_TransId(&ref->transId1)){ + theScanningOp->theError.code = ref->errorCode; + if(!ref->closeNeeded){ + theScanningOp->execCLOSE_SCAN_REP(); + return 0; + } + assert(theScanningOp->m_sent_receivers_count); + theScanningOp->m_conf_receivers_count++; + return 0; + } else { +#ifdef NDB_NO_DROPPED_SIGNAL + abort(); #endif - return -1; } -#if 0 - ndbout << "SCAN_TABREF, " - <<"transid=("<<hex<<scanTabRef->transId1<<", "<<hex<<scanTabRef->transId2<<")" - <<", err="<<dec<<scanTabRef->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 +87,44 @@ 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; + const ScanTabConf * conf = CAST_CONSTPTR(ScanTabConf, aSignal->getDataPtr()); + if(checkState_TransId(&conf->transId1)){ + + if (conf->requestInfo == ScanTabConf::EndOfData) { + theScanningOp->execCLOSE_SCAN_REP(); + return 0; + } + + for(Uint32 i = 0; i<len; i += 3){ + Uint32 ptrI = * ops++; + Uint32 tcPtrI = * ops++; + Uint32 info = * ops++; + Uint32 opCount = ScanTabConf::getRows(info); + Uint32 totalLen = ScanTabConf::getLength(info); + + void * tPtr = theNdb->int2void(ptrI); + assert(tPtr); // For now + NdbReceiver* tOp = theNdb->void2rec(tPtr); + if (tOp && tOp->checkMagicNumber()){ + if(tOp->execSCANOPCONF(tcPtrI, totalLen, opCount)){ + /** + * + */ + theScanningOp->receiver_delivered(tOp); + } else if(info == ScanTabConf::EndOfData){ + theScanningOp->receiver_completed(tOp); + } } - tNoOfOpFetched++; } - 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 + return 0; + } else { +#ifdef NDB_NO_DROPPED_SIGNAL + abort(); +#endif } - // 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 <NdbResultSet.hpp> 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/NdbDictionary.cpp b/ndb/src/ndbapi/NdbDictionary.cpp index 413ad0745db..4b30f41b51d 100644 --- a/ndb/src/ndbapi/NdbDictionary.cpp +++ b/ndb/src/ndbapi/NdbDictionary.cpp @@ -174,6 +174,14 @@ NdbDictionary::Column::getIndexOnlyStorage() const { return m_impl.m_indexOnly; } +const NdbDictionary::Table * +NdbDictionary::Column::getBlobTable() const { + NdbTableImpl * t = m_impl.m_blobTable; + if (t) + return t->m_facade; + return 0; +} + void NdbDictionary::Column::setAutoIncrement(bool val){ m_impl.m_autoIncrement = val; @@ -806,73 +814,90 @@ NdbDictionary::Dictionary::getNdbError() const { return m_impl.getNdbError(); } -NdbOut& operator <<(NdbOut& ndbout, const NdbDictionary::Column::Type type) +// printers + +NdbOut& +operator<<(NdbOut& out, const NdbDictionary::Column& col) { - switch(type){ - case NdbDictionary::Column::Bigunsigned: - ndbout << "Bigunsigned"; + out << col.getName() << " "; + switch (col.getType()) { + case NdbDictionary::Column::Tinyint: + out << "Tinyint"; break; - case NdbDictionary::Column::Unsigned: - ndbout << "Unsigned"; + case NdbDictionary::Column::Tinyunsigned: + out << "Tinyunsigned"; + break; + case NdbDictionary::Column::Smallint: + out << "Smallint"; break; case NdbDictionary::Column::Smallunsigned: - ndbout << "Smallunsigned"; + out << "Smallunsigned"; break; - case NdbDictionary::Column::Tinyunsigned: - ndbout << "Tinyunsigned"; + case NdbDictionary::Column::Mediumint: + out << "Mediumint"; break; - case NdbDictionary::Column::Bigint: - ndbout << "Bigint"; + case NdbDictionary::Column::Mediumunsigned: + out << "Mediumunsigned"; break; case NdbDictionary::Column::Int: - ndbout << "Int"; - break; - case NdbDictionary::Column::Smallint: - ndbout << "Smallint"; + out << "Int"; break; - case NdbDictionary::Column::Tinyint: - ndbout << "Tinyint"; + case NdbDictionary::Column::Unsigned: + out << "Unsigned"; break; - case NdbDictionary::Column::Char: - ndbout << "Char"; + case NdbDictionary::Column::Bigint: + out << "Bigint"; break; - case NdbDictionary::Column::Varchar: - ndbout << "Varchar"; + case NdbDictionary::Column::Bigunsigned: + out << "Bigunsigned"; break; case NdbDictionary::Column::Float: - ndbout << "Float"; + out << "Float"; break; case NdbDictionary::Column::Double: - ndbout << "Double"; + out << "Double"; break; - case NdbDictionary::Column::Mediumint: - ndbout << "Mediumint"; + case NdbDictionary::Column::Decimal: + out << "Decimal(" << col.getScale() << "," << col.getPrecision() << ")"; break; - case NdbDictionary::Column::Mediumunsigned: - ndbout << "Mediumunsigend"; + case NdbDictionary::Column::Char: + out << "Char(" << col.getLength() << ")"; + break; + case NdbDictionary::Column::Varchar: + out << "Varchar(" << col.getLength() << ")"; break; case NdbDictionary::Column::Binary: - ndbout << "Binary"; + out << "Binary(" << col.getLength() << ")"; break; case NdbDictionary::Column::Varbinary: - ndbout << "Varbinary"; + out << "Varbinary(" << col.getLength() << ")"; break; - case NdbDictionary::Column::Decimal: - ndbout << "Decimal"; + case NdbDictionary::Column::Datetime: + out << "Datetime"; break; case NdbDictionary::Column::Timespec: - ndbout << "Timespec"; + out << "Timespec"; break; case NdbDictionary::Column::Blob: - ndbout << "Blob"; + out << "Blob(" << col.getInlineSize() << "," << col.getPartSize() + << ";" << col.getStripeSize() << ")"; + break; + case NdbDictionary::Column::Text: + out << "Text(" << col.getInlineSize() << "," << col.getPartSize() + << ";" << col.getStripeSize() << ")"; break; case NdbDictionary::Column::Undefined: - ndbout << "Undefined"; + out << "Undefined"; break; default: - ndbout << "Unknown type=" << (Uint32)type; + out << "Type" << (Uint32)col.getType(); break; } - - return ndbout; + if (col.getPrimaryKey()) + out << " PRIMARY KEY"; + else if (! col.getNullable()) + out << " NOT NULL"; + else + out << " NULL"; + return out; } diff --git a/ndb/src/ndbapi/NdbDictionaryImpl.cpp b/ndb/src/ndbapi/NdbDictionaryImpl.cpp index 348f6db36e4..cb5e3b3c821 100644 --- a/ndb/src/ndbapi/NdbDictionaryImpl.cpp +++ b/ndb/src/ndbapi/NdbDictionaryImpl.cpp @@ -79,6 +79,7 @@ NdbColumnImpl::operator=(const NdbColumnImpl& col) m_attrSize = col.m_attrSize; m_arraySize = col.m_arraySize; m_keyInfoPos = col.m_keyInfoPos; + m_blobTable = col.m_blobTable; // Do not copy m_facade !! return *this; @@ -104,6 +105,7 @@ NdbColumnImpl::init() m_arraySize = 1, m_autoIncrement = false; m_autoIncrementInitialValue = 1; + m_blobTable = NULL; } NdbColumnImpl::~NdbColumnImpl() @@ -181,7 +183,7 @@ NdbColumnImpl::equal(const NdbColumnImpl& col) const case NdbDictionary::Column::Timespec: break; case NdbDictionary::Column::Blob: - case NdbDictionary::Column::Clob: + case NdbDictionary::Column::Text: if (m_precision != col.m_precision || m_scale != col.m_scale || m_length != col.m_length) { @@ -230,10 +232,6 @@ NdbColumnImpl::assign(const NdbColumnImpl& org) NdbTableImpl::NdbTableImpl() : NdbDictionary::Table(* this), m_facade(this) { - m_noOfKeys = 0; - m_sizeOfKeysInWords = 0; - m_noOfBlobs = 0; - m_index = 0; init(); } @@ -267,6 +265,7 @@ NdbTableImpl::init(){ m_indexType = NdbDictionary::Index::Undefined; m_noOfKeys = 0; + m_fragmentCount = 0; m_sizeOfKeysInWords = 0; m_noOfBlobs = 0; } @@ -287,11 +286,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; } @@ -330,6 +327,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; i<org.m_columns.size(); i++){ NdbColumnImpl * col = new NdbColumnImpl(); @@ -387,7 +385,8 @@ void NdbTableImpl::buildColumnHash(){ const Uint32 size = m_columns.size(); - for(size_t i = 31; i >= 0; i--){ + size_t i; + for(i = 31; i >= 0; i--){ if(((1 << i) & size) != 0){ m_columnHashMask = (1 << (i + 1)) - 1; break; @@ -396,7 +395,7 @@ NdbTableImpl::buildColumnHash(){ Vector<Uint32> hashValues; Vector<Vector<Uint32> > chains; chains.fill(size, hashValues); - for(size_t i = 0; i<size; i++){ + for(i = 0; i<size; i++){ Uint32 hv = Hash(m_columns[i]->getName()) & 0xFFFE; Uint32 bucket = hv & m_columnHashMask; bucket = (bucket < size ? bucket : bucket - size); @@ -410,7 +409,7 @@ NdbTableImpl::buildColumnHash(){ m_columnHash.fill((unsigned)size-1, tmp); // Default no chaining Uint32 pos = 0; // In overflow vector - for(size_t i = 0; i<size; i++){ + for(i = 0; i<size; i++){ Uint32 sz = chains[i].size(); if(sz == 1){ Uint32 col = chains[i][0]; @@ -495,6 +494,12 @@ NdbIndexImpl::getTable() const return m_tableName.c_str(); } +const NdbTableImpl * +NdbIndexImpl::getIndexTable() const +{ + return m_table; +} + /** * NdbEventImpl */ @@ -840,6 +845,7 @@ NdbDictInterface::dictSignal(NdbApiSignal* signal, m_waiter.m_state = wst; m_waiter.wait(theWait); + m_transporter->unlock_mutex(); // End of Protected area if(m_waiter.m_state == NO_WAIT && m_error.code == 0){ @@ -1091,7 +1097,7 @@ columnTypeMapping[] = { { DictTabInfo::ExtDatetime, NdbDictionary::Column::Datetime }, { DictTabInfo::ExtTimespec, NdbDictionary::Column::Timespec }, { DictTabInfo::ExtBlob, NdbDictionary::Column::Blob }, - { DictTabInfo::ExtClob, NdbDictionary::Column::Clob }, + { DictTabInfo::ExtText, NdbDictionary::Column::Text }, { -1, -1 } }; @@ -1132,6 +1138,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, @@ -1147,7 +1154,7 @@ NdbDictInterface::parseTableInfo(NdbTableImpl ** ret, Uint32 keyInfoPos = 0; Uint32 keyCount = 0; - Uint32 blobCount; + Uint32 blobCount = 0; for(Uint32 i = 0; i < tableDesc.NoOfAttributes; i++) { DictTabInfo::Attribute attrDesc; attrDesc.init(); @@ -1206,7 +1213,6 @@ NdbDictInterface::parseTableInfo(NdbTableImpl ** ret, } if (col->getBlobType()) blobCount++; - NdbColumnImpl * null = 0; impl->m_columns.fill(attrDesc.AttributeId, null); if(impl->m_columns[attrDesc.AttributeId] != 0){ @@ -1218,6 +1224,7 @@ NdbDictInterface::parseTableInfo(NdbTableImpl ** ret, it.next(); } impl->m_noOfKeys = keyCount; + impl->m_keyLenInWords = keyInfoPos; impl->m_sizeOfKeysInWords = keyInfoPos; impl->m_noOfBlobs = blobCount; * ret = impl; @@ -1254,13 +1261,34 @@ NdbDictionaryImpl::createBlobTables(NdbTableImpl &t) { for (unsigned i = 0; i < t.m_columns.size(); i++) { NdbColumnImpl & c = *t.m_columns[i]; - if (! c.getBlobType()) + if (! c.getBlobType() || c.getPartSize() == 0) continue; NdbTableImpl bt; NdbBlob::getBlobTable(bt, &t, &c); if (createTable(bt) != 0) return -1; + // Save BLOB table handle + NdbTableImpl * cachedBlobTable = getTable(bt.m_externalName.c_str()); + c.m_blobTable = cachedBlobTable; } + + return 0; +} + +int +NdbDictionaryImpl::addBlobTables(NdbTableImpl &t) +{ + for (unsigned i = 0; i < t.m_columns.size(); i++) { + NdbColumnImpl & c = *t.m_columns[i]; + if (! c.getBlobType() || c.getPartSize() == 0) + continue; + char btname[NdbBlob::BlobTableNameSize]; + NdbBlob::getBlobTableName(btname, &t, &c); + // Save BLOB table handle + NdbTableImpl * cachedBlobTable = getTable(btname);; + c.m_blobTable = cachedBlobTable; + } + return 0; } @@ -1315,6 +1343,7 @@ NdbDictInterface::createOrAlterTable(Ndb & ndb, NdbTableImpl & impl, bool alter) { + unsigned i; if((unsigned)impl.getNoOfPrimaryKeys() > NDB_MAX_NO_OF_ATTRIBUTES_IN_KEY){ m_error.code = 4317; return -1; @@ -1340,7 +1369,7 @@ NdbDictInterface::createOrAlterTable(Ndb & ndb, bool haveAutoIncrement = false; Uint64 autoIncrementValue; - for(unsigned i = 0; i<sz; i++){ + for(i = 0; i<sz; i++){ const NdbColumnImpl * col = impl.m_columns[i]; if(col == 0) continue; @@ -1384,7 +1413,7 @@ NdbDictInterface::createOrAlterTable(Ndb & ndb, abort(); } - for(unsigned i = 0; i<sz; i++){ + for(i = 0; i<sz; i++){ const NdbColumnImpl * col = impl.m_columns[i]; if(col == 0) continue; @@ -1453,7 +1482,7 @@ NdbDictInterface::createOrAlterTable(Ndb & ndb, alterTable(&tSignal, ptr) : createTable(&tSignal, ptr); - if (haveAutoIncrement) { + if (!alter && haveAutoIncrement) { // if (!ndb.setAutoIncrementValue(impl.m_internalName.c_str(), autoIncrementValue)) { if (!ndb.setAutoIncrementValue(impl.m_externalName.c_str(), autoIncrementValue)) { m_error.code = 4336; @@ -1623,7 +1652,7 @@ NdbDictionaryImpl::dropBlobTables(NdbTableImpl & t) { for (unsigned i = 0; i < t.m_columns.size(); i++) { NdbColumnImpl & c = *t.m_columns[i]; - if (! c.getBlobType()) + if (! c.getBlobType() || c.getPartSize() == 0) continue; char btname[NdbBlob::BlobTableNameSize]; NdbBlob::getBlobTableName(btname, &t, &c); @@ -1734,8 +1763,8 @@ NdbDictionaryImpl::getIndexImpl(const char * externalName, return 0; } - NdbTableImpl* primTab = getTable(tab->m_primaryTable.c_str()); - if(primTab == 0){ + NdbTableImpl* prim = getTable(tab->m_primaryTable.c_str()); + if(prim == 0){ m_error.code = 4243; return 0; } @@ -1749,7 +1778,7 @@ NdbDictionaryImpl::getIndexImpl(const char * externalName, idx->m_indexId = tab->m_tableId; idx->m_internalName.assign(internalName); idx->m_externalName.assign(externalName); - idx->m_tableName.assign(primTab->m_externalName); + idx->m_tableName.assign(prim->m_externalName); idx->m_type = tab->m_indexType; // skip last attribute (NDB$PK or NDB$TNODE) for(unsigned i = 0; i+1<tab->m_columns.size(); i++){ @@ -1757,6 +1786,14 @@ NdbDictionaryImpl::getIndexImpl(const char * externalName, // Copy column definition *col = *tab->m_columns[i]; idx->m_columns.push_back(col); + /** + * reverse map + */ + int key_id = prim->getColumn(col->getName())->getColumnNo(); + int fill = -1; + idx->m_key_ids.fill(key_id, fill); + idx->m_key_ids[key_id] = i; + col->m_keyInfoPos = key_id; } idx->m_table = tab; @@ -1788,7 +1825,7 @@ NdbDictInterface::createIndex(Ndb & ndb, { //validate(); //aggregate(); - + unsigned i; UtilBufferWriter w(m_buffer); const size_t len = strlen(impl.m_externalName.c_str()) + 1; if(len > MAX_TAB_NAME_SIZE) { @@ -1828,7 +1865,7 @@ NdbDictInterface::createIndex(Ndb & ndb, req->setOnline(true); AttributeList attributeList; attributeList.sz = impl.m_columns.size(); - for(unsigned i = 0; i<attributeList.sz; i++){ + for(i = 0; i<attributeList.sz; i++){ const NdbColumnImpl* col = table.getColumn(impl.m_columns[i]->m_name.c_str()); if(col == 0){ @@ -1842,18 +1879,11 @@ NdbDictInterface::createIndex(Ndb & ndb, m_error.code = 4245; return -1; } - - if (it == DictTabInfo::UniqueHashIndex && - (col->m_nullable) && (attributeList.sz > 1)) { - // We only support one NULL attribute - m_error.code = 4246; - return -1; - } attributeList.id[i] = col->m_attrId; } if (it == DictTabInfo::UniqueHashIndex) { // Sort index attributes according to primary table (using insertion sort) - for(unsigned i = 1; i < attributeList.sz; i++) { + for(i = 1; i < attributeList.sz; i++) { unsigned int temp = attributeList.id[i]; unsigned int j = i; while((j > 0) && (attributeList.id[j - 1] > temp)) { @@ -1863,7 +1893,7 @@ NdbDictInterface::createIndex(Ndb & ndb, attributeList.id[j] = temp; } // Check for illegal duplicate attributes - for(unsigned i = 0; i<attributeList.sz; i++) { + for(i = 0; i<attributeList.sz; i++) { if ((i != (attributeList.sz - 1)) && (attributeList.id[i] == attributeList.id[i+1])) { m_error.code = 4258; @@ -2043,6 +2073,7 @@ NdbDictInterface::execDROP_INDX_REF(NdbApiSignal * signal, int NdbDictionaryImpl::createEvent(NdbEventImpl & evnt) { + int i; NdbTableImpl* tab = getTable(evnt.getTable()); if(tab == 0){ @@ -2065,7 +2096,7 @@ NdbDictionaryImpl::createEvent(NdbEventImpl & evnt) int attributeList_sz = evnt.m_attrIds.size(); - for (int i = 0; i < attributeList_sz; i++) { + for (i = 0; i < attributeList_sz; i++) { NdbColumnImpl *col_impl = table.getColumn(evnt.m_attrIds[i]); if (col_impl) { evnt.m_facade->addColumn(*(col_impl->m_facade)); @@ -2086,7 +2117,7 @@ NdbDictionaryImpl::createEvent(NdbEventImpl & evnt) int pk_count = 0; evnt.m_attrListBitmask.clear(); - for(int i = 0; i<attributeList_sz; i++){ + for(i = 0; i<attributeList_sz; i++){ const NdbColumnImpl* col = table.getColumn(evnt.m_columns[i]->m_name.c_str()); if(col == 0){ @@ -2104,7 +2135,7 @@ NdbDictionaryImpl::createEvent(NdbEventImpl & evnt) } // Sort index attributes according to primary table (using insertion sort) - for(int i = 1; i < attributeList_sz; i++) { + for(i = 1; i < attributeList_sz; i++) { NdbColumnImpl* temp = evnt.m_columns[i]; unsigned int j = i; while((j > 0) && (evnt.m_columns[j - 1]->m_attrId > temp->m_attrId)) { @@ -2114,7 +2145,7 @@ NdbDictionaryImpl::createEvent(NdbEventImpl & evnt) evnt.m_columns[j] = temp; } // Check for illegal duplicate attributes - for(int i = 1; i<attributeList_sz; i++) { + for(i = 1; i<attributeList_sz; i++) { if (evnt.m_columns[i-1]->m_attrId == evnt.m_columns[i]->m_attrId) { m_error.code = 4258; return -1; @@ -2788,6 +2819,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; @@ -2810,3 +2842,10 @@ NdbDictInterface::execLIST_TABLES_CONF(NdbApiSignal* signal, m_waiter.signal(NO_WAIT); } } + +template class Vector<int>; +template class Vector<Uint32>; +template class Vector<Vector<Uint32> >; +template class Vector<NdbTableImpl*>; +template class Vector<NdbColumnImpl*>; + diff --git a/ndb/src/ndbapi/NdbDictionaryImpl.hpp b/ndb/src/ndbapi/NdbDictionaryImpl.hpp index bf59838c198..9a890f02575 100644 --- a/ndb/src/ndbapi/NdbDictionaryImpl.hpp +++ b/ndb/src/ndbapi/NdbDictionaryImpl.hpp @@ -71,6 +71,7 @@ public: bool m_autoIncrement; Uint64 m_autoIncrementInitialValue; BaseString m_defaultValue; + NdbTableImpl * m_blobTable; /** * Internal types and sizes, and aggregates @@ -124,7 +125,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); @@ -168,12 +171,14 @@ public: const char * getName() const; void setTable(const char * table); const char * getTable() const; + const NdbTableImpl * getIndexTable() const; Uint32 m_indexId; BaseString m_internalName; BaseString m_externalName; BaseString m_tableName; Vector<NdbColumnImpl *> m_columns; + Vector<int> m_key_ids; NdbDictionary::Index::Type m_type; bool m_logging; @@ -358,6 +363,7 @@ public: int createTable(NdbTableImpl &t); int createBlobTables(NdbTableImpl &); + int addBlobTables(NdbTableImpl &); int alterTable(NdbTableImpl &t); int dropTable(const char * name); int dropTable(NdbTableImpl &); @@ -438,7 +444,7 @@ inline bool NdbColumnImpl::getBlobType() const { return (m_type == NdbDictionary::Column::Blob || - m_type == NdbDictionary::Column::Clob); + m_type == NdbDictionary::Column::Text); } inline @@ -612,7 +618,6 @@ NdbDictionaryImpl::getTableImpl(const char * internalTableName) if (ret == 0){ ret = m_receiver.getTable(internalTableName, m_ndb.usingFullyQualifiedNames()); - m_globalHash->lock(); m_globalHash->put(internalTableName, ret); m_globalHash->unlock(); @@ -625,6 +630,8 @@ NdbDictionaryImpl::getTableImpl(const char * internalTableName) m_ndb.theFirstTupleId[ret->getTableId()] = ~0; m_ndb.theLastTupleId[ret->getTableId()] = ~0; + + addBlobTables(*ret); return ret; } diff --git a/ndb/src/ndbapi/NdbEventOperation.cpp b/ndb/src/ndbapi/NdbEventOperation.cpp index ebdebaffd61..506a6c8d86d 100644 --- a/ndb/src/ndbapi/NdbEventOperation.cpp +++ b/ndb/src/ndbapi/NdbEventOperation.cpp @@ -37,7 +37,7 @@ NdbEventOperation::NdbEventOperation(Ndb *theNdb, const char* eventName, - const int bufferLength) + int bufferLength) : m_impl(* new NdbEventOperationImpl(*this,theNdb, eventName, bufferLength)) diff --git a/ndb/src/ndbapi/NdbEventOperationImpl.cpp b/ndb/src/ndbapi/NdbEventOperationImpl.cpp index b73a58d97c4..f5e683b1c29 100644 --- a/ndb/src/ndbapi/NdbEventOperationImpl.cpp +++ b/ndb/src/ndbapi/NdbEventOperationImpl.cpp @@ -93,11 +93,12 @@ NdbEventOperationImpl::NdbEventOperationImpl(NdbEventOperation &N, NdbEventOperationImpl::~NdbEventOperationImpl() { + int i; if (sdata) NdbMem_Free(sdata); - for (int i=0 ; i<3; i++) { + for (i=0 ; i<3; i++) { if (ptr[i].p) NdbMem_Free(ptr[i].p); } - for (int i=0 ; i<2; i++) { + for (i=0 ; i<2; i++) { NdbRecAttr *p = theFirstRecAttrs[i]; while (p) { NdbRecAttr *p_next = p->next(); @@ -166,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) { @@ -387,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; @@ -399,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 @@ -423,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(); } @@ -436,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; @@ -445,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 { @@ -463,7 +456,7 @@ NdbEventOperationImpl::next(int *pOverrun) } } while (tWorkingRecAttr != NULL) { - tWorkingRecAttr->setUNDEFINED(); + tWorkingRecAttr->setNULL(); tWorkingRecAttr = tWorkingRecAttr->next(); } @@ -1233,8 +1226,9 @@ NdbGlobalEventBuffer::real_wait(NdbGlobalEventBufferHandle *h, int aMillisecondNumber) { // check if there are anything in any of the buffers + int i; int n = 0; - for (int i = 0; i < h->m_nids; i++) + for (i = 0; i < h->m_nids; i++) n += hasData(h->m_bufferIds[i]); if (n) return n; @@ -1243,7 +1237,9 @@ NdbGlobalEventBuffer::real_wait(NdbGlobalEventBufferHandle *h, return -1; n = 0; - for (int i = 0; i < h->m_nids; i++) + for (i = 0; i < h->m_nids; i++) n += hasData(h->m_bufferIds[i]); return n; } + +template class Vector<NdbGlobalEventBufferHandle*>; 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 <NdbError.hpp> #include <NdbCondition.h> #include <NdbReceiver.hpp> +#include <NdbOperation.hpp> #include <NdbTick.h> @@ -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 631c09e2e6d..7bea3b9f3d2 100644 --- a/ndb/src/ndbapi/NdbIndexOperation.cpp +++ b/ndb/src/ndbapi/NdbIndexOperation.cpp @@ -14,18 +14,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/***************************************************************************** - * Name: NdbIndexOperation.cpp - * Include: - * Link: - * Author: UABMASD Martin Sköld INN/V Alzato - * Date: 2002-04-01 - * Version: 0.1 - * Description: Secondary index support - * Documentation: - * Adjust: 2002-04-01 UABMASD First version. - ****************************************************************************/ - +#include <ndb_global.h> #include <NdbIndexOperation.hpp> #include <NdbResultSet.hpp> #include <Ndb.hpp> @@ -37,8 +26,6 @@ #include <signaldata/IndxKeyInfo.hpp> #include <signaldata/IndxAttrInfo.hpp> -#define CHECK_NULL(v) assert(v == NULL); v = NULL; - NdbIndexOperation::NdbIndexOperation(Ndb* aNdb) : NdbOperation(aNdb), m_theIndex(NULL), @@ -675,10 +662,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/NdbLinHash.hpp b/ndb/src/ndbapi/NdbLinHash.hpp index f67d4e60200..5d0d52a31d8 100644 --- a/ndb/src/ndbapi/NdbLinHash.hpp +++ b/ndb/src/ndbapi/NdbLinHash.hpp @@ -165,13 +165,14 @@ NdbLinHash<C>::createHashTable() { max = SEGMENTSIZE - 1; slack = SEGMENTSIZE * MAXLOADFCTR; directory[0] = new Segment_t(); - + int i; + /* The first segment cleared before used */ - for(int i = 0; i < SEGMENTSIZE; i++ ) + for(i = 0; i < SEGMENTSIZE; i++ ) directory[0]->elements[i] = 0; /* clear the rest of the directory */ - for( int i = 1; i < DIRECTORYSIZE; i++) + for(i = 1; i < DIRECTORYSIZE; i++) directory[i] = 0; } @@ -203,7 +204,8 @@ NdbLinHash<C>::insertKey( const char* str, Uint32 len, Uint32 lkey1, C* data ) * chain=chainp will copy the contents of HASH_T into chain */ NdbElement_t<C> * oldChain = 0; - for(NdbElement_t<C> * chain = *chainp; chain != 0; chain = chain->next){ + NdbElement_t<C> * chain; + for(chain = *chainp; chain != 0; chain = chain->next){ if(chain->len == len && !memcmp(chain->str, str, len)) return -1; /* Element already exists */ else @@ -211,7 +213,7 @@ NdbLinHash<C>::insertKey( const char* str, Uint32 len, Uint32 lkey1, C* data ) } /* New entry */ - NdbElement_t<C> * chain = new NdbElement_t<C>(); + chain = new NdbElement_t<C>(); chain->len = len; chain->hash = hash; chain->localkey1 = lkey1; diff --git a/ndb/src/ndbapi/NdbOperation.cpp b/ndb/src/ndbapi/NdbOperation.cpp index e6031a58c5f..18a7d1d1c80 100644 --- a/ndb/src/ndbapi/NdbOperation.cpp +++ b/ndb/src/ndbapi/NdbOperation.cpp @@ -14,20 +14,9 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - -/***************************************************************************** - * Name: NdbOperation.C - * Include: - * Link: - * Author: UABMNST Mona Natterkvist UAB/B/SD - * Date: 970829 - * Version: 0.1 - * Description: Interface between TIS and NDB - * Documentation: - * Adjust: 971022 UABMNST First version. - ****************************************************************************/ -#include "NdbConnection.hpp" -#include "NdbOperation.hpp" +#include <ndb_global.h> +#include <NdbConnection.hpp> +#include <NdbOperation.hpp> #include "NdbApiSignal.hpp" #include "NdbRecAttr.hpp" #include "NdbUtil.hpp" @@ -55,7 +44,6 @@ NdbOperation::NdbOperation(Ndb* aNdb) : //theTable(aTable), theNdbCon(NULL), theNext(NULL), - theNextScanOp(NULL), theTCREQ(NULL), theFirstATTRINFO(NULL), theCurrentATTRINFO(NULL), @@ -63,8 +51,6 @@ NdbOperation::NdbOperation(Ndb* aNdb) : theAI_LenInCurrAI(0), theFirstKEYINFO(NULL), theLastKEYINFO(NULL), - theFirstRecAttr(NULL), - theCurrentRecAttr(NULL), theFirstLabel(NULL), theLastLabel(NULL), @@ -77,10 +63,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), @@ -96,14 +78,6 @@ 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), theBlobList(NULL) { @@ -167,7 +141,7 @@ NdbOperation::init(NdbTableImpl* tab, NdbConnection* myConnection){ theNdbCon = myConnection; for (Uint32 i=0; i<NDB_MAX_NO_OF_ATTRIBUTES_IN_KEY; i++) for (int j=0; j<3; j++) - theTupleKeyDefined[i][j] = false; + theTupleKeyDefined[i][j] = 0; theFirstATTRINFO = NULL; theCurrentATTRINFO = NULL; @@ -177,13 +151,11 @@ NdbOperation::init(NdbTableImpl* tab, NdbConnection* myConnection){ theTupKeyLen = 0; theNoOfTupKeyDefined = 0; - theTotalCurrAI_Len = 0; - theAI_LenInCurrAI = 0; - theTotalRecAI_Len = 0; theDistrKeySize = 0; theDistributionGroup = 0; - theCurrRecAI_Len = 0; - theAI_ElementLen = 0; + + theTotalCurrAI_Len = 0; + theAI_LenInCurrAI = 0; theStartIndicator = 0; theCommitIndicator = 0; theSimpleIndicator = 0; @@ -193,9 +165,6 @@ NdbOperation::init(NdbTableImpl* tab, NdbConnection* myConnection){ theDistrGroupType = 0; theDistrKeyIndicator = 0; theScanInfo = 0; - theFirstRecAttr = NULL; - theCurrentRecAttr = NULL; - theCurrElemPtr = NULL; theTotalNrOfKeyWordInSignal = 8; theMagicNumber = 0xABCDEF01; theBoundATTRINFO = NULL; @@ -215,6 +184,7 @@ NdbOperation::init(NdbTableImpl* tab, NdbConnection* myConnection){ tcKeyReq->scanInfo = 0; theKEYINFOptr = &tcKeyReq->keyInfo[0]; theATTRINFOptr = &tcKeyReq->attrInfo[0]; + theReceiver.init(NdbReceiver::NDB_OPERATION, this); return 0; } @@ -229,8 +199,6 @@ NdbOperation::release() { NdbApiSignal* tSignal; NdbApiSignal* tSaveSignal; - NdbRecAttr* tRecAttr; - NdbRecAttr* tSaveRecAttr; NdbBranch* tBranch; NdbBranch* tSaveBranch; NdbLabel* tLabel; @@ -265,15 +233,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; @@ -321,19 +280,19 @@ NdbOperation::release() theNdb->releaseNdbBlob(tSaveBlob); } theBlobList = NULL; - releaseScan(); + theReceiver.release(); } 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 @@ -441,18 +400,6 @@ 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); -} - const char* NdbOperation::getTableName() const { diff --git a/ndb/src/ndbapi/NdbOperationDefine.cpp b/ndb/src/ndbapi/NdbOperationDefine.cpp index 69a6602fe65..08ed6e84271 100644 --- a/ndb/src/ndbapi/NdbOperationDefine.cpp +++ b/ndb/src/ndbapi/NdbOperationDefine.cpp @@ -34,6 +34,7 @@ #include "NdbUtil.hpp" #include "NdbOut.hpp" #include "NdbImpl.hpp" +#include <NdbIndexScanOperation.hpp> #include "NdbBlob.hpp" #include <Interpreter.hpp> @@ -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(); + ((NdbIndexScanOperation*)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 @@ -632,47 +576,6 @@ NdbOperation::getBlobHandle(NdbConnection* aCon, const NdbColumnImpl* tAttrInfo) return tBlob; } -/* - * 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 d00c527550d..7ee76bf2f3e 100644 --- a/ndb/src/ndbapi/NdbOperationExec.cpp +++ b/ndb/src/ndbapi/NdbOperationExec.cpp @@ -14,18 +14,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - -/*************************************************************************** -Name: NdbOperationExec.C -Include: -Link: -Author: UABRONM Mikael Ronström UAB/M/MT Jonas Kamf UAB/M/MT -Date: 2001-10-16 -Version: 1.2 -Description: -Documentation: -***************************************************************************/ - +#include <ndb_global.h> #include <NdbOperation.hpp> #include <NdbConnection.hpp> #include "NdbApiSignal.hpp" @@ -46,83 +35,6 @@ Documentation: #include <NdbOut.hpp> -/****************************************************************************** -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) @@ -178,62 +90,6 @@ NdbOperation::doSend(int aNodeId, Uint32 lastFlag) }//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 +313,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 +336,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 +504,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 +572,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 e61fc5b05d7..3a7e0dda85e 100644 --- a/ndb/src/ndbapi/NdbOperationInt.cpp +++ b/ndb/src/ndbapi/NdbOperationInt.cpp @@ -33,6 +33,7 @@ Adjust: 991029 UABRONM First version. #include "NdbRecAttr.hpp" #include "NdbUtil.hpp" #include "Interpreter.hpp" +#include <NdbIndexScanOperation.hpp> #ifdef VM_TRACE #include <NdbEnv.h> @@ -43,6 +44,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) { @@ -191,7 +217,7 @@ NdbOperation::initial_interpreterCheck() { if ((theInterpretIndicator == 1)) { if (theStatus == SetBound) { - saveBoundATTRINFO(); + ((NdbIndexScanOperation*)this)->saveBoundATTRINFO(); theStatus = GetValue; } if (theStatus == ExecInterpretedValue) { @@ -382,9 +408,7 @@ NdbOperation::incValue(const NdbColumnImpl* tNdbColumnImpl, Uint64 aValue) // Load aValue into register 7 if (insertATTRINFO( Interpreter::LoadConst64(7)) == -1) goto incValue_error1; - if (insertATTRINFO((Uint32)(aValue >> 32)) == -1) - goto incValue_error1; - if (insertATTRINFO(Uint32(aValue & 0xFFFFFFFF)) == -1) + if (insertATTRINFOloop((Uint32*)&aValue, 2) == -1) goto incValue_error1; // Add register 6 and 7 and put result in register 7 if (insertATTRINFO( Interpreter::Add(7, 6, 7)) == -1) @@ -425,9 +449,7 @@ NdbOperation::subValue(const NdbColumnImpl* tNdbColumnImpl, Uint64 aValue) // Load aValue into register 7 if (insertATTRINFO( Interpreter::LoadConst64(7)) == -1) goto subValue_error1; - if (insertATTRINFO((Uint32)(aValue >> 32)) == -1) - goto subValue_error1; - if (insertATTRINFO(Uint32(aValue & 0xFFFFFFFF)) == -1) + if (insertATTRINFOloop((Uint32*)&aValue, 2) == -1) goto subValue_error1; // Subtract register 6 and 7 and put result in register 7 if (insertATTRINFO( Interpreter::Sub(7, 6, 7)) == -1) @@ -664,8 +686,6 @@ int NdbOperation::load_const_u64(Uint32 RegDest, Uint64 Constant) { INT_DEBUG(("load_const_u64 %u %llu", RegDest, Constant)); - Uint32 tTemp1; - Uint32 tTemp2; if (initial_interpreterCheck() == -1) return -1; if (RegDest >= 8) @@ -673,15 +693,11 @@ NdbOperation::load_const_u64(Uint32 RegDest, Uint64 Constant) setErrorCodeAbort(4229); return -1; } - tTemp1 = (Uint32)(Constant & 0xFFFFFFFF); - tTemp2 = (Uint32)(Constant >> 32); - + // 64 bit value if (insertATTRINFO( Interpreter::LoadConst64(RegDest)) == -1) return -1; - if (insertATTRINFO(tTemp1) == -1) - return -1; - if (insertATTRINFO(tTemp2) == -1) + if (insertATTRINFOloop((Uint32*)&Constant, 2) == -1) return -1; theErrorLine++; return 0; diff --git a/ndb/src/ndbapi/NdbOperationScan.cpp b/ndb/src/ndbapi/NdbOperationScan.cpp index 299e6f2adea..283eb591bdb 100644 --- a/ndb/src/ndbapi/NdbOperationScan.cpp +++ b/ndb/src/ndbapi/NdbOperationScan.cpp @@ -14,590 +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 <signaldata/TcKeyReq.hpp> -#include <signaldata/ScanTab.hpp> -#include <signaldata/ScanFrag.hpp> -#include <signaldata/KeyInfo.hpp> - - -/****************************************************************************** - * int openScanRead(); - *****************************************************************************/ -int -NdbOperation::openScanRead(Uint32 aParallelism) -{ - aParallelism = checkParallelism(aParallelism); - - if ((theNdbCon->theCommitStatus != NdbConnection::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 != NdbConnection::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 != NdbConnection::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 != NdbConnection::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; - } - } - } - - // create blob handles automatically - if (opType == DeleteRequest && m_currentTable->m_noOfBlobs != 0) { - for (unsigned i = 0; i < m_currentTable->m_columns.size(); i++) { - NdbColumnImpl* c = m_currentTable->m_columns[i]; - assert(c != 0); - if (c->getBlobType()) { - if (newOp->getBlobHandle(updateTrans, c) == NULL) - return NULL; - } - } - } - - return newOp; -} - -int -NdbOperation::getKeyFromKEYINFO20(Uint32* data, unsigned size) -{ - const NdbScanReceiver* tScanRec = theNdbCon->thePreviousScanRec; - NdbApiSignal* tSignal = tScanRec->theFirstKEYINFO20_Recv; - unsigned pos = 0; - unsigned n = 0; - while (pos < size) { - if (n == 20) { - tSignal = tSignal->next(); - n = 0; - } - const unsigned h = KeyInfo20::HeaderLength; - data[pos++] = tSignal->getDataPtrSend()[h + n++]; - } - return 0; -} diff --git a/ndb/src/ndbapi/NdbRecAttr.cpp b/ndb/src/ndbapi/NdbRecAttr.cpp index 0ed2ff4e796..2e753f13006 100644 --- a/ndb/src/ndbapi/NdbRecAttr.cpp +++ b/ndb/src/ndbapi/NdbRecAttr.cpp @@ -29,6 +29,7 @@ Adjust: 971206 UABRONM First version #include <ndb_global.h> #include <NdbOut.hpp> #include <NdbRecAttr.hpp> +#include <NdbBlob.hpp> #include "NdbDictionaryImpl.hpp" #include <NdbTCP.h> @@ -60,6 +61,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 @@ -128,78 +131,117 @@ NdbRecAttr::clone() const { return ret; } -NdbOut& operator<<(NdbOut& ndbout, const NdbRecAttr &r) +bool +NdbRecAttr::receive_data(const Uint32 * data, Uint32 sz){ + const Uint32 n = (theAttrSize * theArraySize + 3) >> 2; + if(n == sz){ + theNULLind = 0; + if(!copyoutRequired()) + memcpy(theRef, data, 4 * sz); + else + memcpy(theValue, data, theAttrSize * theArraySize); + return true; + } else if(sz == 0){ + setNULL(); + return true; + } + return false; +} + +NdbOut& operator<<(NdbOut& out, const NdbRecAttr &r) { if (r.isNULL()) { - ndbout << "[NULL]"; - return ndbout; + out << "[NULL]"; + return out; } if (r.arraySize() > 1) - ndbout << "["; + out << "["; for (Uint32 j = 0; j < r.arraySize(); j++) { if (j > 0) - ndbout << " "; + out << " "; switch(r.getType()) { case NdbDictionary::Column::Bigunsigned: - ndbout << r.u_64_value(); + out << r.u_64_value(); break; case NdbDictionary::Column::Unsigned: - ndbout << r.u_32_value(); + out << r.u_32_value(); break; case NdbDictionary::Column::Smallunsigned: - ndbout << r.u_short_value(); + out << r.u_short_value(); break; case NdbDictionary::Column::Tinyunsigned: - ndbout << (unsigned) r.u_char_value(); + out << (unsigned) r.u_char_value(); break; case NdbDictionary::Column::Bigint: - ndbout << r.int64_value(); + out << r.int64_value(); break; case NdbDictionary::Column::Int: - ndbout << r.int32_value(); + out << r.int32_value(); break; case NdbDictionary::Column::Smallint: - ndbout << r.short_value(); + out << r.short_value(); break; case NdbDictionary::Column::Tinyint: - ndbout << (int) r.char_value(); + out << (int) r.char_value(); break; case NdbDictionary::Column::Char: - ndbout.print("%.*s", r.arraySize(), r.aRef()); + out.print("%.*s", r.arraySize(), r.aRef()); j = r.arraySize(); break; case NdbDictionary::Column::Varchar: { short len = ntohs(r.u_short_value()); - ndbout.print("%.*s", len, r.aRef()+2); + out.print("%.*s", len, r.aRef()+2); } j = r.arraySize(); break; case NdbDictionary::Column::Float: - ndbout << r.float_value(); + out << r.float_value(); break; case NdbDictionary::Column::Double: - ndbout << r.double_value(); + out << r.double_value(); break; + case NdbDictionary::Column::Blob: + { + const NdbBlob::Head* h = (const NdbBlob::Head*)r.aRef(); + out << h->length << ":"; + const unsigned char* p = (const unsigned char*)(h + 1); + unsigned n = r.arraySize() - sizeof(*h); + for (unsigned k = 0; k < n && k < h->length; k++) + out.print("%02X", (int)p[k]); + j = r.arraySize(); + } + break; + case NdbDictionary::Column::Text: + { + const NdbBlob::Head* h = (const NdbBlob::Head*)r.aRef(); + out << h->length << ":"; + const unsigned char* p = (const unsigned char*)(h + 1); + unsigned n = r.arraySize() - sizeof(*h); + for (unsigned k = 0; k < n && k < h->length; k++) + out.print("%c", (int)p[k]); + j = r.arraySize(); + } + break; default: /* no print functions for the rest, just print type */ - ndbout << r.getType(); + out << r.getType(); j = r.arraySize(); if (j > 1) - ndbout << " %u times" << j; + out << " " << j << " times"; break; } } if (r.arraySize() > 1) { - ndbout << "]"; + out << "]"; } - return ndbout; + return out; } diff --git a/ndb/src/ndbapi/NdbReceiver.cpp b/ndb/src/ndbapi/NdbReceiver.cpp index 4c461698a4a..bdb5e6c7e78 100644 --- a/ndb/src/ndbapi/NdbReceiver.cpp +++ b/ndb/src/ndbapi/NdbReceiver.cpp @@ -16,6 +16,10 @@ #include "NdbImpl.hpp" #include <NdbReceiver.hpp> +#include "NdbDictionaryImpl.hpp" +#include <NdbRecAttr.hpp> +#include <AttributeHeader.hpp> +#include <NdbConnection.hpp> NdbReceiver::NdbReceiver(Ndb *aNdb) : theMagicNumber(0), @@ -24,8 +28,19 @@ NdbReceiver::NdbReceiver(Ndb *aNdb) : m_type(NDB_UNINITIALIZED), m_owner(0) { + theCurrentRecAttr = theFirstRecAttr = 0; + m_defined_rows = 0; + m_rows = new NdbRecAttr*[0]; } +NdbReceiver::~NdbReceiver() +{ + if (m_id != NdbObjectIdMap::InvalidId) { + m_ndb->theNdbObjectIdMap->unmap(m_id, this); + } + delete[] m_rows; +} + void NdbReceiver::init(ReceiverType type, void* owner) { @@ -36,11 +51,175 @@ NdbReceiver::init(ReceiverType type, void* owner) if (m_ndb) m_id = m_ndb->theNdbObjectIdMap->map(this); } + + theFirstRecAttr = NULL; + theCurrentRecAttr = NULL; +} + +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() +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){ + if(rows > m_defined_rows){ + delete[] m_rows; + 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 + } + m_key_info = key_size; + + for(Uint32 i = 0; i<rows; i++){ + NdbRecAttr * prev = theCurrentRecAttr; + assert(prev == 0 || i > 0); + + // Put key-recAttr fir on each row + if(key_size && !getValue(&key, (char*)0)){ + abort(); + return ; // -1 + } + + NdbRecAttr* tRecAttr = org->theFirstRecAttr; + while(tRecAttr != 0){ + if(getValue(&NdbColumnImpl::getImpl(*tRecAttr->m_column), (char*)0) != 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(), src->isNULL() ? 0 : len); + src = src->next(); + dst = dst->next(); + } +} + +int +NdbReceiver::execTRANSID_AI(const Uint32* aDataPtr, Uint32 aLength) { - if (m_id != NdbObjectIdMap::InvalidId) { - m_ndb->theNdbObjectIdMap->unmap(m_id, this); + bool ok = true; + NdbRecAttr* currRecAttr = theCurrentRecAttr; + + 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(); + currRecAttr = currRecAttr->next(); + } + + if(ok && currRecAttr && currRecAttr->receive_data(aDataPtr, tAttrSize)){ + used += tAttrSize; + aDataPtr += tAttrSize; + currRecAttr = currRecAttr->next(); + } else { + ndbout_c("%p: ok: %d tAttrId: %d currRecAttr: %p", + this,ok, tAttrId, currRecAttr); + currRecAttr = theCurrentRecAttr; + while(currRecAttr != 0){ + ndbout_c("%d ", currRecAttr->attrId()); + currRecAttr = currRecAttr->next(); + } + 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 65ed43f60d8..f270584d227 100644 --- a/ndb/src/ndbapi/NdbResultSet.cpp +++ b/ndb/src/ndbapi/NdbResultSet.cpp @@ -29,8 +29,9 @@ #include <Ndb.hpp> #include <NdbConnection.hpp> #include <NdbResultSet.hpp> +#include <NdbBlob.hpp> -NdbResultSet::NdbResultSet(NdbCursorOperation *owner) +NdbResultSet::NdbResultSet(NdbScanOperation *owner) : m_operation(owner) { } @@ -45,7 +46,25 @@ void NdbResultSet::init() int NdbResultSet::nextResult(bool fetchAllowed) { - return m_operation->nextResult(fetchAllowed); + int res; + if ((res = m_operation->nextResult(fetchAllowed)) == 0) { + // handle blobs + NdbBlob* tBlob = m_operation->theBlobList; + while (tBlob != 0) { + if (tBlob->atNextResult() == -1) + return -1; + tBlob = tBlob->theNext; + } + /* + * Flush blob part ops on behalf of user because + * - nextResult is analogous to execute(NoCommit) + * - user is likely to want blob value before next execute + */ + if (m_operation->m_transConnection->executePendingBlobOps() == -1) + return -1; + return 0; + } + return res; } void NdbResultSet::close() @@ -55,52 +74,30 @@ 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(NdbOperation::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(NdbOperation::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(NdbOperation::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(NdbOperation::DeleteRequest, takeOverTrans); if(res == 0) return -1; return 0; } + +int +NdbResultSet::restart(){ + return m_operation->restart(); +} diff --git a/ndb/src/ndbapi/NdbScanFilter.cpp b/ndb/src/ndbapi/NdbScanFilter.cpp index 9542b226d7d..3813ab139de 100644 --- a/ndb/src/ndbapi/NdbScanFilter.cpp +++ b/ndb/src/ndbapi/NdbScanFilter.cpp @@ -337,7 +337,6 @@ static const tab2 table2[] = { const int tab_sz = sizeof(table)/sizeof(table[0]); const int tab2_sz = sizeof(table2)/sizeof(table2[0]); -template<typename T> int matchType(const NdbDictionary::Column * col){ return 1; @@ -382,7 +381,7 @@ NdbScanFilterImpl::cond_col_const(Interpreter::BinaryCondition op, return -1; } - if(!matchType<T>(col)){ + if(!matchType(col)){ /** * Code not reached */ @@ -777,3 +776,10 @@ main(void){ return 0; } #endif + +template class Vector<NdbScanFilterImpl::State>; +#if __SUNPRO_CC != 0x560 +template int NdbScanFilterImpl::cond_col_const(Interpreter::BinaryCondition, Uint32 attrId, Uint32); +template int NdbScanFilterImpl::cond_col_const(Interpreter::BinaryCondition, Uint32 attrId, Uint64); +#endif + diff --git a/ndb/src/ndbapi/NdbScanOperation.cpp b/ndb/src/ndbapi/NdbScanOperation.cpp index cc090ac0364..0aa40f968bb 100644 --- a/ndb/src/ndbapi/NdbScanOperation.cpp +++ b/ndb/src/ndbapi/NdbScanOperation.cpp @@ -14,49 +14,62 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/***************************************************************************** - * Name: NdbScanOperation.cpp - * Include: - * Link: - * Author: UABMASD Martin Sköld INN/V Alzato - * Date: 2002-04-01 - * Version: 0.1 - * Description: Table scan support - * Documentation: - * Adjust: 2002-04-01 UABMASD First version. - ****************************************************************************/ - #include <ndb_global.h> #include <Ndb.hpp> #include <NdbScanOperation.hpp> +#include <NdbIndexScanOperation.hpp> #include <NdbConnection.hpp> #include <NdbResultSet.hpp> #include "NdbApiSignal.hpp" #include <NdbOut.hpp> #include "NdbDictionaryImpl.hpp" -#include "NdbBlob.hpp" + +#include <NdbRecAttr.hpp> +#include <NdbReceiver.hpp> + +#include <stdlib.h> +#include <NdbSqlUtil.hpp> + +#include <signaldata/ScanTab.hpp> +#include <signaldata/KeyInfo.hpp> +#include <signaldata/TcKeyReq.hpp> 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; + m_array = new Uint32[1]; // skip if on delete in fix_receivers } NdbScanOperation::~NdbScanOperation() { - if (m_setValueList) delete m_setValueList; + for(Uint32 i = 0; i<m_allocated_receivers; i++){ + theNdb->releaseNdbScanRec(m_receivers[i]); + } + delete[] m_array; + 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; @@ -91,288 +104,543 @@ NdbScanOperation::init(NdbTableImpl* tab, NdbConnection* myConnection) setErrorCodeAbort(theNdb->getNdbError().code); 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 parallel) { - int res = 0; + m_ordered = 0; + + Uint32 fragCount = m_currentTable->m_fragmentCount; + + if (batch + parallel == 0) { + batch = 16; + parallel= fragCount; + } else { + if (batch == 0 && parallel > 0) { // Backward + batch = (parallel >= 16 ? 16 : parallel); + parallel = (parallel + 15) / 16; + } + if (parallel > fragCount || parallel == 0) + parallel = fragCount; + } + + // 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_CommittedRead: + lockExcl = false; + lockHoldMode = false; + readCommitted = true; break; default: - res = -1; setErrorCode(4003); + return 0; } - if(res == -1){ - return NULL; - } - theNdbCon->theFirstOpInList = 0; - theNdbCon->theLastOpInList = 0; - return getResultSet(); -} + m_keyInfo = lockExcl; -int NdbScanOperation::updateTuples(Uint32 parallelism) -{ - if (openScanExclusive(parallelism) == -1) { - return -1; + bool range = false; + if (m_accessTable->m_indexType == NdbDictionary::Index::OrderedIndex || + m_accessTable->m_indexType == NdbDictionary::Index::UniqueOrderedIndex){ + if (m_currentTable == m_accessTable){ + // Old way of scanning indexes, should not be allowed + m_currentTable = theNdb->theDictionary-> + getTable(m_currentTable->m_primaryTable.c_str()); + assert(m_currentTable != NULL); + } + assert (m_currentTable != m_accessTable); + // Modify operation state + theStatus = SetBound; + theOperationType = OpenRangeScanRequest; + range = true; } - theNdbCon->theFirstOpInList = 0; - theNdbCon->theLastOpInList = 0; - - m_updateOp = true; - - return 0; -} + + theParallelism = parallel; + theBatchSize = batch; -int NdbScanOperation::deleteTuples(Uint32 parallelism) -{ - if (openScanExclusive(parallelism) == -1) { - return -1; + if(fix_receivers(parallel) == -1){ + setErrorCodeAbort(4000); + return 0; } - 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; + 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, parallel); + ScanTabReq::setScanBatch(reqInfo, batch); + ScanTabReq::setLockMode(reqInfo, lockExcl); + ScanTabReq::setHoldLockFlag(reqInfo, lockHoldMode); + ScanTabReq::setReadCommittedFlag(reqInfo, readCommitted); + ScanTabReq::setRangeScanFlag(reqInfo, range); + req->requestInfo = reqInfo; - m_setValueList->add(anAttrName, aValue); - return 0; -} + Uint64 transId = theNdbCon->getTransactionId(); + req->transId1 = (Uint32) transId; + req->transId2 = (Uint32) (transId >> 32); -int NdbScanOperation::setValue(const char* anAttrName, double aValue) -{ - // Check if attribute exist - if (m_currentTable->getColumn(anAttrName) == NULL) - return -1; + getFirstATTRINFOScan(); - m_setValueList->add(anAttrName, aValue); - return 0; + return getResultSet(); } - -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); +int +NdbScanOperation::fix_receivers(Uint32 parallel){ + assert(parallel > 0); + if(parallel > m_allocated_receivers){ + const Uint32 sz = parallel * (4*sizeof(char*)+sizeof(Uint32)); + + Uint32 * tmp = new Uint32[(sz+3)/4]; + // Save old receivers + memcpy(tmp+parallel, m_receivers, m_allocated_receivers*sizeof(char*)); + delete[] m_array; + m_array = tmp; + + m_prepared_receivers = tmp; + m_receivers = (NdbReceiver**)(tmp + parallel); + m_api_receivers = m_receivers + parallel; + m_conf_receivers = m_api_receivers + parallel; + m_sent_receivers = m_conf_receivers + parallel; + + // Only get/init "new" receivers + NdbReceiver* tScanRec; + for (Uint32 i = m_allocated_receivers; i < parallel; i ++) { + tScanRec = theNdb->getNdbScanRec(); + if (tScanRec == NULL) { + setErrorCodeAbort(4000); + return -1; + }//if + m_receivers[i] = tScanRec; + tScanRec->init(NdbReceiver::NDB_SCANRECEIVER, this); + } + m_allocated_receivers = parallel; + } + + for(Uint32 i = 0; i<parallel; i++){ + m_receivers[i]->m_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; + } + + m_api_receivers_count = 0; + m_current_api_receiver = 0; + m_sent_receivers_count = parallel; + m_conf_receivers_count = 0; 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; +/** + * Move receiver from send array to conf:ed array + */ +void +NdbScanOperation::receiver_delivered(NdbReceiver* tRec){ + if(theError.code == 0){ + 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; + } } -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; +/** + * Remove receiver as it's completed + */ +void +NdbScanOperation::receiver_completed(NdbReceiver* tRec){ + if(theError.code == 0){ + 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 NdbScanOperation::setValue(Uint32 anAttrId, Uint64 aValue) +/***************************************************************************** + * 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() { - // Check if attribute exist - if (m_currentTable->getColumn(anAttrId) == NULL) - return -1; - - m_setValueList->add(anAttrId, aValue); - return 0; -} + NdbApiSignal* tSignal; -int NdbScanOperation::setValue(Uint32 anAttrId, Int64 aValue) -{ - // Check if attribute exist - if (m_currentTable->getColumn(anAttrId) == NULL) - return -1; + 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); - 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; +/** + * Constats for theTupleKeyDefined[][0] + */ +#define SETBOUND_EQ 1 +#define FAKE_PTR 2 +#define API_PTR 3 - m_setValueList->add(anAttrId, aValue); - return 0; -} -int NdbScanOperation::setValue(Uint32 anAttrId, double aValue) +/* + * After setBound() are done, move the accumulated ATTRINFO signals to + * a separate list. Then continue with normal scan. + */ +int +NdbIndexScanOperation::saveBoundATTRINFO() { - // Check if attribute exist - if (m_currentTable->getColumn(anAttrId) == NULL) - return -1; - - m_setValueList->add(anAttrId, aValue); - return 0; + 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){ + + /** + * If setBound EQ + */ + Uint32 i = 0; + while(theTupleKeyDefined[i][0] == SETBOUND_EQ) + i++; + + + Uint32 cnt = m_accessTable->getNoOfColumns() - 1; + m_sort_columns = cnt - i; + for(; i<cnt; i++){ + NdbColumnImpl* key = m_accessTable->m_index->m_columns[i]; + NdbColumnImpl* col = m_currentTable->getColumn(key->m_keyInfoPos); + NdbRecAttr* tmp = NdbScanOperation::getValue_impl(col, (char*)-1); + UintPtr newVal = UintPtr(tmp); + theTupleKeyDefined[i][0] = FAKE_PTR; + theTupleKeyDefined[i][1] = (newVal & 0xFFFFFFFF); +#if (SIZEOF_CHARP == 8) + theTupleKeyDefined[i][2] = (newVal >> 32); +#endif + } + } + return res; } -NdbBlob* -NdbScanOperation::getBlobHandle(const char* anAttrName) -{ - return NdbOperation::getBlobHandle(m_transConnection, m_currentTable->getColumn(anAttrName)); -} +#define WAITFOR_SCAN_TIMEOUT 120000 -NdbBlob* -NdbScanOperation::getBlobHandle(Uint32 anAttrId) -{ - return NdbOperation::getBlobHandle(m_transConnection, m_currentTable->getColumn(anAttrId)); +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 = NdbConnection::Aborted; + }//if + return -1; } -// Private methods +#define DEBUG_NEXT_RESULT 0 -int NdbScanOperation::executeCursor(int ProcessorId) +int NdbScanOperation::nextResult(bool fetchAllowed) { - 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(); + 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; + + if(DEBUG_NEXT_RESULT) + ndbout_c("nextResult(%d) idx=%d last=%d", fetchAllowed, idx, last); + + /** + * Check next buckets + */ + for(; idx < last; idx++){ + NdbReceiver* tRec = m_api_receivers[idx]; + if(tRec->nextResult()){ + tRec->copyout(theReceiver); + retVal = 0; + break; + } + } + + /** + * We have advanced atleast one bucket + */ + if(!fetchAllowed || !retVal){ + m_current_api_receiver = idx; + if(DEBUG_NEXT_RESULT) ndbout_c("return %d", retVal); + 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 { + if(theError.code){ + setErrorCode(theError.code); + if(DEBUG_NEXT_RESULT) ndbout_c("return -1"); + return -1; } - else if (m_deleteOp) { - newOp = takeOverScanOp(DeleteRequest, m_transConnection); - // newOp->deleteTuple(); + + Uint32 cnt = m_conf_receivers_count; + Uint32 sent = m_sent_receivers_count; + + if(DEBUG_NEXT_RESULT) + ndbout_c("idx=%d last=%d cnt=%d sent=%d", idx, last, cnt, sent); + + 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 = -2; //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)) { + theError.code = -1; // make sure user gets error if he tries again + if(DEBUG_NEXT_RESULT) ndbout_c("return 1"); + return 1; + } + retVal = -1; //return_code; + } else { + retVal = -3; + } + idx = last; } -#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); + + if(retVal == 0) + break; + + for(; idx < last; idx++){ + NdbReceiver* tRec = m_api_receivers[idx]; + if(tRec->nextResult()){ + tRec->copyout(theReceiver); + retVal = 0; + break; + } } -#else - m_transConnection->execute(NoCommit); -#endif - } - closeScan(); + } while(retVal == 2); + } else { + retVal = -3; } - - return result; + + m_api_receivers_count = last; + m_current_api_receiver = idx; + + switch(retVal){ + case 0: + case 1: + case 2: + if(DEBUG_NEXT_RESULT) ndbout_c("return %d", retVal); + 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; + if(DEBUG_NEXT_RESULT) ndbout_c("return -1", retVal); + 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 (result == 0) { - // handle blobs - NdbBlob* tBlob = theBlobList; - while (tBlob != NULL) { - if (tBlob->atNextResult() == -1) - return -1; - tBlob = tBlob->theNext; +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; i<cnt; i++){ + NdbReceiver * tRec = m_api_receivers[i]; + m_sent_receivers[last+i] = tRec; + tRec->m_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 result; + return 0; } int NdbScanOperation::prepareSend(Uint32 TC_ConnectPtr, Uint64 TransactionId) { printf("NdbScanOperation::prepareSend\n"); + abort(); return 0; } @@ -385,300 +653,834 @@ NdbScanOperation::doSend(int ProcessorId) void NdbScanOperation::closeScan() { - if(theNdbCon){ - if (theNdbCon->stopScan() == -1) - theError = theNdbCon->getNdbError(); - theNdb->closeTransaction(theNdbCon); - theNdbCon = 0; - } + if(m_transConnection) do { + if(DEBUG_NEXT_RESULT) + ndbout_c("closeScan() theError.code = %d " + "m_api_receivers_count = %d " + "m_conf_receivers_count = %d " + "m_sent_receivers_count = %d", + theError.code, + m_api_receivers_count, + m_conf_receivers_count, + m_sent_receivers_count); + + 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; + } + + while(theError.code == 0 && 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_api_receivers_count = 0; + m_conf_receivers_count = 0; + m_sent_receivers_count = 0; + theNdbCon->theReleaseOnClose = true; + } + } + + if(m_api_receivers_count+m_conf_receivers_count){ + // Send close scan + send_next_scan(0, true); // Close scan + } + + /** + * wait for close scan conf + */ + while(m_sent_receivers_count+m_api_receivers_count+m_conf_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_api_receivers_count = 0; + m_conf_receivers_count = 0; + m_sent_receivers_count = 0; + } + } + } while(0); + + theNdbCon->theScanningOp = 0; + theNdb->closeTransaction(theNdbCon); + + theNdbCon = 0; m_transConnection = NULL; } -void NdbScanOperation::release(){ - closeScan(); - NdbCursorOperation::release(); +void +NdbScanOperation::execCLOSE_SCAN_REP(){ + 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; i<m_allocated_receivers; i++){ + m_receivers[i]->release(); } } -void SetValueRecList::add(const char* anAttrName, Int32 aValue) -{ - SetValueRec* newSetValueRec = new SetValueRec(); +/*************************************************************************** +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 NdbScanOperation::prepareSendScan(Uint32 aTC_ConnectPtr, + Uint64 aTransactionId){ + + if (theInterpretIndicator != 1 || + (theOperationType != OpenScanRequest && + theOperationType != OpenRangeScanRequest)) { + setErrorCodeAbort(4005); + return -1; + } - newSetValueRec->stype = SetValueRec::SET_INT32_ATTR1; - newSetValueRec->anAttrName = strdup(anAttrName); - newSetValueRec->anInt32Value = aValue; - if (!last) - first = last = newSetValueRec; - else { - last->next = newSetValueRec; - last = newSetValueRec; + if (theStatus == SetBound) { + ((NdbIndexScanOperation*)this)->saveBoundATTRINFO(); + theStatus = GetValue; } -} -void SetValueRecList::add(const char* anAttrName, Uint32 aValue) -{ - SetValueRec* newSetValueRec = new SetValueRec(); + theErrorLine = 0; - newSetValueRec->stype = SetValueRec::SET_UINT32_ATTR1; - newSetValueRec->anAttrName = strdup(anAttrName); - newSetValueRec->anUint32Value = 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(); + } + + 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); + + /** + * Prepare all receivers + */ + theReceiver.prepareSend(); + bool keyInfo = m_keyInfo; + Uint32 key_size = keyInfo ? m_currentTable->m_keyLenInWords : 0; + for(Uint32 i = 0; i<theParallelism; i++){ + m_receivers[i]->do_get_value(&theReceiver, theBatchSize, key_size); } + return 0; } -void SetValueRecList::add(const char* anAttrName, Int64 aValue) +/****************************************************************************** +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 +NdbScanOperation::doSendScan(int aProcessorId) { - SetValueRec* newSetValueRec = new SetValueRec(); + 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 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; + } + } - newSetValueRec->stype = SetValueRec::SET_INT64_ATTR1; - newSetValueRec->anAttrName = strdup(anAttrName); - 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() + +/****************************************************************************** + * 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. + *****************************************************************************/ +int +NdbScanOperation::getKeyFromKEYINFO20(Uint32* data, unsigned size) +{ + Uint32 idx = m_current_api_receiver; + Uint32 last = m_api_receivers_count; + + 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])){ + + const Uint32 * src = (Uint32*)tRecAttr->aRef(); + memcpy(data, src, 4*size); + return 0; } + return -1; } -void SetValueRecList::add(const char* anAttrName, Uint64 aValue) -{ - SetValueRec* newSetValueRec = new SetValueRec(); +NdbOperation* +NdbScanOperation::takeOverScanOp(OperationType opType, NdbConnection* pTrans){ + + Uint32 idx = m_current_api_receiver; + Uint32 last = m_api_receivers_count; + + 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; + } - newSetValueRec->stype = SetValueRec::SET_UINT64_ATTR1; - newSetValueRec->anAttrName = strdup(anAttrName); - newSetValueRec->anUint64Value = aValue; - if (!last) - first = last = newSetValueRec; - else { - last->next = newSetValueRec; - last = newSetValueRec; + // 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); + } + } + // create blob handles automatically + if (opType == DeleteRequest && m_currentTable->m_noOfBlobs != 0) { + for (unsigned i = 0; i < m_currentTable->m_columns.size(); i++) { + NdbColumnImpl* c = m_currentTable->m_columns[i]; + assert(c != 0); + if (c->getBlobType()) { + if (newOp->getBlobHandle(pTrans, c) == NULL) + return NULL; + } + } + } + + return newOp; } + return 0; } -void SetValueRecList::add(const char* anAttrName, float aValue) +NdbBlob* +NdbScanOperation::getBlobHandle(const char* anAttrName) { - SetValueRec* newSetValueRec = new SetValueRec(); + return NdbOperation::getBlobHandle(m_transConnection, + m_currentTable->getColumn(anAttrName)); +} - newSetValueRec->stype = SetValueRec::SET_FLOAT_ATTR1; - newSetValueRec->anAttrName = strdup(anAttrName); - newSetValueRec->aFloatValue = aValue; - if (!last) - first = last = newSetValueRec; - else { - last->next = newSetValueRec; - last = newSetValueRec; - } +NdbBlob* +NdbScanOperation::getBlobHandle(Uint32 anAttrId) +{ + return NdbOperation::getBlobHandle(m_transConnection, + m_currentTable->getColumn(anAttrId)); } -void SetValueRecList::add(const char* anAttrName, double aValue) +NdbIndexScanOperation::NdbIndexScanOperation(Ndb* aNdb) + : NdbScanOperation(aNdb) { - SetValueRec* newSetValueRec = new SetValueRec(); +} - newSetValueRec->stype = SetValueRec::SET_DOUBLE_ATTR1; - newSetValueRec->anAttrName = strdup(anAttrName); - newSetValueRec->aDoubleValue = aValue; - if (!last) - first = last = newSetValueRec; - else { - last->next = newSetValueRec; - last = newSetValueRec; - } +NdbIndexScanOperation::~NdbIndexScanOperation(){ } -void SetValueRecList::add(Uint32 anAttrId, const char* aValue, Uint32 len) +int +NdbIndexScanOperation::setBound(const char* anAttrName, int type, const void* 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; - } + return setBound(m_accessTable->getColumn(anAttrName), type, aValue, len); } -void SetValueRecList::add(Uint32 anAttrId, Int32 aValue) +int +NdbIndexScanOperation::setBound(Uint32 anAttrId, int type, const void* aValue, Uint32 len) { - SetValueRec* newSetValueRec = new SetValueRec(); + return setBound(m_accessTable->getColumn(anAttrId), type, aValue, len); +} - newSetValueRec->stype = SetValueRec::SET_INT32_ATTR2; - newSetValueRec->anAttrId = anAttrId; - newSetValueRec->anInt32Value = aValue; - last->next = newSetValueRec; - last = newSetValueRec; +int +NdbIndexScanOperation::equal_impl(const NdbColumnImpl* anAttrObject, + const char* aValue, + Uint32 len){ + return setBound(anAttrObject, BoundEQ, aValue, len); } -void SetValueRecList::add(Uint32 anAttrId, Uint32 aValue) -{ - SetValueRec* newSetValueRec = new SetValueRec(); +NdbRecAttr* +NdbIndexScanOperation::getValue_impl(const NdbColumnImpl* attrInfo, + char* aValue){ + if(!m_ordered){ + return NdbScanOperation::getValue_impl(attrInfo, aValue); + } + + if (theStatus == SetBound) { + saveBoundATTRINFO(); + theStatus = GetValue; + } - newSetValueRec->stype = SetValueRec::SET_UINT32_ATTR2; - newSetValueRec->anAttrId = anAttrId; - newSetValueRec->anUint32Value = aValue; - if (!last) - first = last = newSetValueRec; - else { - last->next = newSetValueRec; - last = newSetValueRec; + int id = attrInfo->m_attrId; // In "real" table + assert(m_accessTable->m_index); + int sz = (int)m_accessTable->m_index->m_key_ids.size(); + if(id >= sz || (id = m_accessTable->m_index->m_key_ids[id]) == -1){ + return NdbScanOperation::getValue_impl(attrInfo, aValue); + } + + assert(id < NDB_MAX_NO_OF_ATTRIBUTES_IN_KEY); + 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); } + + assert(marker == FAKE_PTR); + + 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; } -void SetValueRecList::add(Uint32 anAttrId, Int64 aValue) +#include <AttributeHeader.hpp> +/* + * Define bound on index column in range scan. + */ +int +NdbIndexScanOperation::setBound(const NdbColumnImpl* tAttrInfo, + int type, const void* aValue, Uint32 len) { - SetValueRec* newSetValueRec = new SetValueRec(); + if (theOperationType == OpenRangeScanRequest && + theStatus == SetBound && + (0 <= type && type <= 4) && + 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 = aValue != NULL ? sizeInBytes : 0; + Uint32 tIndexAttrId = tAttrInfo->m_attrId; + Uint32 sizeInWords = (len + 3) / 4; + AttributeHeader ah(tIndexAttrId, sizeInWords); + insertATTRINFO(ah.m_value); + if (len != 0) { + // 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); + } + } - newSetValueRec->stype = SetValueRec::SET_INT64_ATTR2; - newSetValueRec->anAttrId = anAttrId; - newSetValueRec->anInt64Value = aValue; - if (!last) - first = last = newSetValueRec; - else { - last->next = newSetValueRec; - last = newSetValueRec; + /** + * 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(type == BoundEQ && !theTupleKeyDefined[tIndexAttrId][0]){ + theNoOfTupKeyDefined++; + theTupleKeyDefined[tIndexAttrId][0] = SETBOUND_EQ; + } + + return 0; + } else { + setErrorCodeAbort(4228); // XXX wrong code + return -1; } } -void SetValueRecList::add(Uint32 anAttrId, Uint64 aValue) -{ - SetValueRec* newSetValueRec = new SetValueRec(); +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->getNoOfColumns() - 1; // -1 for NDB$NODE + m_current_api_receiver = m_sent_receivers_count; + m_api_receivers_count = m_sent_receivers_count; + } + return rs; +} - newSetValueRec->stype = SetValueRec::SET_UINT64_ATTR2; - newSetValueRec->anAttrId = anAttrId; - newSetValueRec->anUint64Value = aValue; - if (!last) - first = last = newSetValueRec; - else { - last->next = newSetValueRec; - last = newSetValueRec; +void +NdbIndexScanOperation::fix_get_values(){ + /** + * Loop through all getValues and set buffer pointer to "API" pointer + */ + NdbRecAttr * curr = theReceiver.theFirstRecAttr; + Uint32 cnt = m_accessTable->getNoOfColumns() - 1; + assert(cnt < NDB_MAX_NO_OF_ATTRIBUTES_IN_KEY); + + NdbIndexImpl * idx = m_accessTable->m_index; + NdbTableImpl * tab = m_currentTable; + for(Uint32 i = 0; i<cnt; i++){ + Uint32 val = theTupleKeyDefined[i][0]; + switch(val){ + case FAKE_PTR: + curr->setup(curr->m_column, 0); + case API_PTR: + curr = curr->next(); + break; + case SETBOUND_EQ: + break; +#ifdef VM_TRACE + default: + abort(); +#endif + } } } -void SetValueRecList::add(Uint32 anAttrId, float aValue) -{ - SetValueRec* newSetValueRec = new SetValueRec(); +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]; - newSetValueRec->stype = SetValueRec::SET_FLOAT_ATTR2; - newSetValueRec->anAttrId = anAttrId; - newSetValueRec->aFloatValue = aValue; - if (!last) - first = last = newSetValueRec; - else { - last->next = newSetValueRec; - last = newSetValueRec; + 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; } -void SetValueRecList::add(Uint32 anAttrId, double aValue) -{ - SetValueRec* newSetValueRec = new SetValueRec(); +int +NdbIndexScanOperation::next_result_ordered(bool fetchAllowed){ + + Uint32 u_idx = 0, u_last = 0; + Uint32 s_idx = m_current_api_receiver; // first sorted + Uint32 s_last = theParallelism; // last sorted - newSetValueRec->stype = SetValueRec::SET_DOUBLE_ATTR2; - newSetValueRec->anAttrId = anAttrId; - newSetValueRec->aDoubleValue = aValue; - if (!last) - first = last = newSetValueRec; - else { - last->next = newSetValueRec; - last = newSetValueRec; + NdbReceiver** arr = m_api_receivers; + NdbReceiver* tRec = arr[s_idx]; + + if(DEBUG_NEXT_RESULT) ndbout_c("nextOrderedResult(%d) nextResult: %d", + fetchAllowed, + (s_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 = (s_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(s_idx)){ + Uint32 tmp = m_sent_receivers_count; + s_idx = m_current_api_receiver; + while(m_sent_receivers_count > 0 && !theError.code){ + 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; + } + if(DEBUG_NEXT_RESULT) ndbout_c("return -1"); + return -1; + } + + u_idx = 0; + u_last = m_conf_receivers_count; + 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); + if(theError.code){ + setErrorCode(theError.code); + if(DEBUG_NEXT_RESULT) ndbout_c("return -1"); + return -1; + } + } + } else { + if(DEBUG_NEXT_RESULT) ndbout_c("return 2"); + return 2; + } + } else { + u_idx = s_idx; + u_last = s_idx + 1; + s_idx++; + } + + 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--; } -} -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; + 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; i<s_last; i++) + ndbout_c("%p", arr[i]); + + tRec = m_api_receivers[s_idx]; + if(s_idx < s_last && tRec->nextResult()){ + tRec->copyout(theReceiver); + if(DEBUG_NEXT_RESULT) ndbout_c("return 0"); + return 0; } -} -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; + 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 && + theError.code == 0){ + if(DEBUG_NEXT_RESULT) ndbout_c("return 1"); + return 1; + } + setErrorCode(theError.code); + if(DEBUG_NEXT_RESULT) ndbout_c("return -1"); + return -1; } int -NdbScanOperation::equal_impl(const NdbColumnImpl* anAttrObject, - const char* aValue, - Uint32 len){ - return setBound(anAttrObject, BoundEQ, aValue, len); +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; + m_current_api_receiver = idx + 1; + + Uint32 nodeId = theNdbCon->theDBnode; + TransporterFacade * tp = TransporterFacade::instance(); + tSignal.setLength(4+1); + return tp->sendSignal(&tSignal, nodeId); } +int +NdbScanOperation::restart(){ + TransporterFacade* tp = TransporterFacade::instance(); + Guard guard(tp->theMutexPtr); + + Uint32 seq = theNdbCon->theNodeSequence; + Uint32 nodeId = theNdbCon->theDBnode; + + if(seq != tp->getNodeSequence(nodeId)){ + theNdbCon->theReleaseOnClose = true; + return -1; + } + + 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_api_receivers_count = 0; + m_conf_receivers_count = 0; + m_sent_receivers_count = 0; + return -1; + } + } + + if(m_api_receivers_count+m_conf_receivers_count){ + // Send close scan + if(send_next_scan(0, true) == -1) // Close scan + return -1; + } + + /** + * wait for close scan conf + */ + while(m_sent_receivers_count+m_api_receivers_count+m_conf_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_api_receivers_count = 0; + m_conf_receivers_count = 0; + m_sent_receivers_count = 0; + return -1; + } + } + /** + * Reset receivers + */ + const Uint32 parallell = theParallelism; + + for(Uint32 i = 0; i<parallell; i++){ + m_receivers[i]->m_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; + m_receivers[i]->prepareSend(); + } + + m_api_receivers_count = 0; + m_current_api_receiver = 0; + m_sent_receivers_count = parallell; + m_conf_receivers_count = 0; + + if(m_ordered){ + m_current_api_receiver = parallell; + m_api_receivers_count = parallell; + } + + if (doSendScan(nodeId) == -1) + return -1; + + return 0; +} diff --git a/ndb/src/ndbapi/Ndbif.cpp b/ndb/src/ndbapi/Ndbif.cpp index a05eb4c54c3..7ad37401b9a 100644 --- a/ndb/src/ndbapi/Ndbif.cpp +++ b/ndb/src/ndbapi/Ndbif.cpp @@ -17,11 +17,9 @@ #include "NdbApiSignal.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" @@ -34,6 +32,9 @@ #include <signaldata/CreateIndx.hpp> #include <signaldata/DropIndx.hpp> #include <signaldata/TcIndx.hpp> +#include <signaldata/TransIdAI.hpp> +#include <signaldata/ScanFrag.hpp> +#include <signaldata/ScanTab.hpp> #include <ndb_limits.h> #include <NdbOut.hpp> @@ -41,12 +42,13 @@ /****************************************************************************** - * int init( int aMaxNoOfTransactions ); + * int init( int aNrOfCon, int aNrOfOp ); * * Return Value: Return 0 : init was successful. * Return -1: In all other case. - * Parameters: aMaxNoOfTransactions : Max number of simultaneous transations - * Remark: Create pointers and idle list Synchronous. + * Parameters: aNrOfCon : Number of connections offered to the application. + * aNrOfOp : Number of operations offered to the application. + * Remark: Create pointers and idle list Synchronous. ****************************************************************************/ int Ndb::init(int aMaxNoOfTransactions) @@ -75,7 +77,7 @@ Ndb::init(int aMaxNoOfTransactions) executeMessage, statusMessage); - + if ( tBlockNo == -1 ) { theError.code = 4105; theFacade->unlock_mutex(); @@ -95,6 +97,7 @@ Ndb::init(int aMaxNoOfTransactions) } theFirstTransId = ((Uint64)theNdbBlockNumber << 52)+((Uint64)theNode << 40); + theFirstTransId += theFacade->m_open_count; theFacade->unlock_mutex(); @@ -253,8 +256,7 @@ Ndb::abortTransactionsAfterNodeFailure(Uint16 aNodeId) NdbConnection* localCon = theSentTransactionsArray[i]; if (localCon->getConnectedNodeId() == aNodeId ) { const NdbConnection::SendStatusType sendStatus = localCon->theSendStatus; - if (sendStatus == NdbConnection::sendTC_OP || - sendStatus == NdbConnection::sendTC_COMMIT) { + if (sendStatus == NdbConnection::sendTC_OP || sendStatus == NdbConnection::sendTC_COMMIT) { /* A transaction was interrupted in the prepare phase by a node failure. Since the transaction was not found in the phase @@ -300,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; @@ -328,7 +332,7 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3]) tCon = void2con(tFirstDataPtr); if ((tCon->checkMagicNumber() == 0) && (tCon->theSendStatus == NdbConnection::sendTC_OP)) { - tReturnCode = tCon->receiveTCKEYCONF(keyConf, aSignal->getLength()); + tReturnCode = tCon->receiveTCKEYCONF(keyConf, tLen); if (tReturnCode != -1) { completedTransaction(tCon); }//if @@ -346,111 +350,71 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3]) 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 == NdbConnection::sendTC_OP) { - tReturnCode = tOp->receiveREAD_CONF(tDataPtr, - aSignal->getLength()); - if (tReturnCode != -1) { - completedTransaction(tCon); - }//if - }//if - }//if - }//if + case GSN_TRANSID_AI:{ + tFirstDataPtr = int2void(tFirstData); + NdbReceiver* tRec; + if (tFirstDataPtr && (tRec = void2rec(tFirstDataPtr)) && + 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); + } + + if(com == 1){ + switch(tRec->getType()){ + case NdbReceiver::NDB_OPERATION: + case NdbReceiver::NDB_INDEX_OPERATION: + if(tCon->OpCompleteSuccess() != -1){ + completedTransaction(tCon); + return; + } + break; + case NdbReceiver::NDB_SCANRECEIVER: + tCon->theScanningOp->receiver_delivered(tRec); + theWaiter.m_state = (tWaitState == WAIT_SCAN ? NO_WAIT : tWaitState); + break; + default: + goto InvalidSignal; + } + } + break; + } else { + /** + * This is ok as transaction can have been aborted before TRANSID_AI + * arrives (if TUP on other node than TC) + */ return; } - case GSN_TRANSID_AI: + } + case GSN_TCKEY_FAILCONF: { - void* tFirstDataPtr = int2void(tFirstData); - if (tFirstDataPtr == 0) goto InvalidSignal; - - // ndbout << "*** GSN_TRANSID_AI ***" << endl; - NdbReceiver* tRec = void2rec(tFirstDataPtr); - if (tRec->getType() == NdbReceiver::NDB_OPERATION){ - // tOp = (NdbOperation*)tRec->getOwner(); + tFirstDataPtr = int2void(tFirstData); + const TcKeyFailConf * failConf = (TcKeyFailConf *)tDataPtr; + const BlockReference aTCRef = aSignal->theSendersBlockRef; + if (tFirstDataPtr != 0){ tOp = void2rec_op(tFirstDataPtr); - // ndbout << "NDB_OPERATION" << endl; - if (tOp->checkMagicNumber() == 0) { - tCon = tOp->theNdbCon; - if (tCon != NULL) { - if (tCon->theSendStatus == NdbConnection::sendTC_OP) { - tReturnCode = tOp->receiveTRANSID_AI(tDataPtr, - aSignal->getLength()); - if (tReturnCode != -1) { - completedTransaction(tCon); - break; - } - } - } - } - } 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) { + + if (tOp->checkMagicNumber(false) == 0) { tCon = tOp->theNdbCon; if (tCon != NULL) { - if (tCon->theSendStatus == NdbConnection::sendTC_OP) { - tReturnCode = tOp->receiveTRANSID_AI(tDataPtr, - aSignal->getLength()); + if ((tCon->theSendStatus == NdbConnection::sendTC_OP) || + (tCon->theSendStatus == NdbConnection::sendTC_COMMIT)) { + tReturnCode = tCon->receiveTCKEY_FAILCONF(failConf); 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) { - theWaiter.m_state = NO_WAIT; - break; + }//if + }//if } } } else { -#ifdef NDB_NO_DROPPED_SIGNAL - abort(); +#ifdef VM_TRACE + ndbout_c("Recevied TCKEY_FAILCONF wo/ operation"); #endif - goto InvalidSignal; } - return; - } - case GSN_TCKEY_FAILCONF: - { - void* tFirstDataPtr = int2void(tFirstData); - if (tFirstDataPtr == 0) goto InvalidSignal; - - const TcKeyFailConf * const failConf = (TcKeyFailConf *)tDataPtr; - const BlockReference aTCRef = aSignal->theSendersBlockRef; - - tOp = void2rec_op(tFirstDataPtr); - - if (tOp->checkMagicNumber() == 0) { - tCon = tOp->theNdbCon; - if (tCon != NULL) { - if ((tCon->theSendStatus == NdbConnection::sendTC_OP) || - (tCon->theSendStatus == NdbConnection::sendTC_COMMIT)) { - tReturnCode = tCon->receiveTCKEY_FAILCONF(failConf); - if (tReturnCode != -1) { - completedTransaction(tCon); - }//if - }//if - }//if - }//if - if(tFirstData & 1){ NdbConnection::sendTC_COMMIT_ACK(theCommitAckSignal, failConf->transId1, @@ -461,28 +425,32 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3]) } case GSN_TCKEY_FAILREF: { - 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 == NdbConnection::sendTC_OP) || - (tCon->theSendStatus == NdbConnection::sendTC_ROLLBACK)) { - tReturnCode = tCon->receiveTCKEY_FAILREF(aSignal); - if (tReturnCode != -1) { - completedTransaction(tCon); - return; - }//if - }//if - }//if - }//if - return; + tFirstDataPtr = int2void(tFirstData); + if(tFirstDataPtr != 0){ + tOp = void2rec_op(tFirstDataPtr); + if (tOp->checkMagicNumber() == 0) { + tCon = tOp->theNdbCon; + if (tCon != NULL) { + if ((tCon->theSendStatus == NdbConnection::sendTC_OP) || + (tCon->theSendStatus == NdbConnection::sendTC_ROLLBACK)) { + tReturnCode = tCon->receiveTCKEY_FAILREF(aSignal); + if (tReturnCode != -1) { + completedTransaction(tCon); + return; + }//if + }//if + }//if + }//if + } else { +#ifdef VM_TRACE + ndbout_c("Recevied TCKEY_FAILREF wo/ operation"); +#endif + } + break; } case GSN_TCKEYREF: { - void* tFirstDataPtr = int2void(tFirstData); + tFirstDataPtr = int2void(tFirstData); if (tFirstDataPtr == 0) goto InvalidSignal; tOp = void2rec_op(tFirstDataPtr); @@ -493,8 +461,9 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3]) tReturnCode = tOp->receiveTCKEYREF(aSignal); if (tReturnCode != -1) { completedTransaction(tCon); + return; }//if - return; + break; }//if }//if } //if @@ -503,7 +472,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; @@ -531,7 +500,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); @@ -540,14 +509,13 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3]) tReturnCode = tCon->receiveTC_COMMITREF(aSignal); if (tReturnCode != -1) { completedTransaction(tCon); - return; }//if }//if return; } case GSN_TCROLLBACKCONF: { - void* tFirstDataPtr = int2void(tFirstData); + tFirstDataPtr = int2void(tFirstData); if (tFirstDataPtr == 0) goto InvalidSignal; tCon = void2con(tFirstDataPtr); @@ -562,7 +530,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); @@ -571,14 +539,13 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3]) tReturnCode = tCon->receiveTCROLLBACKREF(aSignal); if (tReturnCode != -1) { completedTransaction(tCon); - return; }//if }//if return; } case GSN_TCROLLBACKREP: { - void* tFirstDataPtr = int2void(tFirstData); + tFirstDataPtr = int2void(tFirstData); if (tFirstDataPtr == 0) goto InvalidSignal; tCon = void2con(tFirstDataPtr); @@ -592,27 +559,27 @@ 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) { - return; + goto InvalidSignal; }//if tCon = void2con(tFirstDataPtr); if (tCon->checkMagicNumber() != 0) { - return; + goto InvalidSignal; }//if tReturnCode = tCon->receiveTCSEIZECONF(aSignal); if (tReturnCode != -1) { theWaiter.m_state = NO_WAIT; } else { - return; + goto InvalidSignal; }//if break; } case GSN_TCSEIZEREF: { - void* tFirstDataPtr = int2void(tFirstData); + tFirstDataPtr = int2void(tFirstData); if (tFirstDataPtr == 0) goto InvalidSignal; if (tWaitState != WAIT_TC_SEIZE) { @@ -632,7 +599,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) { @@ -650,7 +617,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) { @@ -704,84 +671,100 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3]) case GSN_DIHNDBTAMPER: { - void* tFirstDataPtr = int2void(tFirstData); - if (tFirstDataPtr == 0) goto InvalidSignal; - - if (tWaitState != WAIT_NDB_TAMPER) - return; - tCon = void2con(tFirstDataPtr); - if (tCon->checkMagicNumber() != 0) - return; - tReturnCode = tCon->receiveDIHNDBTAMPER(aSignal); - if (tReturnCode != -1) - theWaiter.m_state = NO_WAIT; - break; + tFirstDataPtr = int2void(tFirstData); + if (tFirstDataPtr == 0) goto InvalidSignal; + + if (tWaitState != WAIT_NDB_TAMPER) + return; + tCon = void2con(tFirstDataPtr); + if (tCon->checkMagicNumber() != 0) + return; + tReturnCode = tCon->receiveDIHNDBTAMPER(aSignal); + if (tReturnCode != -1) + theWaiter.m_state = NO_WAIT; + 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 && tWaitState == WAIT_SCAN) + theWaiter.m_state = NO_WAIT; + break; + } else { + goto InvalidSignal; + } } case GSN_SCAN_TABREF: { - void* tFirstDataPtr = int2void(tFirstData); - if (tFirstDataPtr == 0) goto InvalidSignal; - - if (tWaitState == WAIT_SCAN){ + tFirstDataPtr = int2void(tFirstData); + if (tFirstDataPtr == 0) goto InvalidSignal; + tCon = void2con(tFirstDataPtr); + + assert(tFirstDataPtr != 0 && + void2con(tFirstDataPtr)->checkMagicNumber() == 0); + if (tCon->checkMagicNumber() == 0){ tReturnCode = tCon->receiveSCAN_TABREF(aSignal); - if (tReturnCode != -1){ + if (tReturnCode != -1 && tWaitState == WAIT_SCAN){ theWaiter.m_state = NO_WAIT; } break; } - } - goto InvalidSignal; - } - 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); - if (tFirstDataPtr == 0) goto InvalidSignal; - - //ndbout << "*** GSN_KEYINFO20 ***" << endl; - NdbScanReceiver* tScanRec = void2rec_srec(tFirstDataPtr); - if (tScanRec->checkMagicNumber() != 0) + tFirstDataPtr = int2void(tFirstData); + NdbReceiver* tRec; + if (tFirstDataPtr && (tRec = void2rec(tFirstDataPtr)) && + tRec->checkMagicNumber() && (tCon = tRec->getTransaction()) && + tCon->checkState_TransId(&((const KeyInfo20*)tDataPtr)->transId1)){ + + 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 = (tWaitState == WAIT_SCAN ? NO_WAIT : tWaitState); + break; + case 0: + break; + case -1: + goto InvalidSignal; + } + break; + } else { + /** + * This is ok as transaction can have been aborted before KEYINFO20 + * arrives (if TUP on other node than TC) + */ return; - tReturnCode = tScanRec->receiveKEYINFO20(aSignal); - if (tReturnCode != -1) - theWaiter.m_state = NO_WAIT; - break; + } } case GSN_TCINDXCONF:{ - void* tFirstDataPtr = int2void(tFirstData); + tFirstDataPtr = int2void(tFirstData); if (tFirstDataPtr == 0) goto InvalidSignal; const TcIndxConf * const indxConf = (TcIndxConf *)tDataPtr; @@ -789,7 +772,7 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3]) tCon = void2con(tFirstDataPtr); if ((tCon->checkMagicNumber() == 0) && (tCon->theSendStatus == NdbConnection::sendTC_OP)) { - tReturnCode = tCon->receiveTCINDXCONF(indxConf, aSignal->getLength()); + tReturnCode = tCon->receiveTCINDXCONF(indxConf, tLen); if (tReturnCode != -1) { completedTransaction(tCon); }//if @@ -801,10 +784,10 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3]) indxConf->transId2, aTCRef); } - break; + return; } case GSN_TCINDXREF:{ - void* tFirstDataPtr = int2void(tFirstData); + tFirstDataPtr = int2void(tFirstData); if (tFirstDataPtr == 0) goto InvalidSignal; tIndexOp = void2rec_iop(tFirstDataPtr); @@ -865,8 +848,7 @@ Ndb::completedTransaction(NdbConnection* aCon) Uint32 tTransArrayIndex = aCon->theTransArrayIndex; Uint32 tNoSentTransactions = theNoOfSentTransactions; Uint32 tNoCompletedTransactions = theNoOfCompletedTransactions; - if ((tNoSentTransactions > 0) && - (aCon->theListState == NdbConnection::InSendList) && + if ((tNoSentTransactions > 0) && (aCon->theListState == NdbConnection::InSendList) && (tTransArrayIndex < tNoSentTransactions)) { NdbConnection* tMoveCon = theSentTransactionsArray[tNoSentTransactions - 1]; @@ -895,8 +877,8 @@ Ndb::completedTransaction(NdbConnection* aCon) ndbout << endl << flush; #ifdef VM_TRACE printState("completedTransaction abort"); -#endif abort(); +#endif }//if }//Ndb::completedTransaction() @@ -965,6 +947,10 @@ Ndb::check_send_timeout() WAITFOR_RESPONSE_TIMEOUT) { #ifdef VM_TRACE a_con->printState(); + Uint32 t1 = a_con->theTransactionId; + Uint32 t2 = a_con->theTransactionId >> 32; + ndbout_c("[%.8x %.8x]", t1, t2); + abort(); #endif a_con->setOperationErrorCodeAbort(4012); a_con->theCommitStatus = NdbConnection::Aborted; @@ -1255,8 +1241,7 @@ Return: 0 - Response received ******************************************************************************/ int -Ndb::receiveResponse(int waitTime) -{ +Ndb::receiveResponse(int waitTime){ int tResultCode; TransporterFacade::instance()->checkForceSend(theNdbBlockNumber); @@ -1310,10 +1295,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 @@ -1335,8 +1320,8 @@ void NdbConnection::sendTC_COMMIT_ACK(NdbApiSignal * aSignal, Uint32 transId1, Uint32 transId2, Uint32 aTCRef){ -#if 0 - ndbout_c("Sending TC_COMMIT_ACK(0x%x, 0x%x) to -> %d", +#ifdef MARKER_TRACE + ndbout_c("Sending TC_COMMIT_ACK(0x%.8x, 0x%.8x) to -> %d", transId1, transId2, refToNode(aTCRef)); diff --git a/ndb/src/ndbapi/Ndbinit.cpp b/ndb/src/ndbapi/Ndbinit.cpp index f451ba885d4..be168ddffbe 100644 --- a/ndb/src/ndbapi/Ndbinit.cpp +++ b/ndb/src/ndbapi/Ndbinit.cpp @@ -43,7 +43,7 @@ static int theNoOfNdbObjects = 0; static char *ndbConnectString = 0; -#ifdef NDB_WIN32 +#if defined NDB_WIN32 || defined SCO static NdbMutex & createNdbMutex = * NdbMutex_Create(); #else static NdbMutex createNdbMutex = NDB_MUTEX_INITIALIZER; @@ -111,12 +111,13 @@ Ndb::Ndb( const char* aDataBase , const char* aSchema) : theCurrentConnectCounter = 1; theCurrentConnectIndex = 0; - for (int i = 0; i < MAX_NDB_NODES ; i++) { + int i; + for (i = 0; i < MAX_NDB_NODES ; i++) { theConnectionArray[i] = NULL; the_release_ind[i] = 0; theDBnodes[i] = 0; }//forg - for (int i = 0; i < 2048 ; i++) { + for (i = 0; i < 2048 ; i++) { theFirstTupleId[i] = 0; theLastTupleId[i] = 0; }//for diff --git a/ndb/src/ndbapi/Ndblist.cpp b/ndb/src/ndbapi/Ndblist.cpp index e557fdc0a5f..1e1cb5e4b40 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 <NdbOut.hpp> -#include "Ndb.hpp" -//#include "NdbSchemaOp.hpp" -//#include "NdbSchemaCon.hpp" -#include "NdbOperation.hpp" -#include "NdbScanOperation.hpp" -#include "NdbIndexOperation.hpp" -#include "NdbConnection.hpp" +#include <Ndb.hpp> +#include <NdbOperation.hpp> +#include <NdbIndexOperation.hpp> +#include <NdbIndexScanOperation.hpp> +#include <NdbConnection.hpp> #include "NdbApiSignal.hpp" -#include "NdbRecAttr.hpp" -#include "NdbScanReceiver.hpp" +#include <NdbRecAttr.hpp> #include "NdbUtil.hpp" #include "API.hpp" #include "NdbBlob.hpp" @@ -264,13 +261,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; @@ -345,17 +342,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); } @@ -509,7 +506,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; @@ -558,12 +555,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; } /*************************************************************************** @@ -592,7 +589,7 @@ Ndb::releaseSignal(NdbApiSignal* aSignal) #if defined VM_TRACE // Check that signal is not null assert(aSignal != NULL); - +#if 0 // Check that signal is not already in list NdbApiSignal* tmp = theSignalIdleList; while (tmp != NULL){ @@ -600,6 +597,7 @@ Ndb::releaseSignal(NdbApiSignal* aSignal) tmp = tmp->next(); } #endif +#endif creleaseSignals++; aSignal->next(theSignalIdleList); theSignalIdleList = aSignal; @@ -645,7 +643,7 @@ void Ndb::freeScanOperation() { NdbScanOperation* tOp = theScanOpIdleList; - theScanOpIdleList = (NdbScanOperation *) theScanOpIdleList->next(); + theScanOpIdleList = (NdbIndexScanOperation *) theScanOpIdleList->next(); delete tOp; } @@ -696,7 +694,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<newSize; i++){ diff --git a/ndb/src/ndbapi/ScanOperation.txt b/ndb/src/ndbapi/ScanOperation.txt index 7197cf66f7e..27e4e8c1755 100644 --- a/ndb/src/ndbapi/ScanOperation.txt +++ b/ndb/src/ndbapi/ScanOperation.txt @@ -8,3 +8,49 @@ theNdbCon -> 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/src/ndbapi/TransporterFacade.cpp b/ndb/src/ndbapi/TransporterFacade.cpp index e725144a8f8..7ec9a6a55a3 100644 --- a/ndb/src/ndbapi/TransporterFacade.cpp +++ b/ndb/src/ndbapi/TransporterFacade.cpp @@ -34,11 +34,8 @@ #include <ndb_version.h> #include <SignalLoggerManager.hpp> -#if !defined NDB_OSE && !defined NDB_SOFTOSE -#include <signal.h> -#endif - //#define REPORT_TRANSPORTER +//#define API_TRACE; #if defined DEBUG_TRANSPORTER #define TRP_DEBUG(t) ndbout << __FILE__ << ":" << __LINE__ << ":" << t << endl; @@ -47,7 +44,7 @@ #endif TransporterFacade* TransporterFacade::theFacadeInstance = NULL; - +ConfigRetriever *TransporterFacade::s_config_retriever= 0; /***************************************************************************** @@ -160,14 +157,12 @@ setSignalLog(){ } return false; } +#ifdef TRACE_APIREGREQ +#define TRACE_GSN(gsn) true +#else +#define TRACE_GSN(gsn) (gsn != GSN_API_REGREQ && gsn != GSN_API_REGCONF) +#endif #endif - -// These symbols are needed, but not used in the API -int g_sectionSegmentPool; -struct ErrorReporter { - void handleAssert(const char*, const char*, int); -}; -void ErrorReporter::handleAssert(const char* message, const char* file, int line) {} /** * The execute function : Handle received signal @@ -182,9 +177,7 @@ execute(void * callbackObj, SignalHeader * const header, Uint32 tRecBlockNo = header->theReceiversBlockNumber; #ifdef API_TRACE - if(setSignalLog()){ - // header->theVerId_signalNumber != GSN_API_REGREQ && - // header->theVerId_signalNumber != GSN_API_REGCONF){ + if(setSignalLog() && TRACE_GSN(header->theVerId_signalNumber)){ signalLogger.executeSignal(* header, prio, theData, @@ -314,6 +307,14 @@ execute(void * callbackObj, SignalHeader * const header, } } +// These symbols are needed, but not used in the API +void +SignalLoggerManager::printSegmentedSection(FILE *, const SignalHeader &, + const SegmentedSectionPtr ptr[3], + unsigned i){ + abort(); +} + void copy(Uint32 * & insertPtr, class SectionSegmentPool & thePool, const SegmentedSectionPtr & _ptr){ @@ -332,29 +333,48 @@ atexit_stop_instance(){ * * Which is protected by a mutex */ + + TransporterFacade* TransporterFacade::start_instance(const char * connectString){ // TransporterFacade used from API get config from mgmt srvr - ConfigRetriever configRetriever; - configRetriever.setConnectString(connectString); - ndb_mgm_configuration * props = configRetriever.getConfig(NDB_VERSION, - NODE_TYPE_API); - if (props == 0) { - ndbout << "Configuration error: "; - const char* erString = configRetriever.getErrorString(); - if (erString == 0) { - erString = "No error specified!"; + s_config_retriever= new ConfigRetriever(NDB_VERSION, NODE_TYPE_API); + + s_config_retriever->setConnectString(connectString); + const char* error = 0; + do { + if(s_config_retriever->init() == -1) + break; + + if(s_config_retriever->do_connect() == -1) + break; + + Uint32 nodeId = s_config_retriever->allocNodeId(); + for(Uint32 i = 0; nodeId == 0 && i<5; i++){ + NdbSleep_SecSleep(3); + nodeId = s_config_retriever->allocNodeId(); } - ndbout << erString << endl; - return 0; - } - const int nodeId = configRetriever.getOwnNodeId(); - - TransporterFacade * tf = start_instance(nodeId, props); + if(nodeId == 0) + break; + + ndb_mgm_configuration * props = s_config_retriever->getConfig(); + if(props == 0) + break; + + TransporterFacade * tf = start_instance(nodeId, props); + + free(props); + return tf; + } while(0); - free(props); - return tf; + ndbout << "Configuration error: "; + const char* erString = s_config_retriever->getErrorString(); + if (erString == 0) { + erString = "No error specified!"; + } + ndbout << erString << endl; + return 0; } TransporterFacade* @@ -389,6 +409,14 @@ TransporterFacade::start_instance(int nodeId, return tf; } +void +TransporterFacade::close_configuration(){ + if (s_config_retriever) { + delete s_config_retriever; + s_config_retriever= 0; + } +} + /** * Note that this function need no locking since its * only called from the destructor of Ndb (the NdbObject) @@ -397,6 +425,9 @@ TransporterFacade::start_instance(int nodeId, */ void TransporterFacade::stop_instance(){ + + close_configuration(); + if(theFacadeInstance == NULL){ /** * We are called from atexit function @@ -440,7 +471,21 @@ runSendRequest_C(void * me) void TransporterFacade::threadMainSend(void) { + SocketServer socket_server; + theTransporterRegistry->startSending(); + if (!theTransporterRegistry->start_service(socket_server)){ + ndbout_c("Unable to start theTransporterRegistry->start_service"); + exit(0); + } + + if (!theTransporterRegistry->start_clients()){ + ndbout_c("Unable to start theTransporterRegistry->start_clients"); + exit(0); + } + + socket_server.startServer(); + while(!theStopReceive) { NdbSleep_MilliSleep(10); NdbMutex_Lock(theMutexPtr); @@ -451,6 +496,11 @@ void TransporterFacade::threadMainSend(void) NdbMutex_Unlock(theMutexPtr); } theTransporterRegistry->stopSending(); + + socket_server.stopServer(); + socket_server.stopSessions(); + + theTransporterRegistry->stop_clients(); } extern "C" @@ -466,7 +516,7 @@ void TransporterFacade::threadMainReceive(void) { theTransporterRegistry->startReceiving(); NdbMutex_Lock(theMutexPtr); - theTransporterRegistry->checkConnections(); + theTransporterRegistry->update_connections(); NdbMutex_Unlock(theMutexPtr); while(!theStopReceive) { for(int i = 0; i<10; i++){ @@ -478,7 +528,7 @@ void TransporterFacade::threadMainReceive(void) } } NdbMutex_Lock(theMutexPtr); - theTransporterRegistry->checkConnections(); + theTransporterRegistry->update_connections(); NdbMutex_Unlock(theMutexPtr); }//while theTransporterRegistry->stopReceiving(); @@ -498,6 +548,7 @@ TransporterFacade::TransporterFacade() : theClusterMgr = NULL; theArbitMgr = NULL; theStartNodeId = 1; + m_open_count = 0; } bool @@ -652,6 +703,7 @@ TransporterFacade::open(void* objRef, ExecuteFunction fun, NodeStatusFunction statusFun) { + m_open_count++; return m_threads.open(objRef, fun, statusFun); } @@ -732,8 +784,7 @@ TransporterFacade::checkForceSend(Uint32 block_number) { /****************************************************************************** * SEND SIGNAL METHODS - ******************************************************************************/ - + *****************************************************************************/ int TransporterFacade::sendSignal(NdbApiSignal * aSignal, NodeId aNode){ Uint32* tDataPtr = aSignal->getDataPtrSend(); @@ -741,9 +792,7 @@ TransporterFacade::sendSignal(NdbApiSignal * aSignal, NodeId aNode){ Uint32 TBno = aSignal->theReceiversBlockNumber; if(getIsNodeSendable(aNode) == true){ #ifdef API_TRACE - if(setSignalLog()){ - // aSignal->theVerId_signalNumber != GSN_API_REGREQ && - // aSignal->theVerId_signalNumber != GSN_API_REGCONF){ + if(setSignalLog() && TRACE_GSN(aSignal->theVerId_signalNumber)){ Uint32 tmp = aSignal->theSendersBlockRef; aSignal->theSendersBlockRef = numberToRef(tmp, theOwnId); LinearSectionPtr ptr[3]; @@ -777,9 +826,7 @@ TransporterFacade::sendSignal(NdbApiSignal * aSignal, NodeId aNode){ int TransporterFacade::sendSignalUnCond(NdbApiSignal * aSignal, NodeId aNode){ #ifdef API_TRACE - if(setSignalLog()){ - //aSignal->theVerId_signalNumber != GSN_API_REGREQ && - //aSignal->theVerId_signalNumber != GSN_API_REGCONF + if(setSignalLog() && TRACE_GSN(aSignal->theVerId_signalNumber)){ Uint32 tmp = aSignal->theSendersBlockRef; aSignal->theSendersBlockRef = numberToRef(tmp, theOwnId); LinearSectionPtr ptr[3]; @@ -809,7 +856,7 @@ TransporterFacade::sendFragmentedSignal(NdbApiSignal* aSignal, NodeId aNode, aSignal->m_noOfSections = secs; if(getIsNodeSendable(aNode) == true){ #ifdef API_TRACE - if(setSignalLog()){ + if(setSignalLog() && TRACE_GSN(aSignal->theVerId_signalNumber)){ Uint32 tmp = aSignal->theSendersBlockRef; aSignal->theSendersBlockRef = numberToRef(tmp, theOwnId); signalLogger.sendSignal(* aSignal, @@ -845,7 +892,7 @@ TransporterFacade::sendFragmentedSignalUnCond(NdbApiSignal* aSignal, aSignal->m_noOfSections = secs; #ifdef API_TRACE - if(setSignalLog()){ + if(setSignalLog() && TRACE_GSN(aSignal->theVerId_signalNumber)){ Uint32 tmp = aSignal->theSendersBlockRef; aSignal->theSendersBlockRef = numberToRef(tmp, theOwnId); signalLogger.sendSignal(* aSignal, @@ -875,13 +922,13 @@ TransporterFacade::sendFragmentedSignalUnCond(NdbApiSignal* aSignal, void TransporterFacade::doConnect(int aNodeId){ theTransporterRegistry->setIOState(aNodeId, NoHalt); - theTransporterRegistry->setPerformState(aNodeId, PerformConnect); + theTransporterRegistry->do_connect(aNodeId); } void TransporterFacade::doDisconnect(int aNodeId) { - theTransporterRegistry->setPerformState(aNodeId, PerformDisconnect); + theTransporterRegistry->do_disconnect(aNodeId); } void @@ -906,7 +953,7 @@ TransporterFacade::ownId() const bool TransporterFacade::isConnected(NodeId aNodeId){ - return theTransporterRegistry->performState(aNodeId) == PerformIO; + return theTransporterRegistry->is_connected(aNodeId); } NodeId @@ -992,3 +1039,6 @@ TransporterFacade::ThreadData::close(int number){ m_statusFunction[number] = 0; return 0; } + +template class Vector<NodeStatusFunction>; +template class Vector<TransporterFacade::ThreadData::Object_Execute>; diff --git a/ndb/src/ndbapi/TransporterFacade.hpp b/ndb/src/ndbapi/TransporterFacade.hpp index 4b76cbe864a..14da4b11aa1 100644 --- a/ndb/src/ndbapi/TransporterFacade.hpp +++ b/ndb/src/ndbapi/TransporterFacade.hpp @@ -29,6 +29,7 @@ class ClusterMgr; class ArbitMgr; class IPCConfig; struct ndb_mgm_configuration; +class ConfigRetriever; class Ndb; class NdbApiSignal; @@ -56,6 +57,7 @@ public: static TransporterFacade* instance(); static TransporterFacade* start_instance(int, const ndb_mgm_configuration*); static TransporterFacade* start_instance(const char *connectString); + static void close_configuration(); static void stop_instance(); /** @@ -110,7 +112,6 @@ public: // Close this block number int close_local(BlockNumber blockNumber); - void setState(Uint32 aNodeId, PerformState aState); private: /** @@ -160,7 +161,9 @@ private: /** * Block number handling */ +public: static const unsigned MAX_NO_THREADS = 4711; +private: struct ThreadData { static const Uint32 ACTIVE = (1 << 16) | 1; @@ -208,6 +211,8 @@ private: } } m_threads; + Uint32 m_open_count; + /** * execute function */ @@ -219,6 +224,7 @@ public: NdbMutex* theMutexPtr; private: static TransporterFacade* theFacadeInstance; + static ConfigRetriever *s_config_retriever; public: GlobalDictCache m_globalDictCache; @@ -312,6 +318,7 @@ TransporterFacade::getIsNodeSendable(NodeId n) const { "%d of node: %d", node.m_info.m_type, n); abort(); + return false; // to remove compiler warning } } diff --git a/ndb/src/ndbapi/ndberror.c b/ndb/src/ndbapi/ndberror.c index 760322d669d..66a89326a66 100644 --- a/ndb/src/ndbapi/ndberror.c +++ b/ndb/src/ndbapi/ndberror.c @@ -91,6 +91,9 @@ ErrorBundle ErrorCodes[] = { { 4029, NR, "Node failure caused abort of transaction" }, { 4031, NR, "Node failure caused abort of transaction" }, { 4033, NR, "Send to NDB failed" }, + { 4115, NR, + "Transaction was committed but all read information was not " + "received due to node crash" }, /** * Node shutdown @@ -114,9 +117,6 @@ ErrorBundle ErrorCodes[] = { "Time-out, most likely caused by simple read or cluster failure" }, { 4024, UR, "Time-out, most likely caused by simple read or cluster failure" }, - { 4115, UR, - "Transaction was committed but all read information was not " - "received due to node crash" }, /** * TemporaryResourceError @@ -404,7 +404,6 @@ ErrorBundle ErrorCodes[] = { { 4243, AE, "Index not found" }, { 4244, AE, "Index or table with given name already exists" }, { 4245, AE, "Index attribute must be defined as stored, i.e. the StorageAttributeType must be defined as NormalStorageAttribute"}, - { 4246, AE, "Combined index attributes are not allowed to be NULL attributes" }, { 4247, AE, "Illegal index/trigger create/drop/alter request" }, { 4248, AE, "Trigger/index name invalid" }, { 4249, AE, "Invalid table" }, diff --git a/ndb/test/include/HugoOperations.hpp b/ndb/test/include/HugoOperations.hpp index 7295b72b18f..6bd8f7204b2 100644 --- a/ndb/test/include/HugoOperations.hpp +++ b/ndb/test/include/HugoOperations.hpp @@ -57,10 +57,6 @@ public: int pkDeleteRecord(Ndb*, int recordNo, int numRecords = 1); - - int scanReadRecords(Ndb* pNdb, - Uint32 parallelism = 240, ScanLock lock = SL_Read); - int executeScanRead(Ndb*); int execute_Commit(Ndb*, AbortOption ao = AbortOnError); @@ -93,7 +89,11 @@ public: int recordNo, int numRecords = 1, int updatesValue = 0); - + + int scanReadRecords(Ndb*, NdbScanOperation::LockMode = + NdbScanOperation::LM_CommittedRead, + int numRecords = 1); + protected: void allocRows(int rows); void deallocRows(); @@ -102,48 +102,12 @@ protected: HugoCalculator calc; Vector<BaseString> savedRecords; + + struct RsPair { NdbResultSet* m_result_set; int records; }; + Vector<RsPair> m_result_sets; + Vector<RsPair> m_executed_result_sets; private: NdbConnection* pTrans; - - struct ScanTmp { - ScanTmp() { - pTrans = 0; - m_tmpRow = 0; - m_delete = true; - m_op = DONE; - } - ScanTmp(NdbConnection* a, NDBT_ResultRow* b){ - pTrans = a; - m_tmpRow = b; - m_delete = true; - m_op = DONE; - } - ScanTmp(const ScanTmp& org){ - * this = org; - } - ScanTmp& operator=(const ScanTmp& org){ - pTrans = org.pTrans; - m_tmpRow = org.m_tmpRow; - m_delete = org.m_delete; - m_op = org.m_op; - return * this; - } - - ~ScanTmp() { - if(m_delete && pTrans) - pTrans->close(); - if(m_delete && m_tmpRow) - delete m_tmpRow; - } - - NdbConnection * pTrans; - NDBT_ResultRow * m_tmpRow; - bool m_delete; - enum { DONE, READ, UPDATE, DELETE } m_op; - }; - Vector<ScanTmp> m_scans; - int run(ScanTmp & tmp); - }; #endif diff --git a/ndb/test/include/HugoTransactions.hpp b/ndb/test/include/HugoTransactions.hpp index 5ff1fef16bc..280d9490f15 100644 --- a/ndb/test/include/HugoTransactions.hpp +++ b/ndb/test/include/HugoTransactions.hpp @@ -34,16 +34,17 @@ public: int records, int batch = 512, bool allowConstraintViolation = true, - int doSleep = 0); + int doSleep = 0, + bool oneTrans = false); 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 +53,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 +101,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/NDBT_Table.hpp b/ndb/test/include/NDBT_Table.hpp index eee76773106..59db3ed1092 100644 --- a/ndb/test/include/NDBT_Table.hpp +++ b/ndb/test/include/NDBT_Table.hpp @@ -23,10 +23,9 @@ #include <NdbOut.hpp> class NDBT_Attribute : public NdbDictionary::Column { - friend class NdbOut& operator <<(class NdbOut&, const NDBT_Attribute &); public: NDBT_Attribute(const char* _name, - Column::Type _type, + NdbDictionary::Column::Type _type, int _length = 1, bool _pk = false, bool _nullable = false): @@ -51,13 +50,12 @@ public: NDBT_Table(const char* name, int noOfAttributes, - const NdbDictionary::Column attributes[], - bool stored = true) + const NdbDictionary::Column attributes[]) : NdbDictionary::Table(name) { assert(name != 0); - setStoredTable(stored); + //setStoredTable(stored); for(int i = 0; i<noOfAttributes; i++) addColumn(attributes[i]); } diff --git a/ndb/test/include/NDBT_Tables.hpp b/ndb/test/include/NDBT_Tables.hpp index 1da9818ee70..aa78f7d4e2c 100644 --- a/ndb/test/include/NDBT_Tables.hpp +++ b/ndb/test/include/NDBT_Tables.hpp @@ -26,7 +26,8 @@ class NDBT_Tables { public: - static int createTable(Ndb* pNdb, const char* _name, bool _temp = false); + static int createTable(Ndb* pNdb, const char* _name, bool _temp = false, + bool existsOK = false); static int createAllTables(Ndb* pNdb, bool _temp, bool existsOK = false); static int createAllTables(Ndb* pNdb); diff --git a/ndb/test/include/NDBT_Test.hpp b/ndb/test/include/NDBT_Test.hpp index 7a5d14689bc..6a968c491ae 100644 --- a/ndb/test/include/NDBT_Test.hpp +++ b/ndb/test/include/NDBT_Test.hpp @@ -63,6 +63,8 @@ public: bool getPropertyWait(const char*, Uint32); const char* getPropertyWait(const char*, const char* ); + void decProperty(const char *); + // Communicate with other tests void stopTest(); bool isTestStopped(); @@ -110,6 +112,7 @@ public: NDBT_Step(NDBT_TestCase* ptest, const char* pname, NDBT_TESTFUNC* pfunc); + virtual ~NDBT_Step() {} int execute(NDBT_Context*); virtual int setUp() = 0; virtual void tearDown() = 0; @@ -132,8 +135,9 @@ public: NDBT_NdbApiStep(NDBT_TestCase* ptest, const char* pname, NDBT_TESTFUNC* pfunc); - int setUp(); - void tearDown(); + virtual ~NDBT_NdbApiStep() {} + virtual int setUp(); + virtual void tearDown(); Ndb* getNdb(); protected: @@ -145,6 +149,7 @@ public: NDBT_ParallelStep(NDBT_TestCase* ptest, const char* pname, NDBT_TESTFUNC* pfunc); + virtual ~NDBT_ParallelStep() {} }; class NDBT_Verifier : public NDBT_NdbApiStep { @@ -152,6 +157,7 @@ public: NDBT_Verifier(NDBT_TestCase* ptest, const char* name, NDBT_TESTFUNC* func); + virtual ~NDBT_Verifier() {} }; class NDBT_Initializer : public NDBT_NdbApiStep { @@ -159,6 +165,7 @@ public: NDBT_Initializer(NDBT_TestCase* ptest, const char* name, NDBT_TESTFUNC* func); + virtual ~NDBT_Initializer() {} }; class NDBT_Finalizer : public NDBT_NdbApiStep { @@ -166,6 +173,7 @@ public: NDBT_Finalizer(NDBT_TestCase* ptest, const char* name, NDBT_TESTFUNC* func); + virtual ~NDBT_Finalizer() {} }; @@ -174,7 +182,8 @@ public: NDBT_TestCase(NDBT_TestSuite* psuite, const char* name, const char* comment); - virtual ~NDBT_TestCase(){}; + virtual ~NDBT_TestCase(){} + // This is the default executor of a test case // When a test case is executed it will need to be suplied with a number of // different parameters and settings, these are passed to the test in the diff --git a/ndb/test/include/NdbRestarter.hpp b/ndb/test/include/NdbRestarter.hpp index b4c29a87eff..114726f6a2b 100644 --- a/ndb/test/include/NdbRestarter.hpp +++ b/ndb/test/include/NdbRestarter.hpp @@ -19,6 +19,7 @@ #include <mgmapi.h> #include <Vector.hpp> +#include <BaseString.hpp> class NdbRestarter { public: @@ -85,8 +86,8 @@ protected: Vector<ndb_mgm_node_state> apiNodes; bool connected; - const char* addr; - const char* host; + BaseString addr; + BaseString host; int port; NdbMgmHandle handle; ndb_mgm_configuration * m_config; 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.am b/ndb/test/ndbapi/Makefile.am index 7b3648bdc45..51bc11f8a25 100644 --- a/ndb/test/ndbapi/Makefile.am +++ b/ndb/test/ndbapi/Makefile.am @@ -9,7 +9,6 @@ create_tab \ flexAsynch \ flexBench \ flexHammer \ -flexScan \ flexTT \ testBackup \ testBasic \ @@ -26,9 +25,11 @@ testOperations \ testRestartGci \ testScan \ testScanInterpreter \ +testScanPerf \ testSystemRestart \ testTimeout \ testTransactions \ +testDeadlock \ test_event #flexTimedAsynch @@ -41,7 +42,6 @@ drop_all_tabs_SOURCES = drop_all_tabs.cpp flexAsynch_SOURCES = flexAsynch.cpp flexBench_SOURCES = flexBench.cpp flexHammer_SOURCES = flexHammer.cpp -flexScan_SOURCES = flexScan.cpp flexTT_SOURCES = flexTT.cpp #flexTimedAsynch_SOURCES = flexTimedAsynch.cpp #flex_bench_mysql_SOURCES = flex_bench_mysql.cpp @@ -60,9 +60,11 @@ testOperations_SOURCES = testOperations.cpp testRestartGci_SOURCES = testRestartGci.cpp testScan_SOURCES = testScan.cpp ScanFunctions.hpp testScanInterpreter_SOURCES = testScanInterpreter.cpp ScanFilter.hpp ScanInterpretTest.hpp +testScanPerf_SOURCES = testScanPerf.cpp testSystemRestart_SOURCES = testSystemRestart.cpp testTimeout_SOURCES = testTimeout.cpp testTransactions_SOURCES = testTransactions.cpp +testDeadlock_SOURCES = testDeadlock.cpp test_event_SOURCES = test_event.cpp INCLUDES_LOC = -I$(top_srcdir)/ndb/include/kernel @@ -79,3 +81,4 @@ testBackup_LDADD = $(LDADD) bank/libbank.a # Don't update the files from bitkeeper %::SCCS/s.% + diff --git a/ndb/test/ndbapi/Makefile_old b/ndb/test/ndbapi/Makefile_old index 34761e1eb9c..c3198096ec0 100644 --- a/ndb/test/ndbapi/Makefile_old +++ b/ndb/test/ndbapi/Makefile_old @@ -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/ScanFunctions.hpp b/ndb/test/ndbapi/ScanFunctions.hpp index 36d01909861..2ff4b751c33 100644 --- a/ndb/test/ndbapi/ScanFunctions.hpp +++ b/ndb/test/ndbapi/ScanFunctions.hpp @@ -79,8 +79,9 @@ ScanFunctions::scanReadFunctions(Ndb* pNdb, const int retryMax = 100; int sleepTime = 10; int check; - NdbConnection *pTrans; - NdbOperation *pOp; + NdbConnection *pTrans = 0; + NdbScanOperation *pOp = 0; + NdbResultSet *rs = 0; while (true){ if (retryAttempt >= retryMax){ @@ -103,117 +104,81 @@ 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()); - if (pOp == NULL) { + pOp = pTrans->getNdbScanOperation(tab.getName()); + if (pOp == NULL) { + ERR(pTrans->getNdbError()); + pNdb->closeTransaction(pTrans); + return NDBT_FAILED; + } + + + rs = pOp->readTuples(exclusive ? + NdbScanOperation::LM_Exclusive : + NdbScanOperation::LM_Read); + + if( rs == 0 ) { + ERR(pTrans->getNdbError()); + pNdb->closeTransaction(pTrans); + return NDBT_FAILED; + } + + + if (action == OnlyOpenScanOnce){ + // Call openScan one more time when it's already defined + NdbResultSet* rs2 = pOp->readTuples(NdbScanOperation::LM_Read); + if( rs2 == 0 ) { ERR(pTrans->getNdbError()); pNdb->closeTransaction(pTrans); return NDBT_FAILED; } - - if (exclusive == true) - check = pOp->openScanExclusive(parallelism); - else - check = pOp->openScanRead(parallelism); + } + + if (action==EqualAfterOpenScan){ + check = pOp->equal(tab.getColumn(0)->getName(), 10); if( check == -1 ) { 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 ) { - 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 ) { - ERR(pTrans->getNdbError()); - pNdb->closeTransaction(pTrans); - return NDBT_FAILED; - } - } - - check = pOp->interpret_exit_ok(); - if( check == -1 ) { + } + } + + check = pOp->interpret_exit_ok(); + if( check == -1 ) { + ERR(pTrans->getNdbError()); + pNdb->closeTransaction(pTrans); + return NDBT_FAILED; + } + + for(int a = 0; a<tab.getNoOfColumns(); a++){ + if(pOp->getValue(tab.getColumn(a)->getName()) == NULL) { ERR(pTrans->getNdbError()); pNdb->closeTransaction(pTrans); return NDBT_FAILED; } - - for(int a = 0; a<tab.getNoOfColumns(); a++){ - if(pOp->getValue(tab.getColumn(a)->getName()) == NULL) { - ERR(pTrans->getNdbError()); - pNdb->closeTransaction(pTrans); - return NDBT_FAILED; - } - } - } - check = pTrans->executeScan(); + } + + check = pTrans->execute(NoCommit); if( check == -1 ) { ERR(pTrans->getNdbError()); pNdb->closeTransaction(pTrans); return NDBT_FAILED; } - - + int abortCount = records / 10; bool abortTrans = (action==CloseWithoutStop); int eof; int rows = 0; - eof = pTrans->nextScanResult(); - + eof = rs->nextResult(); + while(eof == 0){ rows++; - + if (abortCount == rows && abortTrans == true){ g_info << "Scan is aborted after "<<abortCount<<" rows" << endl; 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 +201,7 @@ ScanFunctions::scanReadFunctions(Ndb* pNdb, } } - eof = pTrans->nextScanResult(); + eof = rs->nextResult(); } if (eof == -1) { const NdbError err = pTrans->getNdbError(); @@ -246,7 +211,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 +241,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 +250,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/ScanInterpretTest.hpp b/ndb/test/ndbapi/ScanInterpretTest.hpp index 3862de34111..e8a0d4b6dca 100644 --- a/ndb/test/ndbapi/ScanInterpretTest.hpp +++ b/ndb/test/ndbapi/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/ndbapi/bank/Bank.cpp b/ndb/test/ndbapi/bank/Bank.cpp index 14883205693..7a2c5b057a1 100644 --- a/ndb/test/ndbapi/bank/Bank.cpp +++ b/ndb/test/ndbapi/bank/Bank.cpp @@ -670,15 +670,15 @@ int Bank::findLastGL(Uint64 &lastTime){ return NDBT_FAILED; } - NdbOperation* pOp = pScanTrans->getNdbOperation("GL"); + NdbScanOperation* pOp = pScanTrans->getNdbScanOperation("GL"); if (pOp == NULL) { ERR(pScanTrans->getNdbError()); m_ndb.closeTransaction(pScanTrans); return NDBT_FAILED; } - check = pOp->openScanRead(64); - if( check == -1 ) { + NdbResultSet * rs = pOp->readTuples(); + if( rs == 0 ) { ERR(pScanTrans->getNdbError()); m_ndb.closeTransaction(pScanTrans); return NDBT_FAILED; @@ -698,7 +698,7 @@ int Bank::findLastGL(Uint64 &lastTime){ return NDBT_FAILED; } - check = pScanTrans->executeScan(); + check = pScanTrans->execute(NoCommit); if( check == -1 ) { ERR(pScanTrans->getNdbError()); m_ndb.closeTransaction(pScanTrans); @@ -707,7 +707,7 @@ int Bank::findLastGL(Uint64 &lastTime){ int eof; int rows = 0; - eof = pScanTrans->nextScanResult(); + eof = rs->nextResult(); lastTime = 0; while(eof == 0){ @@ -717,7 +717,7 @@ int Bank::findLastGL(Uint64 &lastTime){ if (t > lastTime) lastTime = t; - eof = pScanTrans->nextScanResult(); + eof = rs->nextResult(); } if (eof == -1) { ERR(pScanTrans->getNdbError()); @@ -1002,15 +1002,15 @@ int Bank::sumTransactionsForGL(const Uint64 glTime, return NDBT_FAILED; } - NdbOperation* pOp = pScanTrans->getNdbOperation("TRANSACTION"); + NdbScanOperation* pOp = pScanTrans->getNdbScanOperation("TRANSACTION"); if (pOp == NULL) { ERR(pScanTrans->getNdbError()); m_ndb.closeTransaction(pScanTrans); return NDBT_FAILED; } - check = pOp->openScanExclusive(64); - if( check == -1 ) { + NdbResultSet * rs = pOp->readTuplesExclusive(); + if( rs == 0 ) { ERR(pScanTrans->getNdbError()); m_ndb.closeTransaction(pScanTrans); return NDBT_FAILED; @@ -1051,7 +1051,7 @@ int Bank::sumTransactionsForGL(const Uint64 glTime, return NDBT_FAILED; } - check = pScanTrans->executeScan(); + check = pScanTrans->execute(NoCommit); if( check == -1 ) { ERR(pScanTrans->getNdbError()); m_ndb.closeTransaction(pScanTrans); @@ -1061,7 +1061,7 @@ int Bank::sumTransactionsForGL(const Uint64 glTime, int eof; int rows = 0; int rowsFound = 0; - eof = pScanTrans->nextScanResult(); + eof = rs->nextResult(); while(eof == 0){ rows++; @@ -1085,7 +1085,7 @@ int Bank::sumTransactionsForGL(const Uint64 glTime, } } - eof = pScanTrans->nextScanResult(); + eof = rs->nextResult(); if ((rows % 100) == 0){ // "refresh" ownner transaction every 100th row @@ -1162,15 +1162,15 @@ int Bank::performValidateGL(Uint64 glTime){ return NDBT_FAILED; } - NdbOperation* pOp = pScanTrans->getNdbOperation("GL"); + NdbScanOperation* pOp = pScanTrans->getNdbScanOperation("GL"); if (pOp == NULL) { ERR(pScanTrans->getNdbError()); m_ndb.closeTransaction(pScanTrans); return NDBT_FAILED; } - check = pOp->openScanRead(64); - if( check == -1 ) { + NdbResultSet * rs = pOp->readTuples(); + if( rs == 0 ) { ERR(pScanTrans->getNdbError()); m_ndb.closeTransaction(pScanTrans); return NDBT_FAILED; @@ -1238,7 +1238,7 @@ int Bank::performValidateGL(Uint64 glTime){ return NDBT_FAILED; } - check = pScanTrans->executeScan(); + check = pScanTrans->execute(NoCommit); if( check == -1 ) { ERR(pScanTrans->getNdbError()); m_ndb.closeTransaction(pScanTrans); @@ -1249,7 +1249,7 @@ int Bank::performValidateGL(Uint64 glTime){ int rows = 0; int countGlRecords = 0; int result = NDBT_OK; - eof = pScanTrans->nextScanResult(); + eof = rs->nextResult(); while(eof == 0){ rows++; @@ -1336,7 +1336,7 @@ int Bank::performValidateGL(Uint64 glTime){ } } - eof = pScanTrans->nextScanResult(); + eof = rs->nextResult(); } if (eof == -1) { ERR(pScanTrans->getNdbError()); @@ -1426,15 +1426,15 @@ int Bank::getOldestPurgedGL(const Uint32 accountType, return NDBT_FAILED; } - NdbOperation* pOp = pScanTrans->getNdbOperation("GL"); + NdbScanOperation* pOp = pScanTrans->getNdbScanOperation("GL"); if (pOp == NULL) { ERR(pScanTrans->getNdbError()); m_ndb.closeTransaction(pScanTrans); return NDBT_FAILED; } - check = pOp->openScanRead(64); - if( check == -1 ) { + NdbResultSet * rs = pOp->readTuples(); + if( rs == 0 ) { ERR(pScanTrans->getNdbError()); m_ndb.closeTransaction(pScanTrans); return NDBT_FAILED; @@ -1468,7 +1468,7 @@ int Bank::getOldestPurgedGL(const Uint32 accountType, return NDBT_FAILED; } - check = pScanTrans->executeScan(); + check = pScanTrans->execute(NoCommit); if( check == -1 ) { ERR(pScanTrans->getNdbError()); m_ndb.closeTransaction(pScanTrans); @@ -1477,7 +1477,7 @@ int Bank::getOldestPurgedGL(const Uint32 accountType, int eof; int rows = 0; - eof = pScanTrans->nextScanResult(); + eof = rs->nextResult(); oldest = 0; while(eof == 0){ @@ -1491,7 +1491,7 @@ int Bank::getOldestPurgedGL(const Uint32 accountType, if (t > oldest) oldest = t; } - eof = pScanTrans->nextScanResult(); + eof = rs->nextResult(); } if (eof == -1) { ERR(pScanTrans->getNdbError()); @@ -1518,15 +1518,15 @@ int Bank::getOldestNotPurgedGL(Uint64 &oldest, return NDBT_FAILED; } - NdbOperation* pOp = pScanTrans->getNdbOperation("GL"); + NdbScanOperation* pOp = pScanTrans->getNdbScanOperation("GL"); if (pOp == NULL) { ERR(pScanTrans->getNdbError()); m_ndb.closeTransaction(pScanTrans); return NDBT_FAILED; } - check = pOp->openScanRead(64); - if( check == -1 ) { + NdbResultSet * rs = pOp->readTuples(); + if( rs == 0 ) { ERR(pScanTrans->getNdbError()); m_ndb.closeTransaction(pScanTrans); return NDBT_FAILED; @@ -1560,7 +1560,7 @@ int Bank::getOldestNotPurgedGL(Uint64 &oldest, return NDBT_FAILED; } - check = pScanTrans->executeScan(); + check = pScanTrans->execute(NoCommit); if( check == -1 ) { ERR(pScanTrans->getNdbError()); m_ndb.closeTransaction(pScanTrans); @@ -1569,7 +1569,7 @@ int Bank::getOldestNotPurgedGL(Uint64 &oldest, int eof; int rows = 0; - eof = pScanTrans->nextScanResult(); + eof = rs->nextResult(); oldest = (Uint64)-1; found = false; @@ -1586,7 +1586,7 @@ int Bank::getOldestNotPurgedGL(Uint64 &oldest, accountTypeId = a; } } - eof = pScanTrans->nextScanResult(); + eof = rs->nextResult(); } if (eof == -1) { ERR(pScanTrans->getNdbError()); @@ -1615,15 +1615,15 @@ int Bank::checkNoTransactionsOlderThan(const Uint32 accountType, return NDBT_FAILED; } - NdbOperation* pOp = pScanTrans->getNdbOperation("TRANSACTION"); + NdbScanOperation* pOp = pScanTrans->getNdbScanOperation("TRANSACTION"); if (pOp == NULL) { ERR(pScanTrans->getNdbError()); m_ndb.closeTransaction(pScanTrans); return NDBT_FAILED; } - check = pOp->openScanRead(64); - if( check == -1 ) { + NdbResultSet * rs = pOp->readTuples(); + if( rs == 0 ) { ERR(pScanTrans->getNdbError()); m_ndb.closeTransaction(pScanTrans); return NDBT_FAILED; @@ -1657,7 +1657,7 @@ int Bank::checkNoTransactionsOlderThan(const Uint32 accountType, return NDBT_FAILED; } - check = pScanTrans->executeScan(); + check = pScanTrans->execute(NoCommit); if( check == -1 ) { ERR(pScanTrans->getNdbError()); m_ndb.closeTransaction(pScanTrans); @@ -1667,7 +1667,7 @@ int Bank::checkNoTransactionsOlderThan(const Uint32 accountType, int eof; int rows = 0; int found = 0; - eof = pScanTrans->nextScanResult(); + eof = rs->nextResult(); while(eof == 0){ rows++; @@ -1683,7 +1683,7 @@ int Bank::checkNoTransactionsOlderThan(const Uint32 accountType, << " ti = " << ti << endl; found++; } - eof = pScanTrans->nextScanResult(); + eof = rs->nextResult(); } if (eof == -1) { ERR(pScanTrans->getNdbError()); @@ -1859,15 +1859,15 @@ int Bank::findTransactionsToPurge(const Uint64 glTime, return NDBT_FAILED; } - NdbOperation* pOp = pScanTrans->getNdbOperation("TRANSACTION"); + NdbScanOperation* pOp = pScanTrans->getNdbScanOperation("TRANSACTION"); if (pOp == NULL) { ERR(pScanTrans->getNdbError()); m_ndb.closeTransaction(pScanTrans); return NDBT_FAILED; } - check = pOp->openScanExclusive(64); - if( check == -1 ) { + NdbResultSet * rs = pOp->readTuplesExclusive(); + if( rs == 0 ) { ERR(pScanTrans->getNdbError()); m_ndb.closeTransaction(pScanTrans); return NDBT_FAILED; @@ -1894,7 +1894,7 @@ int Bank::findTransactionsToPurge(const Uint64 glTime, return NDBT_FAILED; } - check = pScanTrans->executeScan(); + check = pScanTrans->execute(NoCommit); if( check == -1 ) { ERR(pScanTrans->getNdbError()); m_ndb.closeTransaction(pScanTrans); @@ -1904,7 +1904,7 @@ int Bank::findTransactionsToPurge(const Uint64 glTime, int eof; int rows = 0; int rowsFound = 0; - eof = pScanTrans->nextScanResult(); + eof = rs->nextResult(); while(eof == 0){ rows++; @@ -1914,8 +1914,8 @@ int Bank::findTransactionsToPurge(const Uint64 glTime, if (a == accountType && t == glTime){ rowsFound++; // One record found - NdbOperation* pDelOp = pOp->takeOverForDelete(pTrans); - if (pDelOp == NULL){ + check = rs->deleteTuple(pTrans); + if (check == -1){ ERR(m_ndb.getNdbError()); m_ndb.closeTransaction(pScanTrans); return NDBT_FAILED; @@ -1929,7 +1929,7 @@ int Bank::findTransactionsToPurge(const Uint64 glTime, return NDBT_FAILED; } } - eof = pScanTrans->nextScanResult(); + eof = rs->nextResult(); } if (eof == -1) { ERR(pScanTrans->getNdbError()); @@ -2348,15 +2348,15 @@ int Bank::getSumAccounts(Uint32 &sumAccounts, return NDBT_FAILED; } - NdbOperation* pOp = pScanTrans->getNdbOperation("ACCOUNT"); + NdbScanOperation* pOp = pScanTrans->getNdbScanOperation("ACCOUNT"); if (pOp == NULL) { ERR(pScanTrans->getNdbError()); m_ndb.closeTransaction(pScanTrans); return NDBT_FAILED; } - check = pOp->openScanExclusive(64); - if( check == -1 ) { + NdbResultSet * rs = pOp->readTuplesExclusive(); + if( rs == 0 ) { ERR(pScanTrans->getNdbError()); m_ndb.closeTransaction(pScanTrans); return NDBT_FAILED; @@ -2376,7 +2376,7 @@ int Bank::getSumAccounts(Uint32 &sumAccounts, return NDBT_FAILED; } - check = pScanTrans->executeScan(); + check = pScanTrans->execute(NoCommit); if( check == -1 ) { ERR(pScanTrans->getNdbError()); m_ndb.closeTransaction(pScanTrans); @@ -2391,7 +2391,7 @@ int Bank::getSumAccounts(Uint32 &sumAccounts, } int eof; - eof = pScanTrans->nextScanResult(); + eof = rs->nextResult(); while(eof == 0){ Uint32 b = balanceRec->u_32_value(); @@ -2403,7 +2403,7 @@ int Bank::getSumAccounts(Uint32 &sumAccounts, // << ", sum="<< sumAccounts << endl; // Take over the operation so that the lock is kept in db - NdbOperation* pLockOp = pOp->takeOverForUpdate(pTrans); + NdbOperation* pLockOp = rs->updateTuple(pTrans); if (pLockOp == NULL){ ERR(m_ndb.getNdbError()); m_ndb.closeTransaction(pScanTrans); @@ -2429,7 +2429,7 @@ int Bank::getSumAccounts(Uint32 &sumAccounts, return NDBT_FAILED; } - eof = pScanTrans->nextScanResult(); + eof = rs->nextResult(); } if (eof == -1) { ERR(pScanTrans->getNdbError()); diff --git a/ndb/test/ndbapi/bank/BankLoad.cpp b/ndb/test/ndbapi/bank/BankLoad.cpp index 76261b664a6..bbaac27735b 100644 --- a/ndb/test/ndbapi/bank/BankLoad.cpp +++ b/ndb/test/ndbapi/bank/BankLoad.cpp @@ -335,15 +335,15 @@ int Bank::getBalanceForAccountType(const Uint32 accountType, return NDBT_FAILED; } - NdbOperation* pOp = pScanTrans->getNdbOperation("ACCOUNT"); + NdbScanOperation* pOp = pScanTrans->getNdbScanOperation("ACCOUNT"); if (pOp == NULL) { ERR(pScanTrans->getNdbError()); m_ndb.closeTransaction(pScanTrans); return NDBT_FAILED; } - check = pOp->openScanRead(64); - if( check == -1 ) { + NdbResultSet* rs = pOp->readTuples(); + if( rs == 0 ) { ERR(pScanTrans->getNdbError()); m_ndb.closeTransaction(pScanTrans); return NDBT_FAILED; @@ -370,7 +370,7 @@ int Bank::getBalanceForAccountType(const Uint32 accountType, return NDBT_FAILED; } - check = pScanTrans->executeScan(); + check = pScanTrans->execute(NoCommit); if( check == -1 ) { ERR(pScanTrans->getNdbError()); m_ndb.closeTransaction(pScanTrans); @@ -379,7 +379,7 @@ int Bank::getBalanceForAccountType(const Uint32 accountType, int eof; int rows = 0; - eof = pScanTrans->nextScanResult(); + eof = rs->nextResult(); while(eof == 0){ rows++; @@ -391,7 +391,7 @@ int Bank::getBalanceForAccountType(const Uint32 accountType, balance += b; } - eof = pScanTrans->nextScanResult(); + eof = rs->nextResult(); } if (eof == -1) { ERR(pScanTrans->getNdbError()); diff --git a/ndb/test/ndbapi/create_tab.cpp b/ndb/test/ndbapi/create_tab.cpp index 8bb1e7a9572..c2e3b7f64ea 100644 --- a/ndb/test/ndbapi/create_tab.cpp +++ b/ndb/test/ndbapi/create_tab.cpp @@ -63,9 +63,10 @@ int main(int argc, const char** argv){ /** * Print instead of creating */ - if(argv[optind] != NULL){ - for(int i = optind; i<argc; i++) + if(optind < argc){ + for(int i = optind; i<argc; i++){ NDBT_Tables::print(argv[i]); + } } else { NDBT_Tables::printAll(); } diff --git a/ndb/test/ndbapi/flexAsynch.cpp b/ndb/test/ndbapi/flexAsynch.cpp index 396ac06c87a..9192ec21b93 100644 --- a/ndb/test/ndbapi/flexAsynch.cpp +++ b/ndb/test/ndbapi/flexAsynch.cpp @@ -146,7 +146,7 @@ tellThreads(StartType what) NDB_COMMAND(flexAsynch, "flexAsynch", "flexAsynch", "flexAsynch", 65535) { ThreadNdb* pThreadData; - int tLoops=0; + int tLoops=0, i; int returnValue = NDBT_OK; flexAsynchErrorData = new ErrorData; @@ -256,7 +256,7 @@ NDB_COMMAND(flexAsynch, "flexAsynch", "flexAsynch", "flexAsynch", 65535) PRINT_TIMER("insert", noOfTransacts, tNoOfOpsPerTrans); if (0 < failed) { - int i = retry_opt ; + i = retry_opt ; int ci = 1 ; while (0 < failed && 0 < i){ ndbout << failed << " of the transactions returned errors!" @@ -293,7 +293,7 @@ NDB_COMMAND(flexAsynch, "flexAsynch", "flexAsynch", "flexAsynch", 65535) PRINT_TIMER("read", noOfTransacts, tNoOfOpsPerTrans); if (0 < failed) { - int i = retry_opt ; + i = retry_opt ; int cr = 1; while (0 < failed && 0 < i){ ndbout << failed << " of the transactions returned errors!"<<endl ; @@ -330,7 +330,7 @@ NDB_COMMAND(flexAsynch, "flexAsynch", "flexAsynch", "flexAsynch", 65535) PRINT_TIMER("update", noOfTransacts, tNoOfOpsPerTrans) ; if (0 < failed) { - int i = retry_opt ; + i = retry_opt ; int cu = 1 ; while (0 < failed && 0 < i){ ndbout << failed << " of the transactions returned errors!"<<endl ; @@ -366,7 +366,7 @@ NDB_COMMAND(flexAsynch, "flexAsynch", "flexAsynch", "flexAsynch", 65535) PRINT_TIMER("read", noOfTransacts, tNoOfOpsPerTrans); if (0 < failed) { - int i = retry_opt ; + i = retry_opt ; int cr2 = 1 ; while (0 < failed && 0 < i){ ndbout << failed << " of the transactions returned errors!"<<endl ; @@ -403,7 +403,7 @@ NDB_COMMAND(flexAsynch, "flexAsynch", "flexAsynch", "flexAsynch", 65535) PRINT_TIMER("delete", noOfTransacts, tNoOfOpsPerTrans); if (0 < failed) { - int i = retry_opt ; + i = retry_opt ; int cd = 1 ; while (0 < failed && 0 < i){ ndbout << failed << " of the transactions returned errors!"<< endl ; @@ -438,7 +438,7 @@ NDB_COMMAND(flexAsynch, "flexAsynch", "flexAsynch", "flexAsynch", 65535) execute(stStop); void * tmp; - for(int i = 0; i<tNoOfThreads; i++){ + for(i = 0; i<tNoOfThreads; i++){ NdbThread_WaitFor(threadLife[i], &tmp); NdbThread_Destroy(&threadLife[i]); } diff --git a/ndb/test/ndbapi/flexBench.cpp b/ndb/test/ndbapi/flexBench.cpp index 809d11086bf..38c8f6e280f 100644 --- a/ndb/test/ndbapi/flexBench.cpp +++ b/ndb/test/ndbapi/flexBench.cpp @@ -282,7 +282,7 @@ tellThreads(ThreadData* pt, StartType what) NDB_COMMAND(flexBench, "flexBench", "flexBench", "flexbench", 65535) { ThreadData* pThreadsData; - int tLoops = 0; + int tLoops = 0, i; int returnValue = NDBT_OK; if (readArguments(argc, argv) != 0){ @@ -355,7 +355,7 @@ NDB_COMMAND(flexBench, "flexBench", "flexBench", "flexbench", 65535) ****************************************************************/ resetThreads(pThreadsData); - for (unsigned int i = 0; i < tNoOfThreads; i++){ + for (i = 0; i < tNoOfThreads; i++){ pThreadsData[i].threadNo = i; pThreadsData[i].threadLife = NdbThread_Create(flexBenchThread, (void**)&pThreadsData[i], @@ -531,7 +531,7 @@ NDB_COMMAND(flexBench, "flexBench", "flexBench", "flexbench", 65535) waitForThreads(pThreadsData); void * tmp; - for(Uint32 i = 0; i<tNoOfThreads; i++){ + for(i = 0; i<tNoOfThreads; i++){ NdbThread_WaitFor(pThreadsData[i].threadLife, &tmp); NdbThread_Destroy(&pThreadsData[i].threadLife); } @@ -540,7 +540,7 @@ NDB_COMMAND(flexBench, "flexBench", "flexBench", "flexbench", 65535) if (useLongKeys == true) { // Only free these areas if they have been allocated // Otherwise cores will happen - for (Uint32 i = 0; i < tNoOfLongPK; i++) + for (i = 0; i < tNoOfLongPK; i++) free(longKeyAttrName[i]); free(longKeyAttrName); } // if @@ -629,9 +629,10 @@ static void* flexBenchThread(void* pArg) if(useLongKeys){ // Allocate and populate the longkey array. longKeyAttrValue = (unsigned ***) malloc(sizeof(unsigned**) * tNoOfOperations ); - for (Uint32 n = 0; n < tNoOfOperations; n++) + Uint32 n; + for (n = 0; n < tNoOfOperations; n++) longKeyAttrValue[n] = (unsigned **) malloc(sizeof(unsigned*) * tNoOfLongPK ); - for (Uint32 n = 0; n < tNoOfOperations; n++){ + for (n = 0; n < tNoOfOperations; n++){ for (Uint32 i = 0; i < tNoOfLongPK ; i++) { longKeyAttrValue[n][i] = (unsigned *) malloc(sizeof(unsigned) * tSizeOfLongPK); memset(longKeyAttrValue[n][i], 0, sizeof(unsigned) * tSizeOfLongPK); @@ -1064,13 +1065,14 @@ static void sleepBeforeStartingTest(int seconds){ static int createTables(Ndb* pMyNdb){ - for (Uint32 i = 0; i < tNoOfAttributes; i++){ + int i; + for (i = 0; i < tNoOfAttributes; i++){ snprintf(attrName[i], MAXSTRLEN, "COL%d", i); } // Note! Uses only uppercase letters in table name's // so that we can look at the tables with SQL - for (Uint32 i = 0; i < tNoOfTables; i++){ + for (i = 0; i < tNoOfTables; i++){ if (theStdTableNameFlag == 0){ snprintf(tableName[i], MAXSTRLEN, "TAB%d_%d", i, (int)(NdbTick_CurrentMillisecond() / 1000)); @@ -1079,7 +1081,7 @@ createTables(Ndb* pMyNdb){ } } - for(unsigned i = 0; i < tNoOfTables; i++){ + for(i = 0; i < tNoOfTables; i++){ ndbout << "Creating " << tableName[i] << "... "; NdbDictionary::Table tmpTable(tableName[i]); diff --git a/ndb/test/ndbapi/flexTT.cpp b/ndb/test/ndbapi/flexTT.cpp index a82875de5c2..c0ff31d1677 100644 --- a/ndb/test/ndbapi/flexTT.cpp +++ b/ndb/test/ndbapi/flexTT.cpp @@ -173,7 +173,7 @@ NDB_COMMAND(flexTT, "flexTT", "flexTT", "flexTT", 65535) { ThreadNdb* pThreadData; int returnValue = NDBT_OK; - + int i; flexTTErrorData = new ErrorData; flexTTErrorData->resetErrorCounters(); @@ -250,7 +250,7 @@ NDB_COMMAND(flexTT, "flexTT", "flexTT", "flexTT", 65535) * Create NDB objects. * ****************************************************************/ resetThreads(); - for (int i = 0; i < tNoOfThreads ; i++) { + for (i = 0; i < tNoOfThreads ; i++) { pThreadData[i].threadNo = i; threadLife[i] = NdbThread_Create(threadLoop, (void**)&pThreadData[i], @@ -301,7 +301,7 @@ NDB_COMMAND(flexTT, "flexTT", "flexTT", "flexTT", 65535) execute(stStop); void * tmp; - for(int i = 0; i<tNoOfThreads; i++){ + for(i = 0; i<tNoOfThreads; i++){ NdbThread_WaitFor(threadLife[i], &tmp); NdbThread_Destroy(&threadLife[i]); } diff --git a/ndb/test/ndbapi/old_dirs/testBackup/Makefile b/ndb/test/ndbapi/old_dirs/testBackup/Makefile index ce0e404803c..abf47dcfb2d 100644 --- a/ndb/test/ndbapi/old_dirs/testBackup/Makefile +++ b/ndb/test/ndbapi/old_dirs/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/old_dirs/testGrep/Makefile b/ndb/test/ndbapi/old_dirs/testGrep/Makefile index 34fdd7113d0..6bad3d56a00 100644 --- a/ndb/test/ndbapi/old_dirs/testGrep/Makefile +++ b/ndb/test/ndbapi/old_dirs/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/old_dirs/testGrep/verify/Makefile b/ndb/test/ndbapi/old_dirs/testGrep/verify/Makefile index 4e6182de6b2..256e3c98f36 100644 --- a/ndb/test/ndbapi/old_dirs/testGrep/verify/Makefile +++ b/ndb/test/ndbapi/old_dirs/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/testBackup.cpp b/ndb/test/ndbapi/testBackup.cpp index 129eced54b0..d328a7db292 100644 --- a/ndb/test/ndbapi/testBackup.cpp +++ b/ndb/test/ndbapi/testBackup.cpp @@ -205,6 +205,11 @@ int runClearTable(NDBT_Context* ctx, NDBT_Step* step){ return NDBT_OK; } +int runDropTable(NDBT_Context* ctx, NDBT_Step* step){ + GETNDB(step)->getDictionary()->dropTable(ctx->getTab()->getName()); + return NDBT_OK; +} + #include "bank/Bank.hpp" int runCreateBank(NDBT_Context* ctx, NDBT_Step* step){ @@ -408,7 +413,7 @@ TESTCASE("BackupOne", INITIALIZER(runRestoreOne); VERIFIER(runVerifyOne); FINALIZER(runClearTable); - + FINALIZER(runDropTable); } TESTCASE("BackupBank", "Test that backup and restore works during transaction load\n" @@ -428,7 +433,6 @@ TESTCASE("BackupBank", STEP(runBackupBank); VERIFIER(runRestoreBankAndVerify); // FINALIZER(runDropBank); - } TESTCASE("NFMaster", "Test that backup behaves during node failiure\n"){ diff --git a/ndb/test/ndbapi/testBasic.cpp b/ndb/test/ndbapi/testBasic.cpp index 64dfe492c2c..26622f9b066 100644 --- a/ndb/test/ndbapi/testBasic.cpp +++ b/ndb/test/ndbapi/testBasic.cpp @@ -29,9 +29,18 @@ * delete should be visible to same transaction * */ +int runLoadTable2(NDBT_Context* ctx, NDBT_Step* step) +{ + int records = ctx->getNumRecords(); + HugoTransactions hugoTrans(*ctx->getTab()); + if (hugoTrans.loadTable(GETNDB(step), records, 512, false, 0, true) != 0){ + return NDBT_FAILED; + } + return NDBT_OK; +} -int runLoadTable(NDBT_Context* ctx, NDBT_Step* step){ - +int runLoadTable(NDBT_Context* ctx, NDBT_Step* step) +{ int records = ctx->getNumRecords(); HugoTransactions hugoTrans(*ctx->getTab()); if (hugoTrans.loadTable(GETNDB(step), records) != 0){ @@ -255,7 +264,7 @@ static int readOneNoCommit(Ndb* pNdb, NdbConnection* pTrans, const NdbDictionary::Table* tab,NDBT_ResultRow * row){ - + int a; NdbOperation * pOp = pTrans->getNdbOperation(tab->getName()); if (pOp == NULL){ ERR(pTrans->getNdbError()); @@ -271,7 +280,7 @@ readOneNoCommit(Ndb* pNdb, NdbConnection* pTrans, } // Define primary keys - for(int a = 0; a<tab->getNoOfColumns(); a++){ + for(a = 0; a<tab->getNoOfColumns(); a++){ if (tab->getColumn(a)->getPrimaryKey() == true){ if(tmp.equalForAttr(pOp, a, 0) != 0){ ERR(pTrans->getNdbError()); @@ -281,7 +290,7 @@ readOneNoCommit(Ndb* pNdb, NdbConnection* pTrans, } // Define attributes to read - for(int a = 0; a<tab->getNoOfColumns(); a++){ + for(a = 0; a<tab->getNoOfColumns(); a++){ if((row->attributeStore(a) = pOp->getValue(tab->getColumn(a)->getName())) == 0) { ERR(pTrans->getNdbError()); @@ -630,35 +639,35 @@ int runNoCommitRollback630(NDBT_Context* ctx, NDBT_Step* step){ int runNoCommitAndClose(NDBT_Context* ctx, NDBT_Step* step){ - int result = NDBT_OK; + int i, result = NDBT_OK; HugoOperations hugoOps(*ctx->getTab()); Ndb* pNdb = GETNDB(step); do{ // Read CHECK(hugoOps.startTransaction(pNdb) == 0); - for (int i = 0; i < 10; i++) + for (i = 0; i < 10; i++) CHECK(hugoOps.pkReadRecord(pNdb, i, true) == 0); CHECK(hugoOps.execute_NoCommit(pNdb) == 0); CHECK(hugoOps.closeTransaction(pNdb) == 0); // Update CHECK(hugoOps.startTransaction(pNdb) == 0); - for (int i = 0; i < 10; i++) + for (i = 0; i < 10; i++) CHECK(hugoOps.pkUpdateRecord(pNdb, i) == 0); CHECK(hugoOps.execute_NoCommit(pNdb) == 0); CHECK(hugoOps.closeTransaction(pNdb) == 0); // Delete CHECK(hugoOps.startTransaction(pNdb) == 0); - for (int i = 0; i < 10; i++) + for (i = 0; i < 10; i++) CHECK(hugoOps.pkDeleteRecord(pNdb, i) == 0); CHECK(hugoOps.execute_NoCommit(pNdb) == 0); CHECK(hugoOps.closeTransaction(pNdb) == 0); // Try to insert, record should already exist CHECK(hugoOps.startTransaction(pNdb) == 0); - for (int i = 0; i < 10; i++) + for (i = 0; i < 10; i++) CHECK(hugoOps.pkInsertRecord(pNdb, i) == 0); CHECK(hugoOps.execute_Commit(pNdb) == 630); CHECK(hugoOps.closeTransaction(pNdb) == 0); @@ -772,14 +781,14 @@ int runCheckRollbackDeleteMultiple(NDBT_Context* ctx, NDBT_Step* step){ CHECK(hugoOps.closeTransaction(pNdb) == 0); Uint32 updatesValue = 0; - + Uint32 j; for(Uint32 i = 0; i<1; i++){ // Read record 5 - 10 CHECK(hugoOps.startTransaction(pNdb) == 0); CHECK(hugoOps.pkReadRecord(pNdb, 5, true, 10) == 0); CHECK(hugoOps.execute_NoCommit(pNdb) == 0); - for(Uint32 j = 0; j<10; j++){ + for(j = 0; j<10; j++){ // Update record 5 - 10 updatesValue++; CHECK(hugoOps.pkUpdateRecord(pNdb, 5, 10, updatesValue) == 0); @@ -790,7 +799,7 @@ int runCheckRollbackDeleteMultiple(NDBT_Context* ctx, NDBT_Step* step){ CHECK(hugoOps.verifyUpdatesValue(updatesValue) == 0); } - for(Uint32 j = 0; j<10; j++){ + for(j = 0; j<10; j++){ // Delete record 5 - 10 times CHECK(hugoOps.pkDeleteRecord(pNdb, 5, 10) == 0); CHECK(hugoOps.execute_NoCommit(pNdb) == 0); @@ -953,6 +962,7 @@ int runMassiveRollback(NDBT_Context* ctx, NDBT_Step* step){ const Uint32 OPS_TOTAL = 4096; for(int row = 0; row < records; row++){ + int res; CHECK(hugoOps.startTransaction(pNdb) == 0); for(int i = 0; i<OPS_TOTAL; i += OPS_PER_TRANS){ for(int j = 0; j<OPS_PER_TRANS; j++){ @@ -963,7 +973,12 @@ int runMassiveRollback(NDBT_Context* ctx, NDBT_Step* step){ if(result != NDBT_OK){ break; } - CHECK(hugoOps.execute_NoCommit(pNdb) == 0); + res = hugoOps.execute_NoCommit(pNdb); + if(res != 0){ + NdbError err = pNdb->getNdbError(res); + CHECK(err.classification == NdbError::TimeoutExpired); + break; + } } if(result != NDBT_OK){ break; @@ -1255,6 +1270,11 @@ TESTCASE("MassiveRollback2", INITIALIZER(runMassiveRollback2); FINALIZER(runClearTable2); } +TESTCASE("MassiveTransaction", + "Test very large insert transaction"){ + INITIALIZER(runLoadTable2); + FINALIZER(runClearTable2); +} NDBT_TESTSUITE_END(testBasic); int main(int argc, const char** argv){ diff --git a/ndb/test/ndbapi/testBlobs.cpp b/ndb/test/ndbapi/testBlobs.cpp index 001ec83630a..64881ca39ab 100644 --- a/ndb/test/ndbapi/testBlobs.cpp +++ b/ndb/test/ndbapi/testBlobs.cpp @@ -38,6 +38,7 @@ struct Bcol { }; struct Opt { + unsigned m_batch; bool m_core; bool m_dbg; bool m_dbgall; @@ -46,7 +47,8 @@ struct Opt { unsigned m_parts; unsigned m_rows; unsigned m_seed; - char m_skip[255]; + const char* m_skip; + const char* m_style; // metadata const char* m_tname; const char* m_x1name; // hash index @@ -60,6 +62,7 @@ struct Opt { int m_bug; int (*m_bugtest)(); Opt() : + m_batch(7), m_core(false), m_dbg(false), m_dbgall(false), @@ -68,6 +71,8 @@ struct Opt { m_parts(10), m_rows(100), m_seed(0), + m_skip(""), + m_style("012"), // metadata m_tname("TBLOB1"), m_x1name("TBLOB1X1"), @@ -80,7 +85,6 @@ struct Opt { // bugs m_bug(0), m_bugtest(0) { - memset(m_skip, false, sizeof(m_skip)); } }; @@ -92,6 +96,7 @@ printusage() Opt d; ndbout << "usage: testBlobs options [default/max]" << endl + << " -batch N number of pk ops in batch [" << d.m_batch << "]" << endl << " -core dump core on error" << endl << " -dbg print debug" << endl << " -dbgall print also NDB API debug (if compiled in)" << endl @@ -101,7 +106,8 @@ printusage() << " -parts N max parts in blob value [" << d.m_parts << "]" << endl << " -rows N number of rows [" << d.m_rows << "]" << endl << " -seed N random seed 0=loop number [" << d.m_seed << "]" << endl - << " -skip xxx skip these tests (see list)" << endl + << " -skip xxx skip these tests (see list) [" << d.m_skip << endl + << " -style xxx access styles to test (see list) [" << d.m_style << "]" << endl << "metadata" << endl << " -pk2len N length of PK2 [" << d.m_pk2len << "/" << g_max_pk2len <<"]" << endl << " -oneblob only 1 blob attribute [default 2]" << endl @@ -111,8 +117,10 @@ printusage() << " s table scans" << endl << " r ordered index scans" << endl << " u update blob value" << endl - << " v getValue / setValue" << endl - << " w readData / writeData" << endl + << "access styles for -style" << endl + << " 0 getValue / setValue" << endl + << " 1 setActiveHook" << endl + << " 2 readData / writeData" << endl << "bug tests (no blob test)" << endl << " -bug 4088 ndb api hang with mixed ops on index table" << endl << " -bug 2222 delete + write gives 626" << endl @@ -122,11 +130,16 @@ printusage() static Opt g_opt; -static char& -skip(unsigned x) +static bool +skipcase(int x) { - assert(x < sizeof(g_opt.m_skip)); - return g_opt.m_skip[x]; + return strchr(g_opt.m_skip, x) != 0; +} + +static bool +skipstyle(int x) +{ + return strchr(g_opt.m_style, '0' + x) == 0; } static Ndb* g_ndb = 0; @@ -138,11 +151,12 @@ static NdbScanOperation* g_ops = 0; static NdbBlob* g_bh1 = 0; static NdbBlob* g_bh2 = 0; static bool g_printerror = true; +static unsigned g_loop = 0; static void printerror(int line, const char* msg) { - ndbout << "line " << line << ": " << msg << " failed" << endl; + ndbout << "line " << line << " FAIL " << msg << endl; if (! g_printerror) { return; } @@ -205,6 +219,7 @@ static int createTable() { NdbDictionary::Table tab(g_opt.m_tname); + tab.setLogging(false); // col PK1 - Uint32 { NdbDictionary::Column col("PK1"); col.setType(NdbDictionary::Column::Unsigned); @@ -228,11 +243,11 @@ createTable() col.setPrimaryKey(true); tab.addColumn(col); } - // col BL2 - Clob nullable + // col BL2 - Text nullable if (! g_opt.m_oneblob) { NdbDictionary::Column col("BL2"); const Bcol& b = g_opt.m_blob2; - col.setType(NdbDictionary::Column::Clob); + col.setType(NdbDictionary::Column::Text); col.setNullable(true); col.setInlineSize(b.m_inline); col.setPartSize(b.m_partsize); @@ -245,6 +260,7 @@ createTable() if (g_opt.m_pk2len != 0) { NdbDictionary::Index idx(g_opt.m_x1name); idx.setType(NdbDictionary::Index::UniqueHashIndex); + idx.setLogging(false); idx.setTable(g_opt.m_tname); idx.addColumnName("PK2"); CHK(g_dic->createIndex(idx) == 0); @@ -281,7 +297,7 @@ struct Bval { m_buf = new char [m_buflen]; trash(); } - void copy(const Bval& v) { + void copyfrom(const Bval& v) { m_len = v.m_len; delete [] m_val; if (v.m_val == 0) @@ -313,10 +329,10 @@ struct Tup { m_blob1.alloc(g_opt.m_blob1.m_inline + g_opt.m_blob1.m_partsize * g_opt.m_parts); m_blob2.alloc(g_opt.m_blob2.m_inline + g_opt.m_blob2.m_partsize * g_opt.m_parts); } - void copy(const Tup& tup) { + void copyfrom(const Tup& tup) { assert(m_pk1 == tup.m_pk1); - m_blob1.copy(tup.m_blob1); - m_blob2.copy(tup.m_blob2); + m_blob1.copyfrom(tup.m_blob1); + m_blob2.copyfrom(tup.m_blob2); } private: Tup(const Tup&); @@ -358,6 +374,14 @@ calcBval(const Bcol& b, Bval& v, bool keepsize) } static void +calcBval(Tup& tup, bool keepsize) +{ + calcBval(g_opt.m_blob1, tup.m_blob1, keepsize); + if (! g_opt.m_oneblob) + calcBval(g_opt.m_blob2, tup.m_blob2, keepsize); +} + +static void calcTups(bool keepsize) { for (unsigned k = 0; k < g_opt.m_rows; k++) { @@ -371,31 +395,59 @@ calcTups(bool keepsize) tup.m_pk2[i] = 'a' + i % 26; } } - calcBval(g_opt.m_blob1, tup.m_blob1, keepsize); - if (! g_opt.m_oneblob) - calcBval(g_opt.m_blob2, tup.m_blob2, keepsize); + calcBval(tup, keepsize); } } // blob handle ops static int +getBlobHandles(NdbOperation* opr) +{ + CHK((g_bh1 = opr->getBlobHandle("BL1")) != 0); + if (! g_opt.m_oneblob) + CHK((g_bh2 = opr->getBlobHandle("BL2")) != 0); + return 0; +} + +static int +getBlobHandles(NdbIndexOperation* opx) +{ + CHK((g_bh1 = opx->getBlobHandle("BL1")) != 0); + if (! g_opt.m_oneblob) + CHK((g_bh2 = opx->getBlobHandle("BL2")) != 0); + return 0; +} + +static int +getBlobHandles(NdbScanOperation* ops) +{ + CHK((g_bh1 = ops->getBlobHandle("BL1")) != 0); + if (! g_opt.m_oneblob) + CHK((g_bh2 = ops->getBlobHandle("BL2")) != 0); + return 0; +} + +static int getBlobLength(NdbBlob* h, unsigned& len) { Uint64 len2 = (unsigned)-1; CHK(h->getLength(len2) == 0); len = (unsigned)len2; assert(len == len2); + DBG("getBlobLength " << h->getColumn()->getName() << " len=" << len); return 0; } +// setValue / getValue + static int setBlobValue(NdbBlob* h, const Bval& v) { bool null = (v.m_val == 0); bool isNull; unsigned len; - DBG("set " << h->getColumn()->getName() << " len=" << v.m_len << " null=" << null); + DBG("setValue " << h->getColumn()->getName() << " len=" << v.m_len << " null=" << null); if (null) { CHK(h->setNull() == 0); isNull = false; @@ -410,10 +462,19 @@ setBlobValue(NdbBlob* h, const Bval& v) } static int +setBlobValue(const Tup& tup) +{ + CHK(setBlobValue(g_bh1, tup.m_blob1) == 0); + if (! g_opt.m_oneblob) + CHK(setBlobValue(g_bh2, tup.m_blob2) == 0); + return 0; +} + +static int getBlobValue(NdbBlob* h, const Bval& v) { bool null = (v.m_val == 0); - DBG("get " << h->getColumn()->getName() << " len=" << v.m_len << " null=" << null); + DBG("getValue " << h->getColumn()->getName() << " buflen=" << v.m_buflen); CHK(h->getValue(v.m_buf, v.m_buflen) == 0); return 0; } @@ -456,6 +517,8 @@ verifyBlobValue(const Tup& tup) return 0; } +// readData / writeData + static int writeBlobData(NdbBlob* h, const Bval& v) { @@ -469,6 +532,7 @@ writeBlobData(NdbBlob* h, const Bval& v) CHK(h->getNull(isNull) == 0 && isNull == true); CHK(getBlobLength(h, len) == 0 && len == 0); } else { + CHK(h->truncate(v.m_len) == 0); unsigned n = 0; do { unsigned m = g_opt.m_full ? v.m_len : urandom(v.m_len + 1); @@ -487,6 +551,15 @@ writeBlobData(NdbBlob* h, const Bval& v) } static int +writeBlobData(const Tup& tup) +{ + CHK(writeBlobData(g_bh1, tup.m_blob1) == 0); + if (! g_opt.m_oneblob) + CHK(writeBlobData(g_bh2, tup.m_blob2) == 0); + return 0; +} + +static int readBlobData(NdbBlob* h, const Bval& v) { bool null = (v.m_val == 0); @@ -531,6 +604,71 @@ readBlobData(const Tup& tup) return 0; } +// hooks + +static NdbBlob::ActiveHook blobWriteHook; + +static int +blobWriteHook(NdbBlob* h, void* arg) +{ + DBG("blobWriteHook"); + Bval& v = *(Bval*)arg; + CHK(writeBlobData(h, v) == 0); + return 0; +} + +static int +setBlobWriteHook(NdbBlob* h, Bval& v) +{ + DBG("setBlobWriteHook"); + CHK(h->setActiveHook(blobWriteHook, &v) == 0); + return 0; +} + +static int +setBlobWriteHook(Tup& tup) +{ + CHK(setBlobWriteHook(g_bh1, tup.m_blob1) == 0); + if (! g_opt.m_oneblob) + CHK(setBlobWriteHook(g_bh2, tup.m_blob2) == 0); + return 0; +} + +static NdbBlob::ActiveHook blobReadHook; + +// no PK yet to identify tuple so just read the value +static int +blobReadHook(NdbBlob* h, void* arg) +{ + DBG("blobReadHook"); + Bval& v = *(Bval*)arg; + unsigned len; + CHK(getBlobLength(h, len) == 0); + v.alloc(len); + Uint32 maxlen = 0xffffffff; + CHK(h->readData(v.m_buf, maxlen) == 0); + DBG("read " << maxlen << " bytes"); + CHK(len == maxlen); + return 0; +} + +static int +setBlobReadHook(NdbBlob* h, Bval& v) +{ + DBG("setBlobReadHook"); + CHK(h->setActiveHook(blobReadHook, &v) == 0); + return 0; +} + +static int +setBlobReadHook(Tup& tup) +{ + CHK(setBlobReadHook(g_bh1, tup.m_blob1) == 0); + if (! g_opt.m_oneblob) + CHK(setBlobReadHook(g_bh2, tup.m_blob2) == 0); + return 0; +} + // verify blob data static int @@ -540,7 +678,11 @@ verifyHeadInline(const Bcol& c, const Bval& v, NdbRecAttr* ra) CHK(ra->isNULL() == 1); } else { CHK(ra->isNULL() == 0); - CHK(ra->u_64_value() == v.m_len); + const NdbBlob::Head* head = (const NdbBlob::Head*)ra->aRef(); + CHK(head->length == v.m_len); + const char* data = (const char*)(head + 1); + for (unsigned i = 0; i < head->length && i < c.m_inline; i++) + CHK(data[i] == v.m_val[i]); } return 0; } @@ -548,7 +690,7 @@ verifyHeadInline(const Bcol& c, const Bval& v, NdbRecAttr* ra) static int verifyHeadInline(const Tup& tup) { - DBG("verifyHeadInline pk1=" << tup.m_pk1); + DBG("verifyHeadInline pk1=" << hex << tup.m_pk1); CHK((g_con = g_ndb->startTransaction()) != 0); CHK((g_opr = g_con->getNdbOperation(g_opt.m_tname)) != 0); CHK(g_opr->readTuple() == 0); @@ -580,17 +722,18 @@ verifyHeadInline(const Tup& tup) static int verifyBlobTable(const Bcol& b, const Bval& v, Uint32 pk1, bool exists) { - DBG("verify " << b.m_btname << " pk1=" << pk1); + DBG("verify " << b.m_btname << " pk1=" << hex << pk1); NdbRecAttr* ra_pk; NdbRecAttr* ra_part; NdbRecAttr* ra_data; + NdbResultSet* rs; CHK((g_con = g_ndb->startTransaction()) != 0); - CHK((g_opr = g_con->getNdbOperation(b.m_btname)) != 0); - CHK(g_opr->openScanRead() == 0); - CHK((ra_pk = g_opr->getValue("PK")) != 0); - CHK((ra_part = g_opr->getValue("PART")) != 0); - CHK((ra_data = g_opr->getValue("DATA")) != 0); - CHK(g_con->executeScan() == 0); + CHK((g_ops = g_con->getNdbScanOperation(b.m_btname)) != 0); + CHK((rs = g_ops->readTuples()) != 0); + CHK((ra_pk = g_ops->getValue("PK")) != 0); + CHK((ra_part = g_ops->getValue("PART")) != 0); + CHK((ra_data = g_ops->getValue("DATA")) != 0); + CHK(g_con->execute(NoCommit) == 0); unsigned partcount; if (! exists || v.m_len <= b.m_inline) partcount = 0; @@ -600,7 +743,7 @@ verifyBlobTable(const Bcol& b, const Bval& v, Uint32 pk1, bool exists) memset(seen, 0, partcount); while (1) { int ret; - CHK((ret = g_con->nextScanResult()) == 0 || ret == 1); + CHK((ret = rs->nextResult()) == 0 || ret == 1); if (ret == 1) break; if (pk1 != ra_pk->u_32_value()) @@ -620,7 +763,7 @@ verifyBlobTable(const Bcol& b, const Bval& v, Uint32 pk1, bool exists) for (unsigned i = 0; i < partcount; i++) CHK(seen[i] == 1); g_ndb->closeTransaction(g_con); - g_opr = 0; + g_ops = 0; g_con = 0; return 0; } @@ -639,7 +782,7 @@ verifyBlob() { for (unsigned k = 0; k < g_opt.m_rows; k++) { const Tup& tup = g_tups[k]; - DBG("verifyBlob pk1=" << tup.m_pk1); + DBG("verifyBlob pk1=" << hex << tup.m_pk1); CHK(verifyHeadInline(tup) == 0); CHK(verifyBlobTable(tup) == 0); } @@ -648,105 +791,120 @@ verifyBlob() // operations +static const char* stylename[3] = { + "style=getValue/setValue", + "style=setActiveHook", + "style=readData/writeData" +}; + +// pk ops + static int -insertPk(bool rw) +insertPk(int style) { - DBG("--- insertPk ---"); + DBG("--- insertPk " << stylename[style] << " ---"); + unsigned n = 0; + CHK((g_con = g_ndb->startTransaction()) != 0); for (unsigned k = 0; k < g_opt.m_rows; k++) { Tup& tup = g_tups[k]; - DBG("insertPk pk1=" << tup.m_pk1); - CHK((g_con = g_ndb->startTransaction()) != 0); + DBG("insertPk pk1=" << hex << tup.m_pk1); CHK((g_opr = g_con->getNdbOperation(g_opt.m_tname)) != 0); CHK(g_opr->insertTuple() == 0); CHK(g_opr->equal("PK1", tup.m_pk1) == 0); if (g_opt.m_pk2len != 0) CHK(g_opr->equal("PK2", tup.m_pk2) == 0); - CHK((g_bh1 = g_opr->getBlobHandle("BL1")) != 0); - if (! g_opt.m_oneblob) - CHK((g_bh2 = g_opr->getBlobHandle("BL2")) != 0); - if (! rw) { - CHK(setBlobValue(g_bh1, tup.m_blob1) == 0); - if (! g_opt.m_oneblob) - CHK(setBlobValue(g_bh2, tup.m_blob2) == 0); + CHK(getBlobHandles(g_opr) == 0); + if (style == 0) { + CHK(setBlobValue(tup) == 0); + } else if (style == 1) { + // non-nullable must be set + CHK(g_bh1->setValue("", 0) == 0); + CHK(setBlobWriteHook(tup) == 0); } else { // non-nullable must be set CHK(g_bh1->setValue("", 0) == 0); CHK(g_con->execute(NoCommit) == 0); - CHK(writeBlobData(g_bh1, tup.m_blob1) == 0); - if (! g_opt.m_oneblob) - CHK(writeBlobData(g_bh2, tup.m_blob2) == 0); + CHK(writeBlobData(tup) == 0); + } + // just another trap + if (urandom(10) == 0) + CHK(g_con->execute(NoCommit) == 0); + if (++n == g_opt.m_batch) { + CHK(g_con->execute(Commit) == 0); + g_ndb->closeTransaction(g_con); + CHK((g_con = g_ndb->startTransaction()) != 0); + n = 0; } - CHK(g_con->execute(Commit) == 0); - g_ndb->closeTransaction(g_con); g_opr = 0; - g_con = 0; tup.m_exists = true; } + if (n != 0) { + CHK(g_con->execute(Commit) == 0); + n = 0; + } + g_ndb->closeTransaction(g_con); + g_con = 0; return 0; } static int -updatePk(bool rw) +readPk(int style) { - DBG("--- updatePk ---"); + DBG("--- readPk " << stylename[style] << " ---"); for (unsigned k = 0; k < g_opt.m_rows; k++) { Tup& tup = g_tups[k]; - DBG("updatePk pk1=" << tup.m_pk1); + DBG("readPk pk1=" << hex << tup.m_pk1); CHK((g_con = g_ndb->startTransaction()) != 0); CHK((g_opr = g_con->getNdbOperation(g_opt.m_tname)) != 0); - CHK(g_opr->updateTuple() == 0); + CHK(g_opr->readTuple() == 0); CHK(g_opr->equal("PK1", tup.m_pk1) == 0); if (g_opt.m_pk2len != 0) CHK(g_opr->equal("PK2", tup.m_pk2) == 0); - CHK((g_bh1 = g_opr->getBlobHandle("BL1")) != 0); - if (! g_opt.m_oneblob) - CHK((g_bh2 = g_opr->getBlobHandle("BL2")) != 0); - if (! rw) { - CHK(setBlobValue(g_bh1, tup.m_blob1) == 0); - if (! g_opt.m_oneblob) - CHK(setBlobValue(g_bh2, tup.m_blob2) == 0); + CHK(getBlobHandles(g_opr) == 0); + if (style == 0) { + CHK(getBlobValue(tup) == 0); + } else if (style == 1) { + CHK(setBlobReadHook(tup) == 0); } else { CHK(g_con->execute(NoCommit) == 0); - CHK(writeBlobData(g_bh1, tup.m_blob1) == 0); - if (! g_opt.m_oneblob) - CHK(writeBlobData(g_bh2, tup.m_blob2) == 0); + CHK(readBlobData(tup) == 0); } CHK(g_con->execute(Commit) == 0); + if (style == 0 || style == 1) { + CHK(verifyBlobValue(tup) == 0); + } g_ndb->closeTransaction(g_con); g_opr = 0; g_con = 0; - tup.m_exists = true; } return 0; } static int -updateIdx(bool rw) +updatePk(int style) { - DBG("--- updateIdx ---"); + DBG("--- updatePk " << stylename[style] << " ---"); for (unsigned k = 0; k < g_opt.m_rows; k++) { Tup& tup = g_tups[k]; - DBG("updateIdx pk1=" << tup.m_pk1); + DBG("updatePk pk1=" << hex << tup.m_pk1); CHK((g_con = g_ndb->startTransaction()) != 0); - CHK((g_opx = g_con->getNdbIndexOperation(g_opt.m_x1name, g_opt.m_tname)) != 0); - CHK(g_opx->updateTuple() == 0); - CHK(g_opx->equal("PK2", tup.m_pk2) == 0); - CHK((g_bh1 = g_opx->getBlobHandle("BL1")) != 0); - if (! g_opt.m_oneblob) - CHK((g_bh2 = g_opx->getBlobHandle("BL2")) != 0); - if (! rw) { - CHK(setBlobValue(g_bh1, tup.m_blob1) == 0); - if (! g_opt.m_oneblob) - CHK(setBlobValue(g_bh2, tup.m_blob2) == 0); + CHK((g_opr = g_con->getNdbOperation(g_opt.m_tname)) != 0); + CHK(g_opr->updateTuple() == 0); + CHK(g_opr->equal("PK1", tup.m_pk1) == 0); + if (g_opt.m_pk2len != 0) + CHK(g_opr->equal("PK2", tup.m_pk2) == 0); + CHK(getBlobHandles(g_opr) == 0); + if (style == 0) { + CHK(setBlobValue(tup) == 0); + } else if (style == 1) { + CHK(setBlobWriteHook(tup) == 0); } else { CHK(g_con->execute(NoCommit) == 0); - CHK(writeBlobData(g_bh1, tup.m_blob1) == 0); - if (! g_opt.m_oneblob) - CHK(writeBlobData(g_bh2, tup.m_blob2) == 0); + CHK(writeBlobData(tup) == 0); } CHK(g_con->execute(Commit) == 0); g_ndb->closeTransaction(g_con); - g_opx = 0; + g_opr = 0; g_con = 0; tup.m_exists = true; } @@ -754,74 +912,115 @@ updateIdx(bool rw) } static int -readPk(bool rw) +deletePk() { - DBG("--- readPk ---"); + DBG("--- deletePk ---"); for (unsigned k = 0; k < g_opt.m_rows; k++) { Tup& tup = g_tups[k]; - DBG("readPk pk1=" << tup.m_pk1); + DBG("deletePk pk1=" << hex << tup.m_pk1); CHK((g_con = g_ndb->startTransaction()) != 0); CHK((g_opr = g_con->getNdbOperation(g_opt.m_tname)) != 0); - CHK(g_opr->readTuple() == 0); + CHK(g_opr->deleteTuple() == 0); CHK(g_opr->equal("PK1", tup.m_pk1) == 0); if (g_opt.m_pk2len != 0) CHK(g_opr->equal("PK2", tup.m_pk2) == 0); - CHK((g_bh1 = g_opr->getBlobHandle("BL1")) != 0); - if (! g_opt.m_oneblob) - CHK((g_bh2 = g_opr->getBlobHandle("BL2")) != 0); - if (! rw) { + CHK(g_con->execute(Commit) == 0); + g_ndb->closeTransaction(g_con); + g_opr = 0; + g_con = 0; + tup.m_exists = false; + } + return 0; +} + +// hash index ops + +static int +readIdx(int style) +{ + DBG("--- readIdx " << stylename[style] << " ---"); + for (unsigned k = 0; k < g_opt.m_rows; k++) { + Tup& tup = g_tups[k]; + DBG("readIdx pk1=" << hex << tup.m_pk1); + CHK((g_con = g_ndb->startTransaction()) != 0); + CHK((g_opx = g_con->getNdbIndexOperation(g_opt.m_x1name, g_opt.m_tname)) != 0); + CHK(g_opx->readTuple() == 0); + CHK(g_opx->equal("PK2", tup.m_pk2) == 0); + CHK(getBlobHandles(g_opx) == 0); + if (style == 0) { CHK(getBlobValue(tup) == 0); + } else if (style == 1) { + CHK(setBlobReadHook(tup) == 0); } else { CHK(g_con->execute(NoCommit) == 0); CHK(readBlobData(tup) == 0); } CHK(g_con->execute(Commit) == 0); - if (! rw) { + if (style == 0 || style == 1) { CHK(verifyBlobValue(tup) == 0); } g_ndb->closeTransaction(g_con); - g_opr = 0; + g_opx = 0; g_con = 0; } return 0; } static int -readIdx(bool rw) +updateIdx(int style) { - DBG("--- readIdx ---"); + DBG("--- updateIdx " << stylename[style] << " ---"); for (unsigned k = 0; k < g_opt.m_rows; k++) { Tup& tup = g_tups[k]; - DBG("readIdx pk1=" << tup.m_pk1); + DBG("updateIdx pk1=" << hex << tup.m_pk1); CHK((g_con = g_ndb->startTransaction()) != 0); CHK((g_opx = g_con->getNdbIndexOperation(g_opt.m_x1name, g_opt.m_tname)) != 0); - CHK(g_opx->readTuple() == 0); + CHK(g_opx->updateTuple() == 0); CHK(g_opx->equal("PK2", tup.m_pk2) == 0); - CHK((g_bh1 = g_opx->getBlobHandle("BL1")) != 0); - if (! g_opt.m_oneblob) - CHK((g_bh2 = g_opx->getBlobHandle("BL2")) != 0); - if (! rw) { - CHK(getBlobValue(tup) == 0); + CHK(getBlobHandles(g_opx) == 0); + if (style == 0) { + CHK(setBlobValue(tup) == 0); + } else if (style == 1) { + CHK(setBlobWriteHook(tup) == 0); } else { CHK(g_con->execute(NoCommit) == 0); - CHK(readBlobData(tup) == 0); + CHK(writeBlobData(tup) == 0); } CHK(g_con->execute(Commit) == 0); - if (! rw) { - CHK(verifyBlobValue(tup) == 0); - } g_ndb->closeTransaction(g_con); g_opx = 0; g_con = 0; + tup.m_exists = true; + } + return 0; +} + +static int +deleteIdx() +{ + DBG("--- deleteIdx ---"); + for (unsigned k = 0; k < g_opt.m_rows; k++) { + Tup& tup = g_tups[k]; + DBG("deleteIdx pk1=" << hex << tup.m_pk1); + CHK((g_con = g_ndb->startTransaction()) != 0); + CHK((g_opx = g_con->getNdbIndexOperation(g_opt.m_x1name, g_opt.m_tname)) != 0); + CHK(g_opx->deleteTuple() == 0); + CHK(g_opx->equal("PK2", tup.m_pk2) == 0); + CHK(g_con->execute(Commit) == 0); + g_ndb->closeTransaction(g_con); + g_opx = 0; + g_con = 0; + tup.m_exists = false; } return 0; } +// scan ops table and index + static int -readScan(bool rw, bool idx) +readScan(int style, bool idx) { - const char* func = ! idx ? "scan read table" : "scan read index"; - DBG("--- " << func << " ---"); + DBG("--- " << "readScan" << (idx ? "Idx" : "") << " " << stylename[style] << " ---"); Tup tup; tup.alloc(); // allocate buffers NdbResultSet* rs; @@ -829,17 +1028,17 @@ readScan(bool rw, bool idx) if (! idx) { CHK((g_ops = g_con->getNdbScanOperation(g_opt.m_tname)) != 0); } else { - CHK((g_ops = g_con->getNdbScanOperation(g_opt.m_x2name, g_opt.m_tname)) != 0); + CHK((g_ops = g_con->getNdbIndexScanOperation(g_opt.m_x2name, g_opt.m_tname)) != 0); } - CHK((rs = g_ops->readTuples(240, NdbScanOperation::LM_Exclusive)) != 0); + CHK((rs = g_ops->readTuples(NdbScanOperation::LM_Exclusive)) != 0); CHK(g_ops->getValue("PK1", (char*)&tup.m_pk1) != 0); if (g_opt.m_pk2len != 0) CHK(g_ops->getValue("PK2", tup.m_pk2) != 0); - CHK((g_bh1 = g_ops->getBlobHandle("BL1")) != 0); - if (! g_opt.m_oneblob) - CHK((g_bh2 = g_ops->getBlobHandle("BL2")) != 0); - if (! rw) { + CHK(getBlobHandles(g_ops) == 0); + if (style == 0) { CHK(getBlobValue(tup) == 0); + } else if (style == 1) { + CHK(setBlobReadHook(tup) == 0); } CHK(g_con->execute(NoCommit) == 0); unsigned rows = 0; @@ -850,11 +1049,14 @@ readScan(bool rw, bool idx) CHK((ret = rs->nextResult(true)) == 0 || ret == 1); if (ret == 1) break; - DBG(func << " pk1=" << tup.m_pk1); + DBG("readScan" << (idx ? "Idx" : "") << " pk1=" << hex << tup.m_pk1); Uint32 k = tup.m_pk1 - g_opt.m_pk1off; CHK(k < g_opt.m_rows && g_tups[k].m_exists); - tup.copy(g_tups[k]); - if (! rw) { + tup.copyfrom(g_tups[k]); + if (style == 0) { + CHK(verifyBlobValue(tup) == 0); + } else if (style == 1) { + // execute ops generated by callbacks, if any CHK(verifyBlobValue(tup) == 0); } else { CHK(readBlobData(tup) == 0); @@ -869,61 +1071,72 @@ readScan(bool rw, bool idx) } static int -deletePk() +updateScan(int style, bool idx) { - DBG("--- deletePk ---"); - for (unsigned k = 0; k < g_opt.m_rows; k++) { - Tup& tup = g_tups[k]; - DBG("deletePk pk1=" << tup.m_pk1); - CHK((g_con = g_ndb->startTransaction()) != 0); - CHK((g_opr = g_con->getNdbOperation(g_opt.m_tname)) != 0); - CHK(g_opr->deleteTuple() == 0); - CHK(g_opr->equal("PK1", tup.m_pk1) == 0); - if (g_opt.m_pk2len != 0) - CHK(g_opr->equal("PK2", tup.m_pk2) == 0); - CHK(g_con->execute(Commit) == 0); - g_ndb->closeTransaction(g_con); - g_opr = 0; - g_con = 0; - tup.m_exists = false; + DBG("--- " << "updateScan" << (idx ? "Idx" : "") << " " << stylename[style] << " ---"); + Tup tup; + tup.alloc(); // allocate buffers + NdbResultSet* rs; + CHK((g_con = g_ndb->startTransaction()) != 0); + if (! idx) { + CHK((g_ops = g_con->getNdbScanOperation(g_opt.m_tname)) != 0); + } else { + CHK((g_ops = g_con->getNdbIndexScanOperation(g_opt.m_x2name, g_opt.m_tname)) != 0); } - return 0; -} - -static int -deleteIdx() -{ - DBG("--- deleteIdx ---"); - for (unsigned k = 0; k < g_opt.m_rows; k++) { - Tup& tup = g_tups[k]; - DBG("deleteIdx pk1=" << tup.m_pk1); - CHK((g_con = g_ndb->startTransaction()) != 0); - CHK((g_opx = g_con->getNdbIndexOperation(g_opt.m_x1name, g_opt.m_tname)) != 0); - CHK(g_opx->deleteTuple() == 0); - CHK(g_opx->equal("PK2", tup.m_pk2) == 0); - CHK(g_con->execute(Commit) == 0); - g_ndb->closeTransaction(g_con); - g_opx = 0; - g_con = 0; - tup.m_exists = false; + CHK((rs = g_ops->readTuples(NdbScanOperation::LM_Exclusive)) != 0); + CHK(g_ops->getValue("PK1", (char*)&tup.m_pk1) != 0); + if (g_opt.m_pk2len != 0) + CHK(g_ops->getValue("PK2", tup.m_pk2) != 0); + CHK(g_con->execute(NoCommit) == 0); + unsigned rows = 0; + while (1) { + int ret; + tup.m_pk1 = (Uint32)-1; + memset(tup.m_pk2, 'x', g_opt.m_pk2len); + CHK((ret = rs->nextResult(true)) == 0 || ret == 1); + if (ret == 1) + break; + DBG("updateScan" << (idx ? "Idx" : "") << " pk1=" << hex << tup.m_pk1); + Uint32 k = tup.m_pk1 - g_opt.m_pk1off; + CHK(k < g_opt.m_rows && g_tups[k].m_exists); + // calculate new blob values + calcBval(g_tups[k], false); + tup.copyfrom(g_tups[k]); + CHK((g_opr = rs->updateTuple()) != 0); + CHK(getBlobHandles(g_opr) == 0); + if (style == 0) { + CHK(setBlobValue(tup) == 0); + } else if (style == 1) { + CHK(setBlobWriteHook(tup) == 0); + } else { + CHK(g_con->execute(NoCommit) == 0); + CHK(writeBlobData(tup) == 0); + } + CHK(g_con->execute(NoCommit) == 0); + g_opr = 0; + rows++; } + CHK(g_con->execute(Commit) == 0); + g_ndb->closeTransaction(g_con); + g_con = 0; + g_ops = 0; + CHK(g_opt.m_rows == rows); return 0; } static int deleteScan(bool idx) { - const char* func = ! idx ? "scan delete table" : "scan delete index"; - DBG("--- " << func << " ---"); + DBG("--- " << "deleteScan" << (idx ? "Idx" : "") << " ---"); Tup tup; NdbResultSet* rs; CHK((g_con = g_ndb->startTransaction()) != 0); if (! idx) { CHK((g_ops = g_con->getNdbScanOperation(g_opt.m_tname)) != 0); } else { - CHK((g_ops = g_con->getNdbScanOperation(g_opt.m_x2name, g_opt.m_tname)) != 0); + CHK((g_ops = g_con->getNdbIndexScanOperation(g_opt.m_x2name, g_opt.m_tname)) != 0); } - CHK((rs = g_ops->readTuples(240, NdbScanOperation::LM_Exclusive)) != 0); + CHK((rs = g_ops->readTuples(NdbScanOperation::LM_Exclusive)) != 0); CHK(g_ops->getValue("PK1", (char*)&tup.m_pk1) != 0); if (g_opt.m_pk2len != 0) CHK(g_ops->getValue("PK2", tup.m_pk2) != 0); @@ -936,7 +1149,7 @@ deleteScan(bool idx) CHK((ret = rs->nextResult()) == 0 || ret == 1); if (ret == 1) break; - DBG(func << " pk1=" << tup.m_pk1); + DBG("deleteScan" << (idx ? "Idx" : "") << " pk1=" << hex << tup.m_pk1); CHK(rs->deleteTuple() == 0); CHK(g_con->execute(NoCommit) == 0); Uint32 k = tup.m_pk1 - g_opt.m_pk1off; @@ -947,7 +1160,6 @@ deleteScan(bool idx) CHK(g_con->execute(Commit) == 0); g_ndb->closeTransaction(g_con); g_con = 0; - g_opr = 0; g_ops = 0; CHK(g_opt.m_rows == rows); return 0; @@ -958,6 +1170,7 @@ deleteScan(bool idx) static int testmain() { + int style; g_ndb = new Ndb("TEST_DB"); CHK(g_ndb->init() == 0); CHK(g_ndb->waitUntilReady() == 0); @@ -980,69 +1193,75 @@ testmain() } if (g_opt.m_seed != 0) srandom(g_opt.m_seed); - for (unsigned loop = 0; g_opt.m_loop == 0 || loop < g_opt.m_loop; loop++) { - DBG("=== loop " << loop << " ==="); + for (g_loop = 0; g_opt.m_loop == 0 || g_loop < g_opt.m_loop; g_loop++) { + DBG("=== loop " << g_loop << " ==="); if (g_opt.m_seed == 0) - srandom(loop); - bool llim = skip('v') ? true : false; - bool ulim = skip('w') ? false : true; + srandom(g_loop); // pk - for (int rw = llim; rw <= ulim; rw++) { - if (skip('k')) + for (style = 0; style <= 2; style++) { + if (skipcase('k') || skipstyle(style)) continue; - DBG("--- pk ops " << (! rw ? "get/set" : "read/write") << " ---"); + DBG("--- pk ops " << stylename[style] << " ---"); calcTups(false); - CHK(insertPk(rw) == 0); + CHK(insertPk(style) == 0); CHK(verifyBlob() == 0); - CHK(readPk(rw) == 0); - if (! skip('u')) { - calcTups(rw); - CHK(updatePk(rw) == 0); + CHK(readPk(style) == 0); + if (! skipcase('u')) { + calcTups(style); + CHK(updatePk(style) == 0); CHK(verifyBlob() == 0); } - CHK(readPk(rw) == 0); + CHK(readPk(style) == 0); CHK(deletePk() == 0); CHK(verifyBlob() == 0); } // hash index - for (int rw = llim; rw <= ulim; rw++) { - if (skip('i')) + for (style = 0; style <= 2; style++) { + if (skipcase('i') || skipstyle(style)) continue; - DBG("--- idx ops " << (! rw ? "get/set" : "read/write") << " ---"); + DBG("--- idx ops " << stylename[style] << " ---"); calcTups(false); - CHK(insertPk(rw) == 0); + CHK(insertPk(style) == 0); CHK(verifyBlob() == 0); - CHK(readIdx(rw) == 0); - calcTups(rw); - if (! skip('u')) { - CHK(updateIdx(rw) == 0); + CHK(readIdx(style) == 0); + calcTups(style); + if (! skipcase('u')) { + CHK(updateIdx(style) == 0); CHK(verifyBlob() == 0); - CHK(readIdx(rw) == 0); + CHK(readIdx(style) == 0); } CHK(deleteIdx() == 0); CHK(verifyBlob() == 0); } // scan table - for (int rw = llim; rw <= ulim; rw++) { - if (skip('s')) + for (style = 0; style <= 2; style++) { + if (skipcase('s') || skipstyle(style)) continue; - DBG("--- table scan " << (! rw ? "get/set" : "read/write") << " ---"); + DBG("--- table scan " << stylename[style] << " ---"); calcTups(false); - CHK(insertPk(rw) == 0); + CHK(insertPk(style) == 0); CHK(verifyBlob() == 0); - CHK(readScan(rw, false) == 0); + CHK(readScan(style, false) == 0); + if (! skipcase('u')) { + CHK(updateScan(style, false) == 0); + CHK(verifyBlob() == 0); + } CHK(deleteScan(false) == 0); CHK(verifyBlob() == 0); } // scan index - for (int rw = llim; rw <= ulim; rw++) { - if (skip('r')) + for (style = 0; style <= 2; style++) { + if (skipcase('r') || skipstyle(style)) continue; - DBG("--- index scan " << (! rw ? "get/set" : "read/write") << " ---"); + DBG("--- index scan " << stylename[style] << " ---"); calcTups(false); - CHK(insertPk(rw) == 0); + CHK(insertPk(style) == 0); CHK(verifyBlob() == 0); - CHK(readScan(rw, true) == 0); + CHK(readScan(style, true) == 0); + if (! skipcase('u')) { + CHK(updateScan(style, true) == 0); + CHK(verifyBlob() == 0); + } CHK(deleteScan(true) == 0); CHK(verifyBlob() == 0); } @@ -1056,6 +1275,7 @@ testmain() static int bugtest_4088() { + unsigned i; DBG("bug test 4088 - ndb api hang with mixed ops on index table"); // insert rows calcTups(false); @@ -1067,7 +1287,7 @@ bugtest_4088() // read table pk via index as a table const unsigned pkcnt = 2; Tup pktup[pkcnt]; - for (unsigned i = 0; i < pkcnt; i++) { + for (i = 0; i < pkcnt; i++) { char name[20]; // XXX guess table id sprintf(name, "%d/%s", 4, g_opt.m_x1name); @@ -1086,7 +1306,7 @@ bugtest_4088() // BUG 4088: gets 1 tckeyconf, 1 tcindxconf, then hangs CHK(g_con->execute(Commit) == 0); // verify - for (unsigned i = 0; i < pkcnt; i++) { + for (i = 0; i < pkcnt; i++) { CHK(pktup[i].m_pk1 == tup.m_pk1); CHK(memcmp(pktup[i].m_pk2, tup.m_pk2, g_opt.m_pk2len) == 0); } @@ -1120,6 +1340,12 @@ NDB_COMMAND(testOdbcDriver, "testBlobs", "testBlobs", "testBlobs", 65535) { while (++argv, --argc > 0) { const char* arg = argv[0]; + if (strcmp(arg, "-batch") == 0) { + if (++argv, --argc > 0) { + g_opt.m_batch = atoi(argv[0]); + continue; + } + } if (strcmp(arg, "-core") == 0) { g_opt.m_core = true; continue; @@ -1131,7 +1357,7 @@ NDB_COMMAND(testOdbcDriver, "testBlobs", "testBlobs", "testBlobs", 65535) if (strcmp(arg, "-dbgall") == 0) { g_opt.m_dbg = true; g_opt.m_dbgall = true; - putenv("NDB_BLOB_DEBUG=1"); + putenv(strdup("NDB_BLOB_DEBUG=1")); continue; } if (strcmp(arg, "-full") == 0) { @@ -1164,9 +1390,13 @@ NDB_COMMAND(testOdbcDriver, "testBlobs", "testBlobs", "testBlobs", 65535) } if (strcmp(arg, "-skip") == 0) { if (++argv, --argc > 0) { - for (const char* p = argv[0]; *p != 0; p++) { - skip(*p) = true; - } + g_opt.m_skip = strdup(argv[0]); + continue; + } + } + if (strcmp(arg, "-style") == 0) { + if (++argv, --argc > 0) { + g_opt.m_style = strdup(argv[0]); continue; } } @@ -1174,10 +1404,6 @@ NDB_COMMAND(testOdbcDriver, "testBlobs", "testBlobs", "testBlobs", 65535) if (strcmp(arg, "-pk2len") == 0) { if (++argv, --argc > 0) { g_opt.m_pk2len = atoi(argv[0]); - if (g_opt.m_pk2len == 0) { - skip('i') = true; - skip('r') = true; - } if (g_opt.m_pk2len <= g_max_pk2len) continue; } @@ -1204,7 +1430,15 @@ NDB_COMMAND(testOdbcDriver, "testBlobs", "testBlobs", "testBlobs", 65535) printusage(); return NDBT_ProgramExit(NDBT_WRONGARGS); } + if (g_opt.m_pk2len == 0) { + char b[100]; + strcpy(b, g_opt.m_skip); + strcat(b, "i"); + strcat(b, "r"); + g_opt.m_skip = strdup(b); + } if (testmain() == -1) { + ndbout << "line " << __LINE__ << " FAIL loop=" << g_loop << endl; return NDBT_ProgramExit(NDBT_FAILED); } return NDBT_ProgramExit(NDBT_OK); diff --git a/ndb/test/ndbapi/testDataBuffers.cpp b/ndb/test/ndbapi/testDataBuffers.cpp index 75773040113..2e29dbb0d7b 100644 --- a/ndb/test/ndbapi/testDataBuffers.cpp +++ b/ndb/test/ndbapi/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 ((op = 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/testDeadlock.cpp b/ndb/test/ndbapi/testDeadlock.cpp new file mode 100644 index 00000000000..f51b3cea1e5 --- /dev/null +++ b/ndb/test/ndbapi/testDeadlock.cpp @@ -0,0 +1,514 @@ +/* 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 */ + +#include <ndb_global.h> +#include <NdbMain.h> +#include <NdbApi.hpp> +#include <NdbOut.hpp> +#include <NdbMutex.h> +#include <NdbCondition.h> +#include <NdbThread.h> +#include <NdbTest.hpp> + +struct Opt { + bool m_dbg; + const char* m_scan; + const char* m_tname; + const char* m_xname; + Opt() : + m_dbg(true), + m_scan("tx"), + m_tname("T"), + m_xname("X") + {} +}; + +static void +printusage() +{ + Opt d; + ndbout + << "usage: testDeadlock" << endl + << "-scan tx scan table, index [" << d.m_scan << "]" << endl + ; +} + +static Opt g_opt; + +static NdbMutex ndbout_mutex = NDB_MUTEX_INITIALIZER; + +#define DBG(x) \ + do { \ + if (! g_opt.m_dbg) break; \ + NdbMutex_Lock(&ndbout_mutex); \ + ndbout << "line " << __LINE__ << " " << x << endl; \ + NdbMutex_Unlock(&ndbout_mutex); \ + } while (0) + +#define CHK(x) \ + do { \ + if (x) break; \ + ndbout << "line " << __LINE__ << ": " << #x << " failed" << endl; \ + return -1; \ + } while (0) + +#define CHN(p, x) \ + do { \ + if (x) break; \ + ndbout << "line " << __LINE__ << ": " << #x << " failed" << endl; \ + ndbout << (p)->getNdbError() << endl; \ + return -1; \ + } while (0) + +// threads + +typedef int (*Runstep)(struct Thr& thr); + +struct Thr { + enum State { Wait, Start, Stop, Stopped, Exit }; + State m_state; + int m_no; + Runstep m_runstep; + int m_ret; + NdbMutex* m_mutex; + NdbCondition* m_cond; + NdbThread* m_thread; + void* m_status; + Ndb* m_ndb; + NdbConnection* m_con; + NdbScanOperation* m_scanop; + NdbIndexScanOperation* m_indexscanop; + NdbResultSet* m_rs; + // + Thr(int no); + ~Thr(); + int run(); + void start(Runstep runstep); + void stop(); + void stopped(); + void lock() { NdbMutex_Lock(m_mutex); } + void unlock() { NdbMutex_Unlock(m_mutex); } + void wait() { NdbCondition_Wait(m_cond, m_mutex); } + void signal() { NdbCondition_Signal(m_cond); } + void exit(); + void join() { NdbThread_WaitFor(m_thread, &m_status); } +}; + +static NdbOut& +operator<<(NdbOut& out, const Thr& thr) { + out << "thr " << thr.m_no; + return out; +} + +extern "C" { static void* runthread(void* arg); } + +Thr::Thr(int no) +{ + m_state = Wait; + m_no = no; + m_runstep = 0; + m_ret = 0; + m_mutex = NdbMutex_Create(); + m_cond = NdbCondition_Create(); + assert(m_mutex != 0 && m_cond != 0); + const unsigned stacksize = 256 * 1024; + const NDB_THREAD_PRIO prio = NDB_THREAD_PRIO_LOW; + m_thread = NdbThread_Create(runthread, (void**)this, stacksize, "me", prio); + if (m_thread == 0) { + DBG("create thread failed: errno=" << errno); + m_ret = -1; + } + m_status = 0; + m_ndb = 0; + m_con = 0; + m_scanop = 0; + m_indexscanop = 0; + m_rs = 0; +} + +Thr::~Thr() +{ + if (m_thread != 0) + NdbThread_Destroy(&m_thread); + if (m_cond != 0) + NdbCondition_Destroy(m_cond); + if (m_mutex != 0) + NdbMutex_Destroy(m_mutex); +} + +static void* +runthread(void* arg) { + Thr& thr = *(Thr*)arg; + thr.run(); + return 0; +} + +int +Thr::run() +{ + DBG(*this << " run"); + while (true) { + lock(); + while (m_state != Start && m_state != Exit) { + wait(); + } + if (m_state == Exit) { + DBG(*this << " exit"); + unlock(); + break; + } + m_ret = (*m_runstep)(*this); + m_state = Stopped; + signal(); + unlock(); + if (m_ret != 0) { + DBG(*this << " error exit"); + break; + } + } + delete m_ndb; + m_ndb = 0; + return 0; +} + +void +Thr::start(Runstep runstep) +{ + lock(); + m_state = Start; + m_runstep = runstep; + signal(); + unlock(); +} + +void +Thr::stopped() +{ + lock(); + while (m_state != Stopped) { + wait(); + } + m_state = Wait; + unlock(); +} + +void +Thr::exit() +{ + lock(); + m_state = Exit; + signal(); + unlock(); +} + +// general + +static int +runstep_connect(Thr& thr) +{ + Ndb* ndb = thr.m_ndb = new Ndb("TEST_DB"); + CHN(ndb, ndb->init() == 0); + CHN(ndb, ndb->waitUntilReady() == 0); + DBG(thr << " connected"); + return 0; +} + +static int +runstep_starttx(Thr& thr) +{ + Ndb* ndb = thr.m_ndb; + assert(ndb != 0); + CHN(ndb, (thr.m_con = ndb->startTransaction()) != 0); + DBG("thr " << thr.m_no << " tx started"); + return 0; +} + +/* + * WL1822 flush locks + * + * Table T with 3 tuples X, Y, Z. + * Two transactions (* = lock wait). + * + * - tx1 reads and locks Z + * - tx2 scans X, Y, *Z + * - tx2 returns X, Y before lock wait on Z + * - tx1 reads and locks *X + * - api asks for next tx2 result + * - LQH unlocks X via ACC or TUX [*] + * - tx1 gets lock on X + * - tx1 returns X to api + * - api commits tx1 + * - tx2 gets lock on Z + * - tx2 returs Z to api + * + * The point is deadlock is avoided due to [*]. + * The test is for 1 db node and 1 fragment table. + */ + +static char wl1822_scantx = 0; + +static const Uint32 wl1822_valA[3] = { 0, 1, 2 }; +static const Uint32 wl1822_valB[3] = { 3, 4, 5 }; + +static Uint32 wl1822_bufA = ~0; +static Uint32 wl1822_bufB = ~0; + +// map scan row to key (A) and reverse +static unsigned wl1822_r2k[3] = { 0, 0, 0 }; +static unsigned wl1822_k2r[3] = { 0, 0, 0 }; + +static int +wl1822_createtable(Thr& thr) +{ + Ndb* ndb = thr.m_ndb; + assert(ndb != 0); + NdbDictionary::Dictionary* dic = ndb->getDictionary(); + // drop T + if (dic->getTable(g_opt.m_tname) != 0) + CHN(dic, dic->dropTable(g_opt.m_tname) == 0); + // create T + NdbDictionary::Table tab(g_opt.m_tname); + tab.setFragmentType(NdbDictionary::Object::FragAllSmall); + { NdbDictionary::Column col("A"); + col.setType(NdbDictionary::Column::Unsigned); + col.setPrimaryKey(true); + tab.addColumn(col); + } + { NdbDictionary::Column col("B"); + col.setType(NdbDictionary::Column::Unsigned); + col.setPrimaryKey(false); + tab.addColumn(col); + } + CHN(dic, dic->createTable(tab) == 0); + // create X + NdbDictionary::Index ind(g_opt.m_xname); + ind.setTable(g_opt.m_tname); + ind.setType(NdbDictionary::Index::OrderedIndex); + ind.setLogging(false); + ind.addColumn("B"); + CHN(dic, dic->createIndex(ind) == 0); + DBG("created " << g_opt.m_tname << ", " << g_opt.m_xname); + return 0; +} + +static int +wl1822_insertrows(Thr& thr) +{ + // insert X, Y, Z + Ndb* ndb = thr.m_ndb; + assert(ndb != 0); + NdbConnection* con; + NdbOperation* op; + for (unsigned k = 0; k < 3; k++) { + CHN(ndb, (con = ndb->startTransaction()) != 0); + CHN(con, (op = con->getNdbOperation(g_opt.m_tname)) != 0); + CHN(op, op->insertTuple() == 0); + CHN(op, op->equal("A", (char*)&wl1822_valA[k]) == 0); + CHN(op, op->setValue("B", (char*)&wl1822_valB[k]) == 0); + CHN(con, con->execute(Commit) == 0); + ndb->closeTransaction(con); + } + DBG("inserted X, Y, Z"); + return 0; +} + +static int +wl1822_getscanorder(Thr& thr) +{ + // cheat, table order happens to be key order in my test + wl1822_r2k[0] = 0; + wl1822_r2k[1] = 1; + wl1822_r2k[2] = 2; + wl1822_k2r[0] = 0; + wl1822_k2r[1] = 1; + wl1822_k2r[2] = 2; + DBG("scan order determined"); + return 0; +} + +static int +wl1822_tx1_readZ(Thr& thr) +{ + // tx1 read Z with exclusive lock + NdbConnection* con = thr.m_con; + assert(con != 0); + NdbOperation* op; + CHN(con, (op = con->getNdbOperation(g_opt.m_tname)) != 0); + CHN(op, op->readTupleExclusive() == 0); + CHN(op, op->equal("A", wl1822_valA[wl1822_r2k[2]]) == 0); + wl1822_bufB = ~0; + CHN(op, op->getValue("B", (char*)&wl1822_bufB) != 0); + CHN(con, con->execute(NoCommit) == 0); + CHK(wl1822_bufB == wl1822_valB[wl1822_r2k[2]]); + DBG("tx1 locked Z"); + return 0; +} + +static int +wl1822_tx2_scanXY(Thr& thr) +{ + // tx2 scan X, Y with exclusive lock + NdbConnection* con = thr.m_con; + assert(con != 0); + NdbScanOperation* scanop; + NdbIndexScanOperation* indexscanop; + NdbResultSet* rs; + if (wl1822_scantx == 't') { + CHN(con, (scanop = thr.m_scanop = con->getNdbScanOperation(g_opt.m_tname)) != 0); + DBG("tx2 scan exclusive " << g_opt.m_tname); + } + if (wl1822_scantx == 'x') { + CHN(con, (scanop = thr.m_scanop = indexscanop = thr.m_indexscanop = con->getNdbIndexScanOperation(g_opt.m_xname, g_opt.m_tname)) != 0); + DBG("tx2 scan exclusive " << g_opt.m_xname); + } + CHN(scanop, (rs = thr.m_rs = scanop->readTuplesExclusive(16)) != 0); + CHN(scanop, scanop->getValue("A", (char*)&wl1822_bufA) != 0); + CHN(scanop, scanop->getValue("B", (char*)&wl1822_bufB) != 0); + CHN(con, con->execute(NoCommit) == 0); + unsigned row = 0; + while (row < 2) { + DBG("before row " << row); + int ret; + wl1822_bufA = wl1822_bufB = ~0; + CHN(con, (ret = rs->nextResult(true)) == 0); + DBG("got row " << row << " a=" << wl1822_bufA << " b=" << wl1822_bufB); + CHK(wl1822_bufA == wl1822_valA[wl1822_r2k[row]]); + CHK(wl1822_bufB == wl1822_valB[wl1822_r2k[row]]); + row++; + } + return 0; +} + +static int +wl1822_tx1_readX_commit(Thr& thr) +{ + // tx1 read X with exclusive lock and commit + NdbConnection* con = thr.m_con; + assert(con != 0); + NdbOperation* op; + CHN(con, (op = con->getNdbOperation(g_opt.m_tname)) != 0); + CHN(op, op->readTupleExclusive() == 0); + CHN(op, op->equal("A", wl1822_valA[wl1822_r2k[2]]) == 0); + wl1822_bufB = ~0; + CHN(op, op->getValue("B", (char*)&wl1822_bufB) != 0); + CHN(con, con->execute(NoCommit) == 0); + CHK(wl1822_bufB == wl1822_valB[wl1822_r2k[2]]); + DBG("tx1 locked X"); + CHN(con, con->execute(Commit) == 0); + DBG("tx1 commit"); + return 0; +} + +static int +wl1822_tx2_scanZ_close(Thr& thr) +{ + // tx2 scan Z with exclusive lock and close scan + Ndb* ndb = thr.m_ndb; + NdbConnection* con = thr.m_con; + NdbScanOperation* scanop = thr.m_scanop; + NdbResultSet* rs = thr.m_rs; + assert(ndb != 0 && con != 0 && scanop != 0 && rs != 0); + unsigned row = 2; + while (true) { + DBG("before row " << row); + int ret; + wl1822_bufA = wl1822_bufB = ~0; + CHN(con, (ret = rs->nextResult(true)) == 0 || ret == 1); + if (ret == 1) + break; + DBG("got row " << row << " a=" << wl1822_bufA << " b=" << wl1822_bufB); + CHK(wl1822_bufA == wl1822_valA[wl1822_r2k[row]]); + CHK(wl1822_bufB == wl1822_valB[wl1822_r2k[row]]); + row++; + } + ndb->closeTransaction(con); + CHK(row == 3); + return 0; +} + +// threads are synced between each step +static Runstep wl1822_step[][2] = { + { runstep_connect, runstep_connect }, + { wl1822_createtable, 0 }, + { wl1822_insertrows, 0 }, + { wl1822_getscanorder, 0 }, + { runstep_starttx, runstep_starttx }, + { wl1822_tx1_readZ, 0 }, + { 0, wl1822_tx2_scanXY }, + { wl1822_tx1_readX_commit, wl1822_tx2_scanZ_close } +}; +const unsigned wl1822_stepcount = sizeof(wl1822_step)/sizeof(wl1822_step[0]); + +static int +wl1822_main(char scantx) +{ + wl1822_scantx = scantx; + static const unsigned thrcount = 2; + // create threads for tx1 and tx2 + Thr* thrlist[2]; + for (int n = 0; n < thrcount; n++) { + Thr& thr = *(thrlist[n] = new Thr(1 + n)); + CHK(thr.m_ret == 0); + } + // run the steps + for (unsigned i = 0; i < wl1822_stepcount; i++) { + DBG("step " << i << " start"); + for (int n = 0; n < thrcount; n++) { + Thr& thr = *thrlist[n]; + Runstep runstep = wl1822_step[i][n]; + if (runstep != 0) + thr.start(runstep); + } + for (int n = 0; n < thrcount; n++) { + Thr& thr = *thrlist[n]; + Runstep runstep = wl1822_step[i][n]; + if (runstep != 0) + thr.stopped(); + } + } + // delete threads + for (int n = 0; n < thrcount; n++) { + Thr& thr = *thrlist[n]; + thr.exit(); + thr.join(); + delete &thr; + } + return 0; +} + +NDB_COMMAND(testOdbcDriver, "testDeadlock", "testDeadlock", "testDeadlock", 65535) +{ + while (++argv, --argc > 0) { + const char* arg = argv[0]; + if (strcmp(arg, "-scan") == 0) { + if (++argv, --argc > 0) { + g_opt.m_scan = strdup(argv[0]); + continue; + } + } + printusage(); + return NDBT_ProgramExit(NDBT_WRONGARGS); + } + if ( + strchr(g_opt.m_scan, 't') != 0 && wl1822_main('t') == -1 || + strchr(g_opt.m_scan, 'x') != 0 && wl1822_main('x') == -1 + ) { + return NDBT_ProgramExit(NDBT_FAILED); + } + return NDBT_ProgramExit(NDBT_OK); +} + +// vim: set sw=2 et: diff --git a/ndb/test/ndbapi/testDict.cpp b/ndb/test/ndbapi/testDict.cpp index 1451c942362..e7597c26960 100644 --- a/ndb/test/ndbapi/testDict.cpp +++ b/ndb/test/ndbapi/testDict.cpp @@ -537,6 +537,7 @@ int runTestFragmentTypes(NDBT_Context* ctx, NDBT_Step* step){ } const NdbDictionary::Table* pTab = ctx->getTab(); + pNdb->getDictionary()->dropTable(pTab->getName()); NdbDictionary::Table newTab(* pTab); // Set fragment type for table diff --git a/ndb/test/ndbapi/testGrep.cpp b/ndb/test/ndbapi/testGrep.cpp index 4b870f6f9a9..0bf84cb4ec8 100644 --- a/ndb/test/ndbapi/testGrep.cpp +++ b/ndb/test/ndbapi/testGrep.cpp @@ -254,8 +254,7 @@ int runClearTable(NDBT_Context* ctx, NDBT_Step* step){ return NDBT_OK; } - -#include "../bank/Bank.hpp" +#include "bank/Bank.hpp" int runCreateBank(NDBT_Context* ctx, NDBT_Step* step){ Bank bank; @@ -444,6 +443,7 @@ int runRestoreBankAndVerify(NDBT_Context* ctx, NDBT_Step* step){ return result; } */ + NDBT_TESTSUITE(testGrep); TESTCASE("GrepBasic", "Test that Global Replication works on one table \n" @@ -473,8 +473,6 @@ TESTCASE("GrepNodeRestart", } - - TESTCASE("GrepBank", "Test that grep and restore works during transaction load\n" " by backing up the bank" @@ -495,6 +493,7 @@ TESTCASE("GrepBank", // FINALIZER(runDropBank); } + TESTCASE("NFMaster", "Test that grep behaves during node failiure\n"){ INITIALIZER(setMaster); diff --git a/ndb/test/ndbapi/testIndex.cpp b/ndb/test/ndbapi/testIndex.cpp index 47db0b3cff7..6ebbfd8b680 100644 --- a/ndb/test/ndbapi/testIndex.cpp +++ b/ndb/test/ndbapi/testIndex.cpp @@ -26,7 +26,7 @@ #define CHECK(b) if (!(b)) { \ g_err << "ERR: "<< step->getName() \ << " failed on line " << __LINE__ << endl; \ - result = NDBT_FAILED; \ + result = NDBT_FAILED; break;\ } @@ -381,6 +381,27 @@ runVerifyIndex(NDBT_Context* ctx, NDBT_Step* step){ } int +sync_down(NDBT_Context* ctx){ + Uint32 threads = ctx->getProperty("PauseThreads", (unsigned)0); + if(threads){ + ctx->decProperty("PauseThreads"); + } + return 0; +} + +int +sync_up_and_wait(NDBT_Context* ctx){ + Uint32 threads = ctx->getProperty("Threads", (unsigned)0); + ndbout_c("Setting PauseThreads to %d", threads); + ctx->setProperty("PauseThreads", threads); + ctx->getPropertyWait("PauseThreads", (unsigned)0); + if(threads){ + ndbout_c("wait completed"); + } + return 0; +} + +int runTransactions1(NDBT_Context* ctx, NDBT_Step* step){ // Verify that data in index match // table data @@ -394,10 +415,17 @@ runTransactions1(NDBT_Context* ctx, NDBT_Step* step){ g_err << "Updated table failed" << endl; return NDBT_FAILED; } + + sync_down(ctx); + if(ctx->isTestStopped()) + break; + if (hugoTrans.scanUpdateRecords(pNdb, rows, batchSize) != 0){ g_err << "Updated table failed" << endl; return NDBT_FAILED; } + + sync_down(ctx); } return NDBT_OK; } @@ -418,7 +446,7 @@ runTransactions2(NDBT_Context* ctx, NDBT_Step* step){ return NDBT_FAILED; } #endif - + sync_down(ctx); if(ctx->isTestStopped()) break; #if 1 @@ -427,6 +455,7 @@ runTransactions2(NDBT_Context* ctx, NDBT_Step* step){ return NDBT_FAILED; } #endif + sync_down(ctx); } return NDBT_OK; } @@ -447,6 +476,7 @@ runTransactions3(NDBT_Context* ctx, NDBT_Step* step){ g_err << "Load table failed" << endl; return NDBT_FAILED; } + sync_down(ctx); if(ctx->isTestStopped()) break; @@ -454,7 +484,8 @@ runTransactions3(NDBT_Context* ctx, NDBT_Step* step){ g_err << "Updated table failed" << endl; return NDBT_FAILED; } - + + sync_down(ctx); if(ctx->isTestStopped()) break; @@ -463,6 +494,7 @@ runTransactions3(NDBT_Context* ctx, NDBT_Step* step){ return NDBT_FAILED; } + sync_down(ctx); if(ctx->isTestStopped()) break; @@ -471,6 +503,7 @@ runTransactions3(NDBT_Context* ctx, NDBT_Step* step){ return NDBT_FAILED; } + sync_down(ctx); if(ctx->isTestStopped()) break; @@ -479,6 +512,7 @@ runTransactions3(NDBT_Context* ctx, NDBT_Step* step){ return NDBT_FAILED; } + sync_down(ctx); if(ctx->isTestStopped()) break; @@ -486,12 +520,15 @@ runTransactions3(NDBT_Context* ctx, NDBT_Step* step){ g_err << "Clear table failed" << endl; return NDBT_FAILED; } + + sync_down(ctx); if(ctx->isTestStopped()) break; - + int count = -1; if(utilTrans.selectCount(pNdb, 64, &count) != 0 || count != 0) return NDBT_FAILED; + sync_down(ctx); } return NDBT_OK; } @@ -510,6 +547,7 @@ int runRestarts(NDBT_Context* ctx, NDBT_Step* step){ result = NDBT_FAILED; break; } + sync_up_and_wait(ctx); i++; } ctx->stopTest(); @@ -1130,7 +1168,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){ @@ -1259,6 +1297,7 @@ TESTCASE("CreateLoadDrop_O", TESTCASE("NFNR1", "Test that indexes are correctly maintained during node fail and node restart"){ TC_PROPERTY("LoggedIndexes", (unsigned)0); + //TC_PROPERTY("Threads", 2); INITIALIZER(runClearTable); INITIALIZER(createRandomIndex); INITIALIZER(runLoadTable); @@ -1492,4 +1531,4 @@ int main(int argc, const char** argv){ return testIndex.execute(argc, argv); } - +template class Vector<Attrib*>; diff --git a/ndb/test/ndbapi/testNdbApi.cpp b/ndb/test/ndbapi/testNdbApi.cpp index 2e08ebbed4e..5b171d42578 100644 --- a/ndb/test/ndbapi/testNdbApi.cpp +++ b/ndb/test/ndbapi/testNdbApi.cpp @@ -1010,4 +1010,5 @@ int main(int argc, const char** argv){ return testNdbApi.execute(argc, argv); } - +template class Vector<Ndb*>; +template class Vector<NdbConnection*>; diff --git a/ndb/test/ndbapi/testNodeRestart.cpp b/ndb/test/ndbapi/testNodeRestart.cpp index fd591f04c69..89b38c78e71 100644 --- a/ndb/test/ndbapi/testNodeRestart.cpp +++ b/ndb/test/ndbapi/testNodeRestart.cpp @@ -287,8 +287,6 @@ TESTCASE("Terror", STEP(runPkUpdateUntilStopped); STEP(runScanReadUntilStopped); STEP(runScanUpdateUntilStopped); - STEP(runInsertUntilStopped); - STEP(runClearTableUntilStopped); FINALIZER(runClearTable); } TESTCASE("FullDb", diff --git a/ndb/test/ndbapi/testOIBasic.cpp b/ndb/test/ndbapi/testOIBasic.cpp index 0ca8ce79e2e..c58dd8538e9 100644 --- a/ndb/test/ndbapi/testOIBasic.cpp +++ b/ndb/test/ndbapi/testOIBasic.cpp @@ -33,14 +33,18 @@ struct Opt { // common options + unsigned m_batch; const char* m_case; bool m_core; bool m_dups; NdbDictionary::Object::FragmentType m_fragtype; + unsigned m_idxloop; const char* m_index; unsigned m_loop; bool m_nologging; + bool m_msglock; unsigned m_rows; + unsigned m_samples; unsigned m_scanrd; unsigned m_scanex; unsigned m_seed; @@ -49,17 +53,21 @@ struct Opt { unsigned m_threads; unsigned m_v; Opt() : + m_batch(32), m_case(0), m_core(false), m_dups(false), m_fragtype(NdbDictionary::Object::FragUndefined), + m_idxloop(4), m_index(0), m_loop(1), m_nologging(false), + m_msglock(true), m_rows(1000), + m_samples(0), m_scanrd(240), m_scanex(240), - m_seed(1), + m_seed(0), m_subloop(4), m_table(0), m_threads(4), @@ -78,17 +86,19 @@ printhelp() Opt d; ndbout << "usage: testOIbasic [options]" << endl + << " -batch N pk operations in batch [" << d.m_batch << "]" << endl << " -case abc only given test cases (letters a-z)" << endl << " -core core dump on error [" << d.m_core << "]" << endl << " -dups allow duplicate tuples from index scan [" << d.m_dups << "]" << endl << " -fragtype T fragment type single/small/medium/large" << endl << " -index xyz only given index numbers (digits 1-9)" << endl - << " -loop N loop count full suite forever=0 [" << d.m_loop << "]" << endl + << " -loop N loop count full suite 0=forever [" << d.m_loop << "]" << endl << " -nologging create tables in no-logging mode" << endl << " -rows N rows per thread [" << d.m_rows << "]" << endl + << " -samples N samples for some timings (0=all) [" << d.m_samples << "]" << endl << " -scanrd N scan read parallelism [" << d.m_scanrd << "]" << endl << " -scanex N scan exclusive parallelism [" << d.m_scanex << "]" << endl - << " -seed N srandom seed [" << d.m_seed << "]" << endl + << " -seed N srandom seed 0=loop number[" << d.m_seed << "]" << endl << " -subloop N subtest loop count [" << d.m_subloop << "]" << endl << " -table xyz only given table numbers (digits 1-9)" << endl << " -threads N number of threads [" << d.m_threads << "]" << endl @@ -99,6 +109,12 @@ printhelp() printtables(); } +// not yet configurable +static const bool g_store_null_key = true; + +// compare NULL like normal value (NULL < not NULL, NULL == NULL) +static const bool g_compare_null = true; + // log and error macros static NdbMutex ndbout_mutex = NDB_MUTEX_INITIALIZER; @@ -124,9 +140,9 @@ getthrstr() #define LLN(n, s) \ do { \ if ((n) > g_opt.m_v) break; \ - NdbMutex_Lock(&ndbout_mutex); \ + if (g_opt.m_msglock) NdbMutex_Lock(&ndbout_mutex); \ ndbout << getthrstr() << s << endl; \ - NdbMutex_Unlock(&ndbout_mutex); \ + if (g_opt.m_msglock) NdbMutex_Unlock(&ndbout_mutex); \ } while(0) #define LL0(s) LLN(0, s) @@ -139,11 +155,10 @@ getthrstr() // following check a condition and return -1 on failure #undef CHK // simple check -#undef CHKTRY // execute action (try-catch) on failure -#undef CHKMSG // print extra message on failure +#undef CHKTRY // check with action on fail #undef CHKCON // print NDB API errors on failure -#define CHK(x) CHKTRY(x, ;) +#define CHK(x) CHKTRY(x, ;) #define CHKTRY(x, act) \ do { \ @@ -154,14 +169,6 @@ getthrstr() return -1; \ } while (0) -#define CHKMSG(x, msg) \ - do { \ - if (x) break; \ - LL0("line " << __LINE__ << ": " << #x << " failed: " << msg); \ - if (g_opt.m_core) abort(); \ - return -1; \ - } while (0) - #define CHKCON(x, con) \ do { \ if (x) break; \ @@ -177,6 +184,7 @@ class Thr; class Con; class Tab; class Set; +class Tmr; struct Par : public Opt { unsigned m_no; @@ -186,14 +194,17 @@ struct Par : public Opt { const Tab& tab() const { assert(m_tab != 0); return *m_tab; } Set* m_set; Set& set() const { assert(m_set != 0); return *m_set; } + Tmr* m_tmr; + Tmr& tmr() const { assert(m_tmr != 0); return *m_tmr; } unsigned m_totrows; - unsigned m_batch; // value calculation unsigned m_pctnull; unsigned m_range; unsigned m_pctrange; // do verify after read bool m_verify; + // deadlock possible + bool m_deadlock; // timer location Par(const Opt& opt) : Opt(opt), @@ -201,12 +212,13 @@ struct Par : public Opt { m_con(0), m_tab(0), m_set(0), + m_tmr(0), m_totrows(m_threads * m_rows), - m_batch(32), m_pctnull(10), m_range(m_rows), m_pctrange(0), - m_verify(false) { + m_verify(false), + m_deadlock(false) { } }; @@ -241,19 +253,20 @@ struct Tmr { void on(); void off(unsigned cnt = 0); const char* time(); + const char* pct(const Tmr& t1); const char* over(const Tmr& t1); NDB_TICKS m_on; unsigned m_ms; unsigned m_cnt; char m_time[100]; - char m_over[100]; + char m_text[100]; Tmr() { clr(); } }; void Tmr::clr() { - m_on = m_ms = m_cnt = m_time[0] = m_over[0] = 0; + m_on = m_ms = m_cnt = m_time[0] = m_text[0] = 0; } void @@ -285,14 +298,63 @@ Tmr::time() } const char* +Tmr::pct(const Tmr& t1) +{ + if (0 < t1.m_ms) { + sprintf(m_text, "%u pct", (100 * m_ms) / t1.m_ms); + } else { + sprintf(m_text, "[cannot measure]"); + } + return m_text; +} + +const char* Tmr::over(const Tmr& t1) { - if (0 < t1.m_ms && t1.m_ms < m_ms) { - sprintf(m_over, "%u pct", (100 * (m_ms - t1.m_ms)) / t1.m_ms); + if (0 < t1.m_ms) { + if (t1.m_ms <= m_ms) + sprintf(m_text, "%u pct", (100 * (m_ms - t1.m_ms)) / t1.m_ms); + else + sprintf(m_text, "-%u pct", (100 * (t1.m_ms - m_ms)) / t1.m_ms); } else { - sprintf(m_over, "[cannot measure]"); + sprintf(m_text, "[cannot measure]"); } - return m_over; + return m_text; +} + +// list of ints + +struct Lst { + Lst(); + unsigned m_arr[1000]; + unsigned m_cnt; + void push(unsigned i); + unsigned cnt() const; + void reset(); +}; + +Lst::Lst() : + m_cnt(0) +{ +} + +void +Lst::push(unsigned i) +{ + assert(m_cnt < sizeof(m_arr)/sizeof(m_arr[0])); + m_arr[m_cnt++] = i; +} + +unsigned +Lst::cnt() const +{ + return m_cnt; +} + +void +Lst::reset() +{ + m_cnt = 0; } // tables and indexes @@ -409,7 +471,7 @@ operator<<(NdbOut& out, const Tab& tab) return out; } -// tt1 + tt1x1 tt1x2 tt1x3 tt1x4 +// tt1 + tt1x1 tt1x2 tt1x3 tt1x4 tt1x5 static const Col tt1col[] = { @@ -422,24 +484,29 @@ tt1col[] = { static const ICol tt1x1col[] = { - { 0, tt1col[1] } + { 0, tt1col[0] } }; static const ICol tt1x2col[] = { + { 0, tt1col[1] } +}; + +static const ICol +tt1x3col[] = { { 0, tt1col[1] }, { 1, tt1col[2] } }; static const ICol -tt1x3col[] = { +tt1x4col[] = { { 0, tt1col[3] }, { 1, tt1col[2] }, { 2, tt1col[1] } }; static const ICol -tt1x4col[] = { +tt1x5col[] = { { 0, tt1col[1] }, { 1, tt1col[4] }, { 2, tt1col[2] }, @@ -453,17 +520,22 @@ tt1x1 = { static const ITab tt1x2 = { - "TT1X2", 2, tt1x2col + "TT1X2", 1, tt1x2col }; static const ITab tt1x3 = { - "TT1X3", 3, tt1x3col + "TT1X3", 2, tt1x3col }; static const ITab tt1x4 = { - "TT1X4", 4, tt1x4col + "TT1X4", 3, tt1x4col +}; + +static const ITab +tt1x5 = { + "TT1X5", 4, tt1x5col }; static const ITab @@ -471,15 +543,16 @@ tt1itab[] = { tt1x1, tt1x2, tt1x3, - tt1x4 + tt1x4, + tt1x5 }; static const Tab tt1 = { - "TT1", 5, tt1col, 4, tt1itab + "TT1", 5, tt1col, 5, tt1itab }; -// tt2 + tt2x1 tt2x2 tt2x3 tt2x4 +// tt2 + tt2x1 tt2x2 tt2x3 tt2x4 tt2x5 static const Col tt2col[] = { @@ -492,24 +565,29 @@ tt2col[] = { static const ICol tt2x1col[] = { + { 0, tt2col[0] } +}; + +static const ICol +tt2x2col[] = { { 0, tt2col[1] }, { 1, tt2col[2] } }; static const ICol -tt2x2col[] = { +tt2x3col[] = { { 0, tt2col[2] }, { 1, tt2col[1] } }; static const ICol -tt2x3col[] = { +tt2x4col[] = { { 0, tt2col[3] }, { 1, tt2col[4] } }; static const ICol -tt2x4col[] = { +tt2x5col[] = { { 0, tt2col[4] }, { 1, tt2col[3] }, { 2, tt2col[2] }, @@ -518,7 +596,7 @@ tt2x4col[] = { static const ITab tt2x1 = { - "TT2X1", 2, tt2x1col + "TT2X1", 1, tt2x1col }; static const ITab @@ -533,7 +611,12 @@ tt2x3 = { static const ITab tt2x4 = { - "TT2X4", 4, tt2x4col + "TT2X4", 2, tt2x4col +}; + +static const ITab +tt2x5 = { + "TT2X5", 4, tt2x5col }; static const ITab @@ -541,12 +624,13 @@ tt2itab[] = { tt2x1, tt2x2, tt2x3, - tt2x4 + tt2x4, + tt2x5 }; static const Tab tt2 = { - "TT2", 5, tt2col, 4, tt2itab + "TT2", 5, tt2col, 5, tt2itab }; // all tables @@ -567,40 +651,42 @@ struct Con { NdbDictionary::Dictionary* m_dic; NdbConnection* m_tx; NdbOperation* m_op; - NdbConnection* m_scantx; - NdbOperation* m_scanop; + NdbScanOperation* m_scanop; + NdbIndexScanOperation* m_indexscanop; + NdbResultSet* m_resultset; enum ScanMode { ScanNo = 0, Committed, Latest, Exclusive }; ScanMode m_scanmode; enum ErrType { ErrNone = 0, ErrDeadlock, ErrOther }; ErrType m_errtype; Con() : m_ndb(0), m_dic(0), m_tx(0), m_op(0), - m_scantx(0), m_scanop(0), m_scanmode(ScanNo), m_errtype(ErrNone) {} + m_scanop(0), m_indexscanop(0), m_resultset(0), m_scanmode(ScanNo), m_errtype(ErrNone) {} + ~Con() { + if (m_tx != 0) + closeTransaction(); + } int connect(); + void connect(const Con& con); void disconnect(); int startTransaction(); - int startBuddyTransaction(const Con& con); int getNdbOperation(const Tab& tab); - int getNdbOperation(const ITab& itab, const Tab& tab); + int getNdbScanOperation(const Tab& tab); + int getNdbScanOperation(const ITab& itab, const Tab& tab); int equal(int num, const char* addr); int getValue(int num, NdbRecAttr*& rec); int setValue(int num, const char* addr); int setBound(int num, int type, const void* value); int execute(ExecType t); + int execute(ExecType t, bool& deadlock); int openScanRead(unsigned parallelism); int openScanExclusive(unsigned parallelism); int executeScan(); - int nextScanResult(); - int takeOverForUpdate(Con& scan); - int takeOverForDelete(Con& scan); + int nextScanResult(bool fetchAllowed); + int nextScanResult(bool fetchAllowed, bool& deadlock); + int updateScanTuple(Con& con2); + int deleteScanTuple(Con& con2); void closeTransaction(); void printerror(NdbOut& out); - // flush dict cache - int bugger() { - //disconnect(); - //CHK(connect() == 0); - return 0; - } }; int @@ -610,12 +696,18 @@ Con::connect() m_ndb = new Ndb("TEST_DB"); CHKCON(m_ndb->init() == 0, *this); CHKCON(m_ndb->waitUntilReady(30) == 0, *this); - m_dic = m_ndb->getDictionary(); m_tx = 0, m_op = 0; return 0; } void +Con::connect(const Con& con) +{ + assert(m_ndb == 0); + m_ndb = con.m_ndb; +} + +void Con::disconnect() { delete m_ndb; @@ -625,31 +717,34 @@ Con::disconnect() int Con::startTransaction() { - assert(m_ndb != 0 && m_tx == 0); + assert(m_ndb != 0); + if (m_tx != 0) + closeTransaction(); CHKCON((m_tx = m_ndb->startTransaction()) != 0, *this); return 0; } int -Con::startBuddyTransaction(const Con& con) +Con::getNdbOperation(const Tab& tab) { - assert(m_ndb != 0 && m_tx == 0 && con.m_ndb == m_ndb && con.m_tx != 0); - CHKCON((m_tx = m_ndb->hupp(con.m_tx)) != 0, *this); + assert(m_tx != 0); + CHKCON((m_op = m_tx->getNdbOperation(tab.m_name)) != 0, *this); return 0; } int -Con::getNdbOperation(const Tab& tab) +Con::getNdbScanOperation(const Tab& tab) { assert(m_tx != 0); - CHKCON((m_op = m_tx->getNdbOperation(tab.m_name)) != 0, *this); + CHKCON((m_op = m_scanop = m_tx->getNdbScanOperation(tab.m_name)) != 0, *this); return 0; } int -Con::getNdbOperation(const ITab& itab, const Tab& tab) +Con::getNdbScanOperation(const ITab& itab, const Tab& tab) { - CHKCON((m_op = m_tx->getNdbOperation(itab.m_name, tab.m_name)) != 0, *this); + assert(m_tx != 0); + CHKCON((m_op = m_scanop = m_indexscanop = m_tx->getNdbIndexScanOperation(itab.m_name, tab.m_name)) != 0, *this); return 0; } @@ -681,7 +776,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_indexscanop->setBound(num, type, value) == 0, *this); return 0; } @@ -694,10 +789,26 @@ Con::execute(ExecType t) } int +Con::execute(ExecType t, bool& deadlock) +{ + int ret = execute(t); + if (ret != 0) { + if (deadlock && m_errtype == ErrDeadlock) { + LL3("caught deadlock"); + ret = 0; + } + } else { + deadlock = false; + } + CHK(ret == 0); + return 0; +} + +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; } @@ -705,39 +816,56 @@ 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; } int -Con::nextScanResult() +Con::nextScanResult(bool fetchAllowed) { int ret; - CHKCON((ret = m_tx->nextScanResult()) != -1, *this); - assert(ret == 0 || ret == 1); + assert(m_resultset != 0); + CHKCON((ret = m_resultset->nextResult(fetchAllowed)) != -1, *this); + assert(ret == 0 || ret == 1 || (! fetchAllowed && ret == 2)); + return ret; +} + +int +Con::nextScanResult(bool fetchAllowed, bool& deadlock) +{ + int ret = nextScanResult(fetchAllowed); + if (ret == -1) { + if (deadlock && m_errtype == ErrDeadlock) { + LL3("caught deadlock"); + ret = 0; + } + } else { + deadlock = false; + } + CHK(ret == 0 || ret == 1 || (! fetchAllowed && ret == 2)); return ret; } int -Con::takeOverForUpdate(Con& scan) +Con::updateScanTuple(Con& con2) { - assert(m_tx != 0 && scan.m_op != 0); - CHKCON((m_op = scan.m_op->takeOverForUpdate(m_tx)) != 0, scan); + assert(con2.m_tx != 0); + CHKCON((con2.m_op = m_resultset->updateTuple(con2.m_tx)) != 0, *this); return 0; } int -Con::takeOverForDelete(Con& scan) +Con::deleteScanTuple(Con& con2) { - assert(m_tx != 0 && scan.m_op != 0); - CHKCON((m_op = scan.m_op->takeOverForUpdate(m_tx)) != 0, scan); + assert(con2.m_tx != 0); + CHKCON(m_resultset->deleteTuple(con2.m_tx) == 0, *this); return 0; } @@ -765,7 +893,7 @@ Con::printerror(NdbOut& out) if (m_tx) { if ((code = m_tx->getNdbError().code) != 0) { LL0(++any << " con: error " << m_tx->getNdbError()); - if (code == 266 || code == 274 || code == 296 || code == 297) + if (code == 266 || code == 274 || code == 296 || code == 297 || code == 499) m_errtype = ErrDeadlock; } if (m_op && m_op->getNdbError().code != 0) { @@ -785,7 +913,7 @@ invalidateindex(Par par, const ITab& itab) { Con& con = par.con(); const Tab& tab = par.tab(); - con.m_dic->invalidateIndex(itab.m_name, tab.m_name); + con.m_ndb->getDictionary()->invalidateIndex(itab.m_name, tab.m_name); return 0; } @@ -809,7 +937,7 @@ invalidatetable(Par par) Con& con = par.con(); const Tab& tab = par.tab(); invalidateindex(par); - con.m_dic->invalidateTable(tab.m_name); + con.m_ndb->getDictionary()->invalidateTable(tab.m_name); return 0; } @@ -818,6 +946,7 @@ droptable(Par par) { Con& con = par.con(); const Tab& tab = par.tab(); + con.m_dic = con.m_ndb->getDictionary(); if (con.m_dic->getTable(tab.m_name) == 0) { // how to check for error LL4("no table " << tab.m_name); @@ -825,6 +954,7 @@ droptable(Par par) LL3("drop table " << tab.m_name); CHKCON(con.m_dic->dropTable(tab.m_name) == 0, con); } + con.m_dic = 0; return 0; } @@ -832,7 +962,6 @@ static int createtable(Par par) { Con& con = par.con(); - CHK(con.bugger() == 0); const Tab& tab = par.tab(); LL3("create table " << tab.m_name); LL4(tab); @@ -852,7 +981,9 @@ createtable(Par par) c.setNullable(col.m_nullable); t.addColumn(c); } + con.m_dic = con.m_ndb->getDictionary(); CHKCON(con.m_dic->createTable(t) == 0, con); + con.m_dic = 0; return 0; } @@ -861,6 +992,7 @@ dropindex(Par par, const ITab& itab) { Con& con = par.con(); const Tab& tab = par.tab(); + con.m_dic = con.m_ndb->getDictionary(); if (con.m_dic->getIndex(itab.m_name, tab.m_name) == 0) { // how to check for error LL4("no index " << itab.m_name); @@ -868,6 +1000,7 @@ dropindex(Par par, const ITab& itab) LL3("drop index " << itab.m_name); CHKCON(con.m_dic->dropIndex(itab.m_name, tab.m_name) == 0, con); } + con.m_dic = 0; return 0; } @@ -888,7 +1021,6 @@ static int createindex(Par par, const ITab& itab) { Con& con = par.con(); - CHK(con.bugger() == 0); const Tab& tab = par.tab(); LL3("create index " << itab.m_name); LL4(itab); @@ -900,7 +1032,9 @@ createindex(Par par, const ITab& itab) const Col& col = itab.m_icol[k].m_col; x.addColumnName(col.m_name); } + con.m_dic = con.m_ndb->getDictionary(); CHKCON(con.m_dic->createIndex(x) == 0, con); + con.m_dic = 0; return 0; } @@ -1115,9 +1249,9 @@ Val::cmp(const Val& val2) const assert(col.m_type == col2.m_type && col.m_length == col2.m_length); if (m_null || val2.m_null) { if (! m_null) - return -1; - if (! val2.m_null) return +1; + if (! val2.m_null) + return -1; return 0; } // verify data formats @@ -1175,6 +1309,8 @@ struct Row { const Tab& m_tab; Val** m_val; bool m_exist; + enum Op { NoOp = 0, ReadOp, InsOp, UpdOp, DelOp }; + Op m_pending; Row(const Tab& tab); ~Row(); void copy(const Row& row2); @@ -1199,6 +1335,7 @@ Row::Row(const Tab& tab) : m_val[k] = new Val(col); } m_exist = false; + m_pending = NoOp; } Row::~Row() @@ -1236,7 +1373,7 @@ int Row::verify(const Row& row2) const { const Tab& tab = m_tab; - assert(&tab == &row2.m_tab); + assert(&tab == &row2.m_tab && m_exist && row2.m_exist); for (unsigned k = 0; k < tab.m_cols; k++) { const Val& val = *m_val[k]; const Val& val2 = *row2.m_val[k]; @@ -1257,7 +1394,7 @@ Row::insrow(Par par) const Val& val = *m_val[k]; CHK(val.setval(par) == 0); } - m_exist = true; + m_pending = InsOp; return 0; } @@ -1273,6 +1410,7 @@ Row::updrow(Par par) const Val& val = *m_val[k]; CHK(val.setval(par) == 0); } + m_pending = UpdOp; return 0; } @@ -1290,7 +1428,7 @@ Row::delrow(Par par) if (col.m_pk) CHK(val.setval(par) == 0); } - m_exist = false; + m_pending = DelOp; return 0; } @@ -1307,7 +1445,6 @@ Row::selrow(Par par) if (col.m_pk) CHK(val.setval(par) == 0); } - m_exist = false; return 0; } @@ -1322,6 +1459,7 @@ Row::setrow(Par par) if (! col.m_pk) CHK(val.setval(par) == 0); } + m_pending = UpdOp; return 0; } @@ -1349,6 +1487,10 @@ operator<<(NdbOut& out, const Row& row) out << " "; out << *row.m_val[i]; } + out << " [exist=" << row.m_exist; + if (row.m_pending) + out << " pending=" << row.m_pending; + out << "]"; return out; } @@ -1357,15 +1499,19 @@ operator<<(NdbOut& out, const Row& row) struct Set { const Tab& m_tab; unsigned m_rows; - unsigned m_count; Row** m_row; Row** m_saverow; Row* m_keyrow; NdbRecAttr** m_rec; Set(const Tab& tab, unsigned rows); ~Set(); + void reset(); + unsigned count() const; // row methods bool exist(unsigned i) const; + Row::Op pending(unsigned i) const; + void notpending(unsigned i); + void notpending(const Lst& lst); void calc(Par par, unsigned i); int insrow(Par par, unsigned i); int updrow(Par par, unsigned i); @@ -1380,7 +1526,7 @@ struct Set { void savepoint(); void commit(); void rollback(); - // locking (not perfect since ops may complete in different order) + // protect structure NdbMutex* m_mutex; void lock() { NdbMutex_Lock(m_mutex); @@ -1396,9 +1542,9 @@ Set::Set(const Tab& tab, unsigned rows) : m_tab(tab) { m_rows = rows; - m_count = 0; m_row = new Row* [m_rows]; for (unsigned i = 0; i < m_rows; i++) { + // allocate on need to save space m_row[i] = 0; } m_saverow = 0; @@ -1425,11 +1571,47 @@ Set::~Set() NdbMutex_Destroy(m_mutex); } +void +Set::reset() +{ + for (unsigned i = 0; i < m_rows; i++) { + if (m_row[i] != 0) { + Row& row = *m_row[i]; + row.m_exist = false; + } + } +} + +unsigned +Set::count() const +{ + unsigned count = 0; + for (unsigned i = 0; i < m_rows; i++) { + if (m_row[i] != 0) { + Row& row = *m_row[i]; + if (row.m_exist) + count++; + } + } + return count; +} + bool Set::exist(unsigned i) const { assert(i < m_rows); - return m_row[i] != 0 && m_row[i]->m_exist; + if (m_row[i] == 0) // not allocated => not exist + return false; + return m_row[i]->m_exist; +} + +Row::Op +Set::pending(unsigned i) const +{ + assert(i < m_rows); + if (m_row[i] == 0) // not allocated => not pending + return Row::NoOp; + return m_row[i]->m_pending; } void @@ -1448,9 +1630,9 @@ Set::calc(Par par, unsigned i) int Set::insrow(Par par, unsigned i) { - assert(m_row[i] != 0 && m_count < m_rows); - CHK(m_row[i]->insrow(par) == 0); - m_count++; + assert(m_row[i] != 0); + Row& row = *m_row[i]; + CHK(row.insrow(par) == 0); return 0; } @@ -1458,16 +1640,17 @@ int Set::updrow(Par par, unsigned i) { assert(m_row[i] != 0); - CHK(m_row[i]->updrow(par) == 0); + Row& row = *m_row[i]; + CHK(row.updrow(par) == 0); return 0; } int Set::delrow(Par par, unsigned i) { - assert(m_row[i] != 0 && m_count != 0); - CHK(m_row[i]->delrow(par) == 0); - m_count--; + assert(m_row[i] != 0); + Row& row = *m_row[i]; + CHK(row.delrow(par) == 0); return 0; } @@ -1507,7 +1690,7 @@ Set::getkey(Par par, unsigned* i) assert(m_rec[0] != 0); const char* aRef0 = m_rec[0]->aRef(); Uint32 key = *(const Uint32*)aRef0; - CHKMSG(key < m_rows, "key=" << key << " rows=" << m_rows); + CHK(key < m_rows); *i = key; return 0; } @@ -1532,19 +1715,37 @@ Set::putval(unsigned i, bool force) val.copy(aRef); val.m_null = false; } - if (! row.m_exist) { + if (! row.m_exist) row.m_exist = true; - m_count++; - } return 0; } +void +Set::notpending(unsigned i) +{ + assert(m_row[i] != 0); + Row& row = *m_row[i]; + if (row.m_pending == Row::InsOp) + row.m_exist = true; + if (row.m_pending == Row::DelOp) + row.m_exist = false; + row.m_pending = Row::NoOp; +} + +void +Set::notpending(const Lst& lst) +{ + for (unsigned j = 0; j < lst.m_cnt; j++) { + unsigned i = lst.m_arr[j]; + notpending(i); + } +} + int Set::verify(const Set& set2) const { const Tab& tab = m_tab; assert(&tab == &set2.m_tab && m_rows == set2.m_rows); - CHKMSG(m_count == set2.m_count, "set=" << m_count << " set2=" << set2.m_count); for (unsigned i = 0; i < m_rows; i++) { CHK(exist(i) == set2.exist(i)); if (! exist(i)) @@ -1618,8 +1819,8 @@ int BVal::setbnd(Par par) const { Con& con = par.con(); - const char* addr = (const char*)dataaddr(); - assert(! m_null); + assert(g_compare_null || ! m_null); + const char* addr = ! m_null ? (const char*)dataaddr() : 0; const ICol& icol = m_icol; CHK(con.setBound(icol.m_num, m_type, addr) == 0); return 0; @@ -1647,7 +1848,10 @@ struct BSet { unsigned m_bvals; BVal** m_bval; BSet(const Tab& tab, const ITab& itab, unsigned rows); + ~BSet(); + void reset(); void calc(Par par); + void calcpk(Par par, unsigned i); int setbnd(Par par) const; void filter(const Set& set, Set& set2) const; }; @@ -1659,12 +1863,31 @@ BSet::BSet(const Tab& tab, const ITab& itab, unsigned rows) : m_bvals(0) { m_bval = new BVal* [m_alloc]; + for (unsigned i = 0; i < m_alloc; i++) { + m_bval[i] = 0; + } +} + +BSet::~BSet() +{ + delete [] m_bval; +} + +void +BSet::reset() +{ + while (m_bvals > 0) { + unsigned i = --m_bvals; + delete m_bval[i]; + m_bval[i] = 0; + } } void BSet::calc(Par par) { const ITab& itab = m_itab; + reset(); for (unsigned k = 0; k < itab.m_icols; k++) { const ICol& icol = itab.m_icol[k]; const Col& col = icol.m_col; @@ -1686,7 +1909,8 @@ BSet::calc(Par par) if (k + 1 < itab.m_icols) bval.m_type = 4; // value generation parammeters - par.m_pctnull = 0; + if (! g_compare_null) + par.m_pctnull = 0; par.m_pctrange = 50; // bit higher do { bval.calc(par, 0); @@ -1705,6 +1929,23 @@ BSet::calc(Par par) } } +void +BSet::calcpk(Par par, unsigned i) +{ + const ITab& itab = m_itab; + reset(); + for (unsigned k = 0; k < itab.m_icols; k++) { + const ICol& icol = itab.m_icol[k]; + const Col& col = icol.m_col; + assert(col.m_pk); + assert(m_bvals < m_alloc); + BVal& bval = *new BVal(icol); + m_bval[m_bvals++] = &bval; + bval.m_type = 4; + bval.calc(par, i); + } +} + int BSet::setbnd(Par par) const { @@ -1721,23 +1962,25 @@ BSet::filter(const Set& set, Set& set2) const const Tab& tab = m_tab; const ITab& itab = m_itab; assert(&tab == &set2.m_tab && set.m_rows == set2.m_rows); - assert(set2.m_count == 0); + assert(set2.count() == 0); for (unsigned i = 0; i < set.m_rows; i++) { if (! set.exist(i)) continue; const Row& row = *set.m_row[i]; - bool ok1 = false; - for (unsigned k = 0; k < itab.m_icols; k++) { - const ICol& icol = itab.m_icol[k]; - const Col& col = icol.m_col; - const Val& val = *row.m_val[col.m_num]; - if (! val.m_null) { - ok1 = true; - break; + if (! g_store_null_key) { + bool ok1 = false; + for (unsigned k = 0; k < itab.m_icols; k++) { + const ICol& icol = itab.m_icol[k]; + const Col& col = icol.m_col; + const Val& val = *row.m_val[col.m_num]; + if (! val.m_null) { + ok1 = true; + break; + } } + if (! ok1) + continue; } - if (! ok1) - continue; bool ok2 = true; for (unsigned j = 0; j < m_bvals; j++) { const BVal& bval = *m_bval[j]; @@ -1769,7 +2012,6 @@ BSet::filter(const Set& set, Set& set2) const assert(! row2.m_exist); row2.copy(row); row2.m_exist = true; - set2.m_count++; } } @@ -1794,28 +2036,46 @@ pkinsert(Par par) Set& set = par.set(); LL3("pkinsert"); CHK(con.startTransaction() == 0); - unsigned n = 0; + Lst lst; for (unsigned j = 0; j < par.m_rows; j++) { unsigned i = thrrow(par, j); set.lock(); - if (set.exist(i)) { + if (set.exist(i) || set.pending(i)) { set.unlock(); continue; } set.calc(par, i); - LL4("pkinsert " << i << ": " << *set.m_row[i]); - CHKTRY(set.insrow(par, i) == 0, set.unlock()); + CHK(set.insrow(par, i) == 0); set.unlock(); - if (++n == par.m_batch) { - CHK(con.execute(Commit) == 0); + LL4("pkinsert " << i << ": " << *set.m_row[i]); + lst.push(i); + if (lst.cnt() == par.m_batch) { + bool deadlock = par.m_deadlock; + CHK(con.execute(Commit, deadlock) == 0); con.closeTransaction(); + if (deadlock) { + LL1("pkinsert: stop on deadlock"); + return 0; + } + set.lock(); + set.notpending(lst); + set.unlock(); + lst.reset(); CHK(con.startTransaction() == 0); - n = 0; } } - if (n != 0) { - CHK(con.execute(Commit) == 0); - n = 0; + if (lst.cnt() != 0) { + bool deadlock = par.m_deadlock; + CHK(con.execute(Commit, deadlock) == 0); + con.closeTransaction(); + if (deadlock) { + LL1("pkinsert: stop on deadlock"); + return 0; + } + set.lock(); + set.notpending(lst); + set.unlock(); + return 0; } con.closeTransaction(); return 0; @@ -1828,28 +2088,45 @@ pkupdate(Par par) Set& set = par.set(); LL3("pkupdate"); CHK(con.startTransaction() == 0); - unsigned n = 0; + Lst lst; + bool deadlock = false; for (unsigned j = 0; j < par.m_rows; j++) { unsigned i = thrrow(par, j); set.lock(); - if (! set.exist(i)) { + if (! set.exist(i) || set.pending(i)) { set.unlock(); continue; } set.calc(par, i); - LL4("pkupdate " << i << ": " << *set.m_row[i]); - CHKTRY(set.updrow(par, i) == 0, set.unlock()); + CHK(set.updrow(par, i) == 0); set.unlock(); - if (++n == par.m_batch) { - CHK(con.execute(Commit) == 0); + LL4("pkupdate " << i << ": " << *set.m_row[i]); + lst.push(i); + if (lst.cnt() == par.m_batch) { + deadlock = par.m_deadlock; + CHK(con.execute(Commit, deadlock) == 0); + if (deadlock) { + LL1("pkupdate: stop on deadlock"); + break; + } con.closeTransaction(); + set.lock(); + set.notpending(lst); + set.unlock(); + lst.reset(); CHK(con.startTransaction() == 0); - n = 0; } } - if (n != 0) { - CHK(con.execute(Commit) == 0); - n = 0; + if (! deadlock && lst.cnt() != 0) { + deadlock = par.m_deadlock; + CHK(con.execute(Commit, deadlock) == 0); + if (deadlock) { + LL1("pkupdate: stop on deadlock"); + } else { + set.lock(); + set.notpending(lst); + set.unlock(); + } } con.closeTransaction(); return 0; @@ -1862,27 +2139,44 @@ pkdelete(Par par) Set& set = par.set(); LL3("pkdelete"); CHK(con.startTransaction() == 0); - unsigned n = 0; + Lst lst; + bool deadlock = false; for (unsigned j = 0; j < par.m_rows; j++) { unsigned i = thrrow(par, j); set.lock(); - if (! set.exist(i)) { + if (! set.exist(i) || set.pending(i)) { set.unlock(); continue; } - LL4("pkdelete " << i << ": " << *set.m_row[i]); - CHKTRY(set.delrow(par, i) == 0, set.unlock()); + CHK(set.delrow(par, i) == 0); set.unlock(); - if (++n == par.m_batch) { - CHK(con.execute(Commit) == 0); + LL4("pkdelete " << i << ": " << *set.m_row[i]); + lst.push(i); + if (lst.cnt() == par.m_batch) { + deadlock = par.m_deadlock; + CHK(con.execute(Commit, deadlock) == 0); + if (deadlock) { + LL1("pkdelete: stop on deadlock"); + break; + } con.closeTransaction(); + set.lock(); + set.notpending(lst); + set.unlock(); + lst.reset(); CHK(con.startTransaction() == 0); - n = 0; } } - if (n != 0) { - CHK(con.execute(Commit) == 0); - n = 0; + if (! deadlock && lst.cnt() != 0) { + deadlock = par.m_deadlock; + CHK(con.execute(Commit, deadlock) == 0); + if (deadlock) { + LL1("pkdelete: stop on deadlock"); + } else { + set.lock(); + set.notpending(lst); + set.unlock(); + } } con.closeTransaction(); return 0; @@ -1893,21 +2187,25 @@ pkread(Par par) { Con& con = par.con(); const Tab& tab = par.tab(); - const Set& set = par.set(); + Set& set = par.set(); LL3((par.m_verify ? "pkverify " : "pkread ") << tab.m_name); // expected const Set& set1 = set; Set set2(tab, set.m_rows); for (unsigned i = 0; i < set.m_rows; i++) { - if (! set.exist(i)) + set.lock(); + if (! set.exist(i) || set.pending(i)) { + set.unlock(); continue; + } + set.unlock(); CHK(con.startTransaction() == 0); CHK(set2.selrow(par, i) == 0); CHK(con.execute(Commit) == 0); unsigned i2 = (unsigned)-1; CHK(set2.getkey(par, &i2) == 0 && i == i2); CHK(set2.putval(i, false) == 0); - LL4("row " << set2.m_count << ": " << *set2.m_row[i]); + LL4("row " << set2.count() << ": " << *set2.m_row[i]); con.closeTransaction(); } if (par.m_verify) @@ -1915,6 +2213,32 @@ pkread(Par par) return 0; } +static int +pkreadfast(Par par, unsigned count) +{ + Con& con = par.con(); + const Tab& tab = par.tab(); + const Set& set = par.set(); + LL3("pkfast " << tab.m_name); + Row keyrow(tab); + // not batched on purpose + for (unsigned j = 0; j < count; j++) { + unsigned i = urandom(set.m_rows); + assert(set.exist(i)); + CHK(con.startTransaction() == 0); + // define key + keyrow.calc(par, i); + CHK(keyrow.selrow(par) == 0); + NdbRecAttr* rec; + CHK(con.getValue((Uint32)0, rec) == 0); + CHK(con.executeScan() == 0); + // get 1st column + CHK(con.execute(Commit) == 0); + con.closeTransaction(); + } + return 0; +} + // scan read static int @@ -1928,19 +2252,19 @@ scanreadtable(Par par) LL3((par.m_verify ? "scanverify " : "scanread ") << tab.m_name); Set set2(tab, set.m_rows); CHK(con.startTransaction() == 0); - CHK(con.getNdbOperation(tab) == 0); + CHK(con.getNdbScanOperation(tab) == 0); CHK(con.openScanRead(par.m_scanrd) == 0); set2.getval(par); CHK(con.executeScan() == 0); while (1) { int ret; - CHK((ret = con.nextScanResult()) == 0 || ret == 1); + CHK((ret = con.nextScanResult(true)) == 0 || ret == 1); if (ret == 1) break; unsigned i = (unsigned)-1; CHK(set2.getkey(par, &i) == 0); CHK(set2.putval(i, false) == 0); - LL4("row " << set2.m_count << ": " << *set2.m_row[i]); + LL4("row " << set2.count() << ": " << *set2.m_row[i]); } con.closeTransaction(); if (par.m_verify) @@ -1949,6 +2273,33 @@ scanreadtable(Par par) } static int +scanreadtablefast(Par par, unsigned countcheck) +{ + Con& con = par.con(); + const Tab& tab = par.tab(); + const Set& set = par.set(); + LL3("scanfast " << tab.m_name); + CHK(con.startTransaction() == 0); + CHK(con.getNdbScanOperation(tab) == 0); + CHK(con.openScanRead(par.m_scanrd) == 0); + // get 1st column + NdbRecAttr* rec; + CHK(con.getValue((Uint32)0, rec) == 0); + CHK(con.executeScan() == 0); + unsigned count = 0; + while (1) { + int ret; + CHK((ret = con.nextScanResult(true)) == 0 || ret == 1); + if (ret == 1) + break; + count++; + } + con.closeTransaction(); + CHK(count == countcheck); + return 0; +} + +static int scanreadindex(Par par, const ITab& itab, const BSet& bset) { Con& con = par.con(); @@ -1961,21 +2312,21 @@ scanreadindex(Par par, const ITab& itab, const BSet& bset) LL4(bset); Set set2(tab, set.m_rows); CHK(con.startTransaction() == 0); - CHK(con.getNdbOperation(itab, tab) == 0); + CHK(con.getNdbScanOperation(itab, tab) == 0); CHK(con.openScanRead(par.m_scanrd) == 0); CHK(bset.setbnd(par) == 0); set2.getval(par); CHK(con.executeScan() == 0); while (1) { int ret; - CHK((ret = con.nextScanResult()) == 0 || ret == 1); + CHK((ret = con.nextScanResult(true)) == 0 || ret == 1); if (ret == 1) break; unsigned i = (unsigned)-1; CHK(set2.getkey(par, &i) == 0); LL4("key " << i); CHK(set2.putval(i, par.m_dups) == 0); - LL4("row " << set2.m_count << ": " << *set2.m_row[i]); + LL4("row " << set2.count() << ": " << *set2.m_row[i]); } con.closeTransaction(); if (par.m_verify) @@ -1984,10 +2335,39 @@ scanreadindex(Par par, const ITab& itab, const BSet& bset) } static int +scanreadindexfast(Par par, const ITab& itab, const BSet& bset, unsigned countcheck) +{ + Con& con = par.con(); + const Tab& tab = par.tab(); + const Set& set = par.set(); + LL3("scanfast " << itab.m_name << " bounds=" << bset.m_bvals); + LL4(bset); + CHK(con.startTransaction() == 0); + CHK(con.getNdbScanOperation(itab, tab) == 0); + CHK(con.openScanRead(par.m_scanrd) == 0); + CHK(bset.setbnd(par) == 0); + // get 1st column + NdbRecAttr* rec; + CHK(con.getValue((Uint32)0, rec) == 0); + CHK(con.executeScan() == 0); + unsigned count = 0; + while (1) { + int ret; + CHK((ret = con.nextScanResult(true)) == 0 || ret == 1); + if (ret == 1) + break; + count++; + } + con.closeTransaction(); + CHK(count == countcheck); + return 0; +} + +static int scanreadindex(Par par, const ITab& itab) { const Tab& tab = par.tab(); - for (unsigned i = 0; i < par.m_subloop; i++) { + for (unsigned i = 0; i < par.m_idxloop; i++) { BSet bset(tab, itab, par.m_rows); bset.calc(par); CHK(scanreadindex(par, itab, bset) == 0); @@ -2017,6 +2397,60 @@ scanreadall(Par par) return 0; } +// timing scans + +static int +timescantable(Par par) +{ + par.tmr().on(); + CHK(scanreadtablefast(par, par.m_totrows) == 0); + par.tmr().off(par.set().m_rows); + return 0; +} + +static int +timescanpkindex(Par par) +{ + const Tab& tab = par.tab(); + const ITab& itab = tab.m_itab[0]; // 1st index is on PK + BSet bset(tab, itab, par.m_rows); + par.tmr().on(); + CHK(scanreadindexfast(par, itab, bset, par.m_totrows) == 0); + par.tmr().off(par.set().m_rows); + return 0; +} + +static int +timepkreadtable(Par par) +{ + par.tmr().on(); + unsigned count = par.m_samples; + if (count == 0) + count = par.m_totrows; + CHK(pkreadfast(par, count) == 0); + par.tmr().off(count); + return 0; +} + +static int +timepkreadindex(Par par) +{ + const Tab& tab = par.tab(); + const ITab& itab = tab.m_itab[0]; // 1st index is on PK + BSet bset(tab, itab, par.m_rows); + unsigned count = par.m_samples; + if (count == 0) + count = par.m_totrows; + par.tmr().on(); + for (unsigned j = 0; j < count; j++) { + unsigned i = urandom(par.m_totrows); + bset.calcpk(par, i); + CHK(scanreadindexfast(par, itab, bset, 1) == 0); + } + par.tmr().off(count); + return 0; +} + // scan update static int @@ -2028,36 +2462,70 @@ scanupdatetable(Par par) LL3("scan update " << tab.m_name); Set set2(tab, set.m_rows); CHK(con.startTransaction() == 0); - CHK(con.getNdbOperation(tab) == 0); + CHK(con.getNdbScanOperation(tab) == 0); CHK(con.openScanExclusive(par.m_scanex) == 0); set2.getval(par); CHK(con.executeScan() == 0); unsigned count = 0; // updating trans Con con2; - con2.m_ndb = con.m_ndb; - CHK(con2.startBuddyTransaction(con) == 0); + con2.connect(con); + CHK(con2.startTransaction() == 0); + Lst lst; + bool deadlock = false; while (1) { int ret; - CHK((ret = con.nextScanResult()) == 0 || ret == 1); + deadlock = par.m_deadlock; + CHK((ret = con.nextScanResult(true, deadlock)) == 0 || ret == 1); + if (ret == 1) + break; + if (deadlock) { + LL1("scanupdatetable: stop on deadlock"); + break; + } + do { + unsigned i = (unsigned)-1; + CHK(set2.getkey(par, &i) == 0); + const Row& row = *set.m_row[i]; + set.lock(); + if (! set.exist(i) || set.pending(i)) { + LL4("scan update " << tab.m_name << ": skip: " << row); + } else { + CHKTRY(set2.putval(i, false) == 0, set.unlock()); + CHKTRY(con.updateScanTuple(con2) == 0, set.unlock()); + Par par2 = par; + par2.m_con = &con2; + set.calc(par, i); + CHKTRY(set.setrow(par2, i) == 0, set.unlock()); + LL4("scan update " << tab.m_name << ": " << row); + lst.push(i); + } + set.unlock(); + if (lst.cnt() == par.m_batch) { + CHK(con2.execute(Commit) == 0); + con2.closeTransaction(); + set.lock(); + set.notpending(lst); + set.unlock(); + count += lst.cnt(); + lst.reset(); + CHK(con2.startTransaction() == 0); + } + CHK((ret = con.nextScanResult(false)) == 0 || ret == 1 || ret == 2); + if (ret == 2 && lst.cnt() != 0) { + CHK(con2.execute(Commit) == 0); + con2.closeTransaction(); + set.lock(); + set.notpending(lst); + set.unlock(); + count += lst.cnt(); + lst.reset(); + CHK(con2.startTransaction() == 0); + } + } while (ret == 0); if (ret == 1) break; - unsigned i = (unsigned)-1; - CHK(set2.getkey(par, &i) == 0); - LL4("key " << i); - CHK(set2.putval(i, false) == 0); - CHK(con2.takeOverForUpdate(con) == 0); - Par par2 = par; - par2.m_con = &con2; - set.lock(); - set.calc(par, i); - LL4("scan update " << tab.m_name << ": " << *set.m_row[i]); - CHKTRY(set.setrow(par2, i) == 0, set.unlock()); - set.unlock(); - CHK(con2.execute(NoCommit) == 0); - count++; } - CHK(con2.execute(Commit) == 0); con2.closeTransaction(); LL3("scan update " << tab.m_name << " rows updated=" << count); con.closeTransaction(); @@ -2073,7 +2541,7 @@ scanupdateindex(Par par, const ITab& itab, const BSet& bset) LL3("scan update " << itab.m_name); Set set2(tab, set.m_rows); CHK(con.startTransaction() == 0); - CHK(con.getNdbOperation(itab, tab) == 0); + CHK(con.getNdbScanOperation(itab, tab) == 0); CHK(con.openScanExclusive(par.m_scanex) == 0); CHK(bset.setbnd(par) == 0); set2.getval(par); @@ -2081,32 +2549,61 @@ scanupdateindex(Par par, const ITab& itab, const BSet& bset) unsigned count = 0; // updating trans Con con2; - con2.m_ndb = con.m_ndb; - CHK(con2.startBuddyTransaction(con) == 0); + con2.connect(con); + CHK(con2.startTransaction() == 0); + Lst lst; + bool deadlock = false; while (1) { int ret; - CHK((ret = con.nextScanResult()) == 0 || ret == 1); + deadlock = par.m_deadlock; + CHK((ret = con.nextScanResult(true, deadlock)) == 0 || ret == 1); if (ret == 1) break; - unsigned i = (unsigned)-1; - CHK(set2.getkey(par, &i) == 0); - LL4("key " << i); - CHK(set2.putval(i, par.m_dups) == 0); - // avoid deadlock for now - //if (! isthrrow(par, i)) - //continue; - CHK(con2.takeOverForUpdate(con) == 0); - Par par2 = par; - par2.m_con = &con2; - set.lock(); - set.calc(par, i); - LL4("scan update " << itab.m_name << ": " << *set.m_row[i]); - CHKTRY(set.setrow(par2, i) == 0, set.unlock()); - set.unlock(); - CHK(con2.execute(NoCommit) == 0); - count++; + if (deadlock) { + LL1("scanupdateindex: stop on deadlock"); + break; + } + do { + unsigned i = (unsigned)-1; + CHK(set2.getkey(par, &i) == 0); + const Row& row = *set.m_row[i]; + set.lock(); + if (! set.exist(i) || set.pending(i)) { + LL4("scan update " << itab.m_name << ": skip: " << row); + } else { + CHKTRY(set2.putval(i, par.m_dups) == 0, set.unlock()); + CHKTRY(con.updateScanTuple(con2) == 0, set.unlock()); + Par par2 = par; + par2.m_con = &con2; + set.calc(par, i); + CHKTRY(set.setrow(par2, i) == 0, set.unlock()); + LL4("scan update " << itab.m_name << ": " << row); + lst.push(i); + } + set.unlock(); + if (lst.cnt() == par.m_batch) { + CHK(con2.execute(Commit) == 0); + con2.closeTransaction(); + set.lock(); + set.notpending(lst); + set.unlock(); + count += lst.cnt(); + lst.reset(); + CHK(con2.startTransaction() == 0); + } + CHK((ret = con.nextScanResult(false)) == 0 || ret == 1 || ret == 2); + if (ret == 2 && lst.cnt() != 0) { + CHK(con2.execute(Commit) == 0); + con2.closeTransaction(); + set.lock(); + set.notpending(lst); + set.unlock(); + count += lst.cnt(); + lst.reset(); + CHK(con2.startTransaction() == 0); + } + } while (ret == 0); } - CHK(con2.execute(Commit) == 0); con2.closeTransaction(); LL3("scan update " << itab.m_name << " rows updated=" << count); con.closeTransaction(); @@ -2117,7 +2614,7 @@ static int scanupdateindex(Par par, const ITab& itab) { const Tab& tab = par.tab(); - for (unsigned i = 0; i < par.m_subloop; i++) { + for (unsigned i = 0; i < par.m_idxloop; i++) { BSet bset(tab, itab, par.m_rows); bset.calc(par); CHK(scanupdateindex(par, itab, bset) == 0); @@ -2148,41 +2645,15 @@ scanupdateall(Par par) // medium level routines -static bool -ignoreverifyerror(Par par) -{ - Con& con = par.con(); - bool b = par.m_threads > 1; - if (b) { - LL1("ignore verify error"); - if (con.m_tx != 0) - con.closeTransaction(); - return true; - } - return b; -} - static int readverify(Par par) { par.m_verify = true; - CHK(pkread(par) == 0 || ignoreverifyerror(par)); - CHK(scanreadall(par) == 0 || ignoreverifyerror(par)); + CHK(pkread(par) == 0); + CHK(scanreadall(par) == 0); return 0; } -static bool -ignoredeadlock(Par par) -{ - Con& con = par.con(); - if (con.m_errtype == Con::ErrDeadlock) { - LL1("ignore deadlock"); - con.closeTransaction(); - return true; - } - return false; -} - static int pkupdatescanread(Par par) { @@ -2204,15 +2675,16 @@ static int mixedoperations(Par par) { par.m_dups = true; + par.m_deadlock = true; unsigned sel = urandom(10); if (sel < 2) { - CHK(pkdelete(par) == 0 || ignoredeadlock(par)); + CHK(pkdelete(par) == 0); } else if (sel < 4) { - CHK(pkupdate(par) == 0 || ignoredeadlock(par)); + CHK(pkupdate(par) == 0); } else if (sel < 6) { - CHK(scanupdatetable(par) == 0 || ignoredeadlock(par)); + CHK(scanupdatetable(par) == 0); } else { - CHK(scanupdateindex(par) == 0 || ignoredeadlock(par)); + CHK(scanupdateindex(par) == 0); } return 0; } @@ -2346,7 +2818,6 @@ Thr::run() break; } LL4("start"); - CHK(con.bugger() == 0); assert(m_state == Start); m_ret = (*m_func)(m_par); m_state = Stopped; @@ -2426,6 +2897,7 @@ runstep(Par par, const char* fname, TFunc func, unsigned mode) Thr& thr = *g_thrlist[n]; thr.m_par.m_tab = par.m_tab; thr.m_par.m_set = par.m_set; + thr.m_par.m_tmr = par.m_tmr; thr.m_func = func; thr.start(); } @@ -2476,13 +2948,13 @@ tpkops(Par par) RUNSTEP(par, pkinsert, MT); RUNSTEP(par, createindex, ST); RUNSTEP(par, invalidateindex, MT); - RUNSTEP(par, readverify, MT); + RUNSTEP(par, readverify, ST); for (unsigned i = 0; i < par.m_subloop; i++) { RUNSTEP(par, pkupdatescanread, MT); - RUNSTEP(par, readverify, MT); + RUNSTEP(par, readverify, ST); } RUNSTEP(par, pkdelete, MT); - RUNSTEP(par, readverify, MT); + RUNSTEP(par, readverify, ST); return 0; } @@ -2495,10 +2967,10 @@ tmixedops(Par par) RUNSTEP(par, pkinsert, MT); RUNSTEP(par, createindex, ST); RUNSTEP(par, invalidateindex, MT); - RUNSTEP(par, readverify, MT); + RUNSTEP(par, readverify, ST); for (unsigned i = 0; i < par.m_subloop; i++) { RUNSTEP(par, mixedoperations, MT); - RUNSTEP(par, readverify, MT); + RUNSTEP(par, readverify, ST); } return 0; } @@ -2513,7 +2985,7 @@ tbusybuild(Par par) for (unsigned i = 0; i < par.m_subloop; i++) { RUNSTEP(par, pkupdateindexbuild, MT); RUNSTEP(par, invalidateindex, MT); - RUNSTEP(par, readverify, MT); + RUNSTEP(par, readverify, ST); RUNSTEP(par, dropindex, ST); } return 0; @@ -2564,6 +3036,50 @@ ttimemaint(Par par) } static int +ttimescan(Par par) +{ + Tmr t1, t2; + RUNSTEP(par, droptable, ST); + RUNSTEP(par, createtable, ST); + RUNSTEP(par, invalidatetable, MT); + for (unsigned i = 0; i < par.m_subloop; i++) { + RUNSTEP(par, pkinsert, MT); + RUNSTEP(par, createindex, ST); + par.m_tmr = &t1; + RUNSTEP(par, timescantable, ST); + par.m_tmr = &t2; + RUNSTEP(par, timescanpkindex, ST); + RUNSTEP(par, dropindex, ST); + } + LL1("full scan table - " << t1.time()); + LL1("full scan PK index - " << t2.time()); + LL1("overhead - " << t2.over(t1)); + return 0; +} + +static int +ttimepkread(Par par) +{ + Tmr t1, t2; + RUNSTEP(par, droptable, ST); + RUNSTEP(par, createtable, ST); + RUNSTEP(par, invalidatetable, MT); + for (unsigned i = 0; i < par.m_subloop; i++) { + RUNSTEP(par, pkinsert, MT); + RUNSTEP(par, createindex, ST); + par.m_tmr = &t1; + RUNSTEP(par, timepkreadtable, ST); + par.m_tmr = &t2; + RUNSTEP(par, timepkreadindex, ST); + RUNSTEP(par, dropindex, ST); + } + LL1("pk read table - " << t1.time()); + LL1("pk read PK index - " << t2.time()); + LL1("overhead - " << t2.over(t1)); + return 0; +} + +static int tdrop(Par par) { RUNSTEP(par, droptable, ST); @@ -2589,6 +3105,8 @@ tcaselist[] = { TCase("d", tbusybuild, "pk operations and index build"), TCase("t", ttimebuild, "time index build"), TCase("u", ttimemaint, "time index maintenance"), + TCase("v", ttimescan, "time full scan table vs index on pk"), + TCase("w", ttimepkread, "time pk read table vs index on pk"), TCase("z", tdrop, "drop test tables") }; @@ -2608,7 +3126,7 @@ printcases() static void printtables() { - ndbout << "tables and indexes:" << endl; + ndbout << "tables and indexes (X1 is on table PK):" << endl; for (unsigned j = 0; j < tabcount; j++) { const Tab& tab = tablist[j]; ndbout << " " << tab.m_name; @@ -2624,7 +3142,8 @@ static int runtest(Par par) { LL1("start"); - srandom(par.m_seed); + if (par.m_seed != 0) + srandom(par.m_seed); Con con; CHK(con.connect() == 0); par.m_con = &con; @@ -2639,6 +3158,8 @@ runtest(Par par) } for (unsigned l = 0; par.m_loop == 0 || l < par.m_loop; l++) { LL1("loop " << l); + if (par.m_seed == 0) + srandom(l); for (unsigned i = 0; i < tcasecount; i++) { const TCase& tcase = tcaselist[i]; if (par.m_case != 0 && strchr(par.m_case, tcase.m_name[0]) == 0) @@ -2649,8 +3170,8 @@ runtest(Par par) continue; const Tab& tab = tablist[j]; par.m_tab = &tab; - Set set(tab, par.m_totrows); - par.m_set = &set; + delete par.m_set; + par.m_set = new Set(tab, par.m_totrows); LL1("table " << tab.m_name); CHK(tcase.m_func(par) == 0); } @@ -2680,6 +3201,12 @@ NDB_COMMAND(testOIBasic, "testOIBasic", "testOIBasic", "testOIBasic", 65535) ndbout << "testOIBasic: unknown argument " << arg; goto usage; } + if (strcmp(arg, "-batch") == 0) { + if (++argv, --argc > 0) { + g_opt.m_batch = atoi(argv[0]); + continue; + } + } if (strcmp(arg, "-case") == 0) { if (++argv, --argc > 0) { g_opt.m_case = strdup(argv[0]); @@ -2736,6 +3263,12 @@ NDB_COMMAND(testOIBasic, "testOIBasic", "testOIBasic", "testOIBasic", 65535) continue; } } + if (strcmp(arg, "-samples") == 0) { + if (++argv, --argc > 0) { + g_opt.m_samples = atoi(argv[0]); + continue; + } + } if (strcmp(arg, "-scanrd") == 0) { if (++argv, --argc > 0) { g_opt.m_scanrd = atoi(argv[0]); diff --git a/ndb/test/ndbapi/testRestartGci.cpp b/ndb/test/ndbapi/testRestartGci.cpp index e3dd1f8e2ce..54d38654ff2 100644 --- a/ndb/test/ndbapi/testRestartGci.cpp +++ b/ndb/test/ndbapi/testRestartGci.cpp @@ -216,3 +216,5 @@ NDBT_TESTSUITE_END(testRestartGci); int main(int argc, const char** argv){ return testRestartGci.execute(argc, argv); } + +template class Vector<SavedRecord>; diff --git a/ndb/test/ndbapi/testScan.cpp b/ndb/test/ndbapi/testScan.cpp index bc3be0b7dc9..3d8b37df0ca 100644 --- a/ndb/test/ndbapi/testScan.cpp +++ b/ndb/test/ndbapi/testScan.cpp @@ -65,7 +65,7 @@ int runDropAllTablesExceptTestTable(NDBT_Context* ctx, NDBT_Step* step){ } int res = GETNDB(step)->getDictionary()->dropTable(tab->getName()); - if(res != -1){ + if(res == -1){ return NDBT_FAILED; } } @@ -776,108 +776,19 @@ int runOnlyOpenScanOnce(NDBT_Context* ctx, NDBT_Step* step){ } int runOnlyOneOpInScanTrans(NDBT_Context* ctx, NDBT_Step* step){ - const NdbDictionary::Table* pTab = ctx->getTab(); - int records = ctx->getNumRecords(); - int numFailed = 0; - - ScanFunctions scanF(*pTab); - if (scanF.scanReadFunctions(GETNDB(step), - records, - 6, - ScanFunctions::OnlyOneOpInScanTrans, - false) == 0){ - numFailed++; - } - if (scanF.scanReadFunctions(GETNDB(step), - records, - 6, - ScanFunctions::OnlyOneOpInScanTrans, - true) == 0){ - numFailed++; - } - - - if(numFailed > 0) - return NDBT_FAILED; - else - return NDBT_OK; - + return NDBT_OK; } int runExecuteScanWithoutOpenScan(NDBT_Context* ctx, NDBT_Step* step){ - const NdbDictionary::Table* pTab = ctx->getTab(); - int records = ctx->getNumRecords(); - int numFailed = 0; - ScanFunctions scanF(*pTab); - if (scanF.scanReadFunctions(GETNDB(step), - records, - 1, - ScanFunctions::ExecuteScanWithOutOpenScan, - false) == 0){ - numFailed++; - } - - if(numFailed > 0) - return NDBT_FAILED; - else - return NDBT_OK; + return NDBT_OK; } - - int runOnlyOneOpBeforeOpenScan(NDBT_Context* ctx, NDBT_Step* step){ - const NdbDictionary::Table* pTab = ctx->getTab(); - int records = ctx->getNumRecords(); - int numFailed = 0; - - ScanFunctions scanF(*pTab); - if (scanF.scanReadFunctions(GETNDB(step), - records, - 6, - ScanFunctions::OnlyOneOpBeforeOpenScan, - false) == 0){ - numFailed++; - } - if (scanF.scanReadFunctions(GETNDB(step), - records, - 6, - ScanFunctions::OnlyOneOpBeforeOpenScan, - true) == 0){ - numFailed++; - } - - if(numFailed > 0) - return NDBT_FAILED; - else return NDBT_OK; - } -int runOnlyOneScanPerTrans(NDBT_Context* ctx, NDBT_Step* step){ - const NdbDictionary::Table* pTab = ctx->getTab(); - int records = ctx->getNumRecords(); - int numFailed = 0; - - ScanFunctions scanF(*pTab); - if (scanF.scanReadFunctions(GETNDB(step), - records, - 6, - ScanFunctions::OnlyOneScanPerTrans, - false) == 0){ - numFailed++; - } - if (scanF.scanReadFunctions(GETNDB(step), - records, - 6, - ScanFunctions::OnlyOneScanPerTrans, - true) == 0){ - numFailed++; - } - - if(numFailed > 0) - return NDBT_FAILED; - else - return NDBT_OK; +int runOnlyOneScanPerTrans(NDBT_Context* ctx, NDBT_Step* step){ + return NDBT_OK; } int runNoCloseTransaction(NDBT_Context* ctx, NDBT_Step* step){ @@ -970,6 +881,93 @@ int runCheckInactivityBeforeClose(NDBT_Context* ctx, NDBT_Step* step){ } +int runScanRestart(NDBT_Context* ctx, NDBT_Step* step){ + int loops = ctx->getNumLoops(); + int records = ctx->getNumRecords(); + Ndb * pNdb = GETNDB(step); + const NdbDictionary::Table* pTab = ctx->getTab(); + + HugoCalculator calc(* pTab); + NDBT_ResultRow tmpRow(* pTab); + + int i = 0; + while (i<loops && !ctx->isTestStopped()) { + g_info << i++ << ": "; + const int record = (rand() % records); + g_info << " row=" << record; + + NdbConnection* pCon = pNdb->startTransaction(); + NdbScanOperation* pOp = pCon->getNdbScanOperation(pTab->getName()); + if (pOp == NULL) { + ERR(pCon->getNdbError()); + return NDBT_FAILED; + } + + NdbResultSet* rs = pOp->readTuples(); + if( rs == 0 ) { + ERR(pCon->getNdbError()); + return NDBT_FAILED; + } + + int check = pOp->interpret_exit_ok(); + if( check == -1 ) { + ERR(pCon->getNdbError()); + return NDBT_FAILED; + } + + // Define attributes to read + for(int a = 0; a<pTab->getNoOfColumns(); a++){ + if((tmpRow.attributeStore(a) = + pOp->getValue(pTab->getColumn(a)->getName())) == 0) { + ERR(pCon->getNdbError()); + return NDBT_FAILED; + } + } + + check = pCon->execute(NoCommit); + if( check == -1 ) { + ERR(pCon->getNdbError()); + return NDBT_FAILED; + } + + int res; + int row = 0; + while(row < record && (res = rs->nextResult()) == 0) { + if(calc.verifyRowValues(&tmpRow) != 0){ + abort(); + return NDBT_FAILED; + } + row++; + } + if(row != record){ + ERR(pCon->getNdbError()); + abort(); + return NDBT_FAILED; + } + g_info << " restarting" << endl; + if((res = rs->restart()) != 0){ + ERR(pCon->getNdbError()); + abort(); + return NDBT_FAILED; + } + + row = 0; + while((res = rs->nextResult()) == 0) { + if(calc.verifyRowValues(&tmpRow) != 0){ + abort(); + return NDBT_FAILED; + } + row++; + } + if(res != 1 || row != records){ + ERR(pCon->getNdbError()); + abort(); + return NDBT_FAILED; + } + pCon->close(); + } + return NDBT_OK; +} NDBT_TESTSUITE(testScan); @@ -1393,6 +1391,12 @@ TESTCASE("ScanReadWhileNodeIsDown", STEP(runStopAndStartNode); FINALIZER(runClearTable); } +TESTCASE("ScanRestart", + "Verify restart functionallity"){ + INITIALIZER(runLoadTable); + STEP(runScanRestart); + FINALIZER(runClearTable); +} NDBT_TESTSUITE_END(testScan); int main(int argc, const char** argv){ @@ -1400,3 +1404,4 @@ int main(int argc, const char** argv){ return testScan.execute(argc, argv); } +template class Vector<Attrib*>; diff --git a/ndb/test/ndbapi/testScanPerf/testScanPerf.cpp b/ndb/test/ndbapi/testScanPerf.cpp index 61af1ffb989..61af1ffb989 100644 --- a/ndb/test/ndbapi/testScanPerf/testScanPerf.cpp +++ b/ndb/test/ndbapi/testScanPerf.cpp diff --git a/ndb/test/ndbapi/testScanPerf/Makefile b/ndb/test/ndbapi/testScanPerf/Makefile deleted file mode 100644 index fdf5980b385..00000000000 --- a/ndb/test/ndbapi/testScanPerf/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -include .defs.mk - -TYPE = ndbapitest - -BIN_TARGET = testScanPerf - -SOURCES = testScanPerf.cpp - -include $(NDB_TOP)/Epilogue.mk diff --git a/ndb/test/ndbapi/testTimeout.cpp b/ndb/test/ndbapi/testTimeout.cpp index 8a7866880b3..62e69125073 100644 --- a/ndb/test/ndbapi/testTimeout.cpp +++ b/ndb/test/ndbapi/testTimeout.cpp @@ -20,6 +20,44 @@ #include <UtilTransactions.hpp> #include <random.h> #include <NdbConfig.hpp> +#include <signaldata/DumpStateOrd.hpp> + +#define TIMEOUT 3000 + +Uint32 g_org_timeout = 3000; + +int +setTransactionTimeout(NDBT_Context* ctx, NDBT_Step* step){ + NdbRestarter restarter; + + NdbConfig conf(GETNDB(step)->getNodeId()+1); + unsigned int nodeId = conf.getMasterNodeId(); + if (!conf.getProperty(nodeId, + NODE_TYPE_DB, + CFG_DB_TRANSACTION_INACTIVE_TIMEOUT, + &g_org_timeout)){ + return NDBT_FAILED; + } + + int val[] = { DumpStateOrd::TcSetApplTransactionTimeout, TIMEOUT }; + if(restarter.dumpStateAllNodes(val, 2) != 0){ + return NDBT_FAILED; + } + + return NDBT_OK; +} + +int +resetTransactionTimeout(NDBT_Context* ctx, NDBT_Step* step){ + NdbRestarter restarter; + + int val[] = { DumpStateOrd::TcSetApplTransactionTimeout, g_org_timeout }; + if(restarter.dumpStateAllNodes(val, 2) != 0){ + return NDBT_FAILED; + } + + return NDBT_OK; +} int runLoadTable(NDBT_Context* ctx, NDBT_Step* step){ @@ -55,16 +93,10 @@ int runTimeoutTrans(NDBT_Context* ctx, NDBT_Step* step){ NdbConfig conf(GETNDB(step)->getNodeId()+1); unsigned int nodeId = conf.getMasterNodeId(); int stepNo = step->getStepNo(); - Uint32 timeoutVal; - if (!conf.getProperty(nodeId, - NODE_TYPE_DB, - CFG_DB_TRANSACTION_INACTIVE_TIMEOUT, - &timeoutVal)){ - return NDBT_FAILED; - } - int minSleep = (int)(timeoutVal * 1.5); - int maxSleep = timeoutVal * 2; - ndbout << "TransactionInactiveTimeout="<<timeoutVal + + int minSleep = (int)(TIMEOUT * 1.5); + int maxSleep = TIMEOUT * 2; + ndbout << "TransactionInactiveTimeout="<< TIMEOUT << ", minSleep="<<minSleep << ", maxSleep="<<maxSleep<<endl; @@ -89,7 +121,125 @@ int runTimeoutTrans(NDBT_Context* ctx, NDBT_Step* step){ } while(false); hugoOps.closeTransaction(pNdb); + } + + return result; +} + +int runTimeoutTrans2(NDBT_Context* ctx, NDBT_Step* step){ + int result = NDBT_OK; + int loops = ctx->getNumLoops(); + int stepNo = step->getStepNo(); + int mul1 = ctx->getProperty("Op1", (Uint32)0); + int mul2 = ctx->getProperty("Op2", (Uint32)0); + int records = ctx->getNumRecords(); + + int minSleep = (int)(TIMEOUT * 1.5); + int maxSleep = TIMEOUT * 2; + HugoOperations hugoOps(*ctx->getTab()); + Ndb* pNdb = GETNDB(step); + + for (int l = 0; l<loops && !ctx->isTestStopped() && result == NDBT_OK; l++){ + + int op1 = 0 + (l + stepNo) * mul1; + int op2 = 0 + (l + stepNo) * mul2; + + op1 = (op1 % 5); + op2 = (op2 % 5); + + ndbout << stepNo << ": TransactionInactiveTimeout="<< TIMEOUT + << ", minSleep="<<minSleep + << ", maxSleep="<<maxSleep + << ", op1=" << op1 + << ", op2=" << op2 << endl;; + + do{ + // Commit transaction + CHECK(hugoOps.startTransaction(pNdb) == 0); + + switch(op1){ + case 0: + break; + case 1: + if(hugoOps.pkReadRecord(pNdb, stepNo, true) != 0){ + g_err << stepNo << ": Fail" << __LINE__ << endl; + result = NDBT_FAILED; break; + } + break; + case 2: + if(hugoOps.pkUpdateRecord(pNdb, stepNo, true) != 0){ + g_err << stepNo << ": Fail" << __LINE__ << endl; + result = NDBT_FAILED; break; + } + break; + case 3: + if(hugoOps.pkDeleteRecord(pNdb, stepNo, true) != 0){ + g_err << stepNo << ": Fail" << __LINE__ << endl; + result = NDBT_FAILED; break; + } + break; + case 4: + if(hugoOps.pkInsertRecord(pNdb, stepNo+records+l, true) != 0){ + g_err << stepNo << ": Fail" << __LINE__ << endl; + result = NDBT_FAILED; break; + } + break; + } + + if(result != NDBT_OK) + break; + + int res = hugoOps.execute_NoCommit(pNdb); + if(res != 0){ + g_err << stepNo << ": Fail" << __LINE__ << endl; + result = NDBT_FAILED; break; + } + + int sleep = minSleep + myRandom48(maxSleep-minSleep); + ndbout << stepNo << ": Sleeping for "<< sleep << " milliseconds" << endl; + NdbSleep_MilliSleep(sleep); + + switch(op2){ + case 0: + break; + case 1: + if(hugoOps.pkReadRecord(pNdb, stepNo, true) != 0){ + g_err << stepNo << ": Fail" << __LINE__ << endl; + result = NDBT_FAILED; break; + } + break; + case 2: + if(hugoOps.pkUpdateRecord(pNdb, stepNo, true) != 0){ + g_err << stepNo << ": Fail" << __LINE__ << endl; + result = NDBT_FAILED; break; + } + break; + case 3: + if(hugoOps.pkDeleteRecord(pNdb, stepNo, true) != 0){ + g_err << stepNo << ": Fail" << __LINE__ << endl; + result = NDBT_FAILED; break; + } + break; + case 4: + if(hugoOps.pkInsertRecord(pNdb, stepNo+2*records+l, true) != 0){ + g_err << stepNo << ": Fail" << __LINE__ << endl; + result = NDBT_FAILED; break; + } + break; + } + + // Expect that transaction has timed-out + res = hugoOps.execute_Commit(pNdb); + if(op1 != 0 && res != 266){ + g_err << stepNo << ": Fail: " << res << "!= 237, op1=" + << op1 << ", op2=" << op2 << endl; + result = NDBT_FAILED; break; + } + + } while(false); + + hugoOps.closeTransaction(pNdb); } return result; @@ -98,18 +248,10 @@ int runTimeoutTrans(NDBT_Context* ctx, NDBT_Step* step){ int runDontTimeoutTrans(NDBT_Context* ctx, NDBT_Step* step){ int result = NDBT_OK; int loops = ctx->getNumLoops(); - NdbConfig conf(GETNDB(step)->getNodeId()+1); - unsigned int nodeId = conf.getMasterNodeId(); int stepNo = step->getStepNo(); - Uint32 timeoutVal; - if (!conf.getProperty(nodeId, - NODE_TYPE_DB, - CFG_DB_TRANSACTION_INACTIVE_TIMEOUT, - &timeoutVal)){ - return NDBT_FAILED; - } - int maxSleep = (int)(timeoutVal * 0.5); - ndbout << "TransactionInactiveTimeout="<<timeoutVal + + int maxSleep = (int)(TIMEOUT * 0.5); + ndbout << "TransactionInactiveTimeout="<< TIMEOUT << ", maxSleep="<<maxSleep<<endl; @@ -134,11 +276,8 @@ int runDontTimeoutTrans(NDBT_Context* ctx, NDBT_Step* step){ } while(false); hugoOps.closeTransaction(pNdb); - - } - return result; } @@ -146,18 +285,9 @@ int runBuddyTransNoTimeout(NDBT_Context* ctx, NDBT_Step* step){ int result = NDBT_OK; int loops = ctx->getNumLoops(); int records = ctx->getNumRecords(); - NdbConfig conf(GETNDB(step)->getNodeId()+1); - unsigned int nodeId = conf.getMasterNodeId(); int stepNo = step->getStepNo(); - Uint32 timeoutVal; - if (!conf.getProperty(nodeId, - NODE_TYPE_DB, - CFG_DB_TRANSACTION_INACTIVE_TIMEOUT, - &timeoutVal)){ - return NDBT_FAILED; - } - int maxSleep = (int)(timeoutVal * 0.3); - ndbout << "TransactionInactiveTimeout="<<timeoutVal + int maxSleep = (int)(TIMEOUT * 0.3); + ndbout << "TransactionInactiveTimeout="<< TIMEOUT << ", maxSleep="<<maxSleep<<endl; HugoOperations hugoOps(*ctx->getTab()); @@ -172,11 +302,11 @@ int runBuddyTransNoTimeout(NDBT_Context* ctx, NDBT_Step* step){ CHECK(hugoOps.pkInsertRecord(pNdb, recordNo, true) == 0); CHECK(hugoOps.execute_NoCommit(pNdb) == 0); - for (int i = 0; i < 10; i++){ + for (int i = 0; i < 3; i++){ // Perform buddy scan reads - CHECK(hugoOps.scanReadRecords(pNdb) == 0); - CHECK(hugoOps.executeScanRead(pNdb) == 0); - + CHECK((hugoOps.scanReadRecords(pNdb)) == 0); + CHECK(hugoOps.execute_NoCommit(pNdb) == 0); + int sleep = myRandom48(maxSleep); ndbout << "Sleeping for " << sleep << " milliseconds" << endl; NdbSleep_MilliSleep(sleep); @@ -188,10 +318,7 @@ int runBuddyTransNoTimeout(NDBT_Context* ctx, NDBT_Step* step){ } while(false); hugoOps.closeTransaction(pNdb); - - } - return result; } @@ -202,7 +329,9 @@ TESTCASE("DontTimeoutTransaction", "if we sleep during the transaction. Use a sleep "\ "value which is smaller than TransactionInactiveTimeout"){ INITIALIZER(runLoadTable); + INITIALIZER(setTransactionTimeout); STEPS(runDontTimeoutTrans, 1); + FINALIZER(resetTransactionTimeout); FINALIZER(runClearTable); } TESTCASE("DontTimeoutTransaction5", @@ -211,7 +340,9 @@ TESTCASE("DontTimeoutTransaction5", "value which is smaller than TransactionInactiveTimeout" \ "Five simultaneous threads"){ INITIALIZER(runLoadTable); + INITIALIZER(setTransactionTimeout); STEPS(runDontTimeoutTrans, 5); + FINALIZER(resetTransactionTimeout); FINALIZER(runClearTable); } TESTCASE("TimeoutTransaction", @@ -219,7 +350,9 @@ TESTCASE("TimeoutTransaction", "if we sleep during the transaction. Use a sleep "\ "value which is larger than TransactionInactiveTimeout"){ INITIALIZER(runLoadTable); + INITIALIZER(setTransactionTimeout); STEPS(runTimeoutTrans, 1); + FINALIZER(resetTransactionTimeout); FINALIZER(runClearTable); } TESTCASE("TimeoutTransaction5", @@ -228,7 +361,21 @@ TESTCASE("TimeoutTransaction5", "value which is larger than TransactionInactiveTimeout" \ "Five simultaneous threads"){ INITIALIZER(runLoadTable); + INITIALIZER(setTransactionTimeout); STEPS(runTimeoutTrans, 5); + FINALIZER(resetTransactionTimeout); + FINALIZER(runClearTable); +} +TESTCASE("TimeoutRandTransaction", + "Test that the transaction does timeout "\ + "if we sleep during the transaction. Use a sleep "\ + "value which is larger than TransactionInactiveTimeout"){ + INITIALIZER(runLoadTable); + INITIALIZER(setTransactionTimeout); + TC_PROPERTY("Op1", 7); + TC_PROPERTY("Op2", 11); + STEPS(runTimeoutTrans2, 5); + FINALIZER(resetTransactionTimeout); FINALIZER(runClearTable); } TESTCASE("BuddyTransNoTimeout", @@ -238,7 +385,9 @@ TESTCASE("BuddyTransNoTimeout", "The total sleep time is longer than TransactionInactiveTimeout" \ "Commit the first transaction, it should not have timed out."){ INITIALIZER(runLoadTable); + INITIALIZER(setTransactionTimeout); STEPS(runBuddyTransNoTimeout, 1); + FINALIZER(resetTransactionTimeout); FINALIZER(runClearTable); } TESTCASE("BuddyTransNoTimeout5", @@ -249,7 +398,9 @@ TESTCASE("BuddyTransNoTimeout5", "Commit the first transaction, it should not have timed out." \ "Five simultaneous threads"){ INITIALIZER(runLoadTable); + INITIALIZER(setTransactionTimeout); STEPS(runBuddyTransNoTimeout, 5); + FINALIZER(resetTransactionTimeout); FINALIZER(runClearTable); } NDBT_TESTSUITE_END(testTimeout); diff --git a/ndb/test/ndbapi/testTransactions.cpp b/ndb/test/ndbapi/testTransactions.cpp index 9ce928f8736..67a2df24390 100644 --- a/ndb/test/ndbapi/testTransactions.cpp +++ b/ndb/test/ndbapi/testTransactions.cpp @@ -102,7 +102,7 @@ OperationTestCase matrix[] = { { "ScanExInsert", true, "SCAN-EX",1, "INSERT", 266, X, 0, 1 }, { "ScanExUpdate", true, "SCAN-EX",1, "UPDATE", 266, 2, 0, 1 }, { "ScanExDelete", true, "SCAN-EX",1, "DELETE", 266, X, 0, 1 }, - { "ScanExScan", true, "SCAN-EX",1, "SCAN", 274, X, 0, 1 }, + { "ScanExScan", true, "SCAN-EX",1, "SCAN", 0, 1, 0, 1 }, { "ScanExScanHl", true, "SCAN-EX",1, "SCAN-HL", 274, X, 0, 1 }, { "ScanExScanEx", true, "SCAN-EX",1, "SCAN-EX", 274, X, 0, 1 }, #if 0 @@ -117,8 +117,8 @@ OperationTestCase matrix[] = { { "ReadExInsert", true, "READ-EX",1, "INSERT", 266, X, 0, 1 }, { "ReadExUpdate", true, "READ-EX",1, "UPDATE", 266, X, 0, 1 }, { "ReadExDelete", true, "READ-EX",1, "DELETE", 266, X, 0, 1 }, - { "ReadExScan", true, "READ-EX",1, "SCAN", 274, 1, 0, 1 }, - { "ReadExScanHl", true, "READ-EX",1, "SCAN-HL", 274, 1, 0, 1 }, + { "ReadExScan", true, "READ-EX",1, "SCAN", 0, 1, 0, 1 }, + { "ReadExScanHl", true, "READ-EX",1, "SCAN-HL", 274, X, 0, 1 }, { "ReadExScanEx", true, "READ-EX",1, "SCAN-EX", 274, X, 0, 1 }, #if 0 { "ReadExScanUp", true, "READ-EX",1, "SCAN-UP", 266, X, 0, 1 }, @@ -132,7 +132,7 @@ OperationTestCase matrix[] = { { "InsertInsert", false, "INSERT", 1, "INSERT", 266, X, 0, 1 }, { "InsertUpdate", false, "INSERT", 1, "UPDATE", 266, X, 0, 1 }, { "InsertDelete", false, "INSERT", 1, "DELETE", 266, X, 0, 1 }, - { "InsertScan", false, "INSERT", 1, "SCAN", 274, X, 0, 1 }, + { "InsertScan", false, "INSERT", 1, "SCAN", 626, X, 0, 1 }, { "InsertScanHl", false, "INSERT", 1, "SCAN-HL", 274, X, 0, 1 }, { "InsertScanEx", false, "INSERT", 1, "SCAN-EX", 274, X, 0, 1 }, #if 0 @@ -147,7 +147,7 @@ OperationTestCase matrix[] = { { "UpdateInsert", true, "UPDATE", 2, "INSERT", 266, X, 0, 2 }, { "UpdateUpdate", true, "UPDATE", 2, "UPDATE", 266, X, 0, 2 }, { "UpdateDelete", true, "UPDATE", 2, "DELETE", 266, X, 0, 2 }, - { "UpdateScan", true, "UPDATE", 2, "SCAN", 274, X, 0, 2 }, + { "UpdateScan", true, "UPDATE", 2, "SCAN", 0, 1, 0, 2 }, { "UpdateScanHl", true, "UPDATE", 2, "SCAN-HL", 274, X, 0, 2 }, { "UpdateScanEx", true, "UPDATE", 2, "SCAN-EX", 274, X, 0, 2 }, #if 0 @@ -162,7 +162,7 @@ OperationTestCase matrix[] = { { "DeleteInsert", true, "DELETE", X, "INSERT", 266, X, 626, X }, { "DeleteUpdate", true, "DELETE", X, "UPDATE", 266, X, 626, X }, { "DeleteDelete", true, "DELETE", X, "DELETE", 266, X, 626, X }, - { "DeleteScan", true, "DELETE", X, "SCAN", 274, X, 626, X }, + { "DeleteScan", true, "DELETE", X, "SCAN", 0, 1, 626, X }, { "DeleteScanHl", true, "DELETE", X, "SCAN-HL", 274, X, 626, X }, { "DeleteScanEx", true, "DELETE", X, "SCAN-EX", 274, X, 626, X }, #if 0 @@ -206,9 +206,9 @@ runOp(HugoOperations & hugoOps, } else if(strcmp(op, "SCAN") == 0){ C2(hugoOps.scanReadRecords(pNdb) == 0); } else if(strcmp(op, "SCAN-HL") == 0){ - C2(hugoOps.scanReadRecords(pNdb, 240, HugoOperations::SL_ReadHold) == 0); + C2(hugoOps.scanReadRecords(pNdb, NdbScanOperation::LM_Read)== 0); } else if(strcmp(op, "SCAN-EX") == 0){ - C2(hugoOps.scanReadRecords(pNdb, 240, HugoOperations::SL_Exclusive) == 0); + C2(hugoOps.scanReadRecords(pNdb, NdbScanOperation::LM_Exclusive)== 0); } else { g_err << __FILE__ << " - " << __LINE__ << ": Unknown operation" << op << endl; diff --git a/ndb/test/run-test/Makefile.am b/ndb/test/run-test/Makefile.am index 3dd9632ce4b..04be35325db 100644 --- a/ndb/test/run-test/Makefile.am +++ b/ndb/test/run-test/Makefile.am @@ -1,18 +1,18 @@ -ndbtest_PROGRAMS = atrt +testdir=$(prefix)/mysql-test/ndb -atrt_SOURCES = main.cpp +include $(top_srcdir)/ndb/config/common.mk.am +include $(top_srcdir)/ndb/config/type_util.mk.am +include $(top_srcdir)/ndb/config/type_mgmapiclient.mk.am -ndbtest_SCRIPTS = atrt-analyze-result.sh atrt-gather-result.sh atrt-setup.sh \ +test_PROGRAMS = atrt +test_DATA=daily-basic-tests.txt daily-devel-tests.txt +test_SCRIPTS=atrt-analyze-result.sh atrt-gather-result.sh atrt-setup.sh \ atrt-clear-result.sh make-config.sh make-index.sh make-html-reports.sh -EXTRA_DIST = $(ndbtest_SCRIPTS) +atrt_SOURCES = main.cpp INCLUDES_LOC = -I$(top_srcdir)/ndb/src/mgmclient LDADD_LOC = $(top_builddir)/ndb/src/mgmclient/CpcClient.o $(top_builddir)/ndb/src/libndbclient.la -include $(top_srcdir)/ndb/config/common.mk.am -include $(top_srcdir)/ndb/config/type_util.mk.am -include $(top_srcdir)/ndb/config/type_mgmapiclient.mk.am - # Don't update the files from bitkeeper %::SCCS/s.% diff --git a/ndb/test/run-test/daily-basic-tests.txt b/ndb/test/run-test/daily-basic-tests.txt new file mode 100644 index 00000000000..631378cb636 --- /dev/null +++ b/ndb/test/run-test/daily-basic-tests.txt @@ -0,0 +1,1008 @@ +# BASIC FUNCTIONALITY +max-time: 500 +cmd: testBasic +args: -n PkRead + +max-time: 500 +cmd: testBasic +args: -n PkUpdate + +max-time: 500 +cmd: testBasic +args: -n PkDelete + +max-time: 500 +cmd: testBasic +args: -n PkInsert + +max-time: 600 +cmd: testBasic +args: -n UpdateAndRead + +max-time: 500 +cmd: testBasic +args: -n PkReadAndLocker T6 + +max-time: 500 +cmd: testBasic +args: -n PkReadAndLocker2 T6 + +max-time: 500 +cmd: testBasic +args: -n PkReadUpdateAndLocker T6 + +max-time: 500 +cmd: testBasic +args: -n ReadWithLocksAndInserts T6 + +max-time: 500 +cmd: testBasic +args: -n PkInsertTwice T1 T6 T10 + +max-time: 1500 +cmd: testBasic +args: -n Fill T13 + +max-time: 1500 +cmd: testBasic +args: -n Fill T6 + +max-time: 500 +cmd: testBasic +args: -n NoCommitSleep T6 + +max-time: 500 +cmd: testBasic +args: -n NoCommit626 T6 + +max-time: 500 +cmd: testBasic +args: -n NoCommitAndClose T6 + +max-time: 500 +cmd: testBasic +args: -n Commit626 T6 + +max-time: 500 +cmd: testBasic +args: -n CommitTry626 T6 + +max-time: 500 +cmd: testBasic +args: -n CommitAsMuch626 T6 + +max-time: 500 +cmd: testBasic +args: -n NoCommit626 T6 + +max-time: 500 +cmd: testBasic +args: -n NoCommitRollback626 T1 T6 + +max-time: 500 +cmd: testBasic +args: -n Commit630 T1 T6 + +max-time: 500 +cmd: testBasic +args: -n CommitTry630 T1 T6 + +max-time: 500 +cmd: testBasic +args: -n CommitAsMuch630 T1 T6 + +max-time: 500 +cmd: testBasic +args: -n NoCommit630 T1 T6 + +max-time: 500 +cmd: testBasic +args: -n NoCommitRollback630 T1 T6 + +max-time: 500 +cmd: testBasic +args: -n NoCommitAndClose T1 T6 + +max-time: 500 +cmd: testBasic +args: -n RollbackUpdate T1 T6 + +max-time: 500 +cmd: testBasic +args: -n RollbackDeleteMultiple T1 T6 + +max-time: 500 +cmd: testBasic +args: -n ImplicitRollbackDelete T1 T6 + +max-time: 500 +cmd: testBasic +args: -n CommitDelete T1 T6 + +max-time: 500 +cmd: testBasic +args: -n RollbackNothing T1 T6 + +max-time: 500 +cmd: testBasicAsynch +args: -n PkInsertAsynch + +max-time: 500 +cmd: testBasicAsynch +args: -n PkReadAsynch + +max-time: 500 +cmd: testBasicAsynch +args: -n PkUpdateAsynch + +max-time: 500 +cmd: testBasicAsynch +args: -n PkDeleteAsynch + +max-time: 500 +cmd: testBasic +args: -n MassiveRollback T1 T6 T13 + +max-time: 500 +cmd: testBasic +args: -n MassiveRollback2 T1 T6 T13 + +#-m 500 1: testBasic -n ReadConsistency T6 +max-time: 500 +cmd: testTimeout +args: -n DontTimeoutTransaction T1 + +max-time: 500 +cmd: testTimeout +args: -n DontTimeoutTransaction5 T1 + +max-time: 500 +cmd: testTimeout +args: -n TimeoutTransaction T1 + +max-time: 500 +cmd: testTimeout +args: -n TimeoutTransaction5 T1 + +max-time: 500 +cmd: testTimeout +args: -n BuddyTransNoTimeout T1 + +max-time: 500 +cmd: testTimeout +args: -n BuddyTransNoTimeout5 T1 + +max-time: 500 +cmd: testTimeout +args: -n TimeoutRandTransaction T1 + +# SCAN TESTS +# +max-time: 500 +cmd: testScan +args: -n ScanRead16 + +max-time: 500 +cmd: testScan +args: -n ScanRead240 + +max-time: 500 +cmd: testScan +args: -n ScanReadCommitted240 + +max-time: 500 +cmd: testScan +args: -n ScanUpdate + +max-time: 500 +cmd: testScan +args: -n ScanUpdate2 T6 + +max-time: 500 +cmd: testScan +args: -n ScanDelete + +max-time: 500 +cmd: testScan +args: -n ScanDelete2 T10 + +max-time: 500 +cmd: testScan +args: -n ScanUpdateAndScanRead T6 + +max-time: 500 +cmd: testScan +args: -n ScanReadAndLocker T6 + +max-time: 500 +cmd: testScan +args: -n ScanReadAndPkRead T6 + +max-time: 500 +cmd: testScan +args: -n ScanRead488 -l 10 T6 + +max-time: 600 +cmd: testScan +args: -n ScanRead40 -l 100 T2 + +max-time: 1800 +cmd: testScan +args: -n ScanRead100 -l 100 T1 + +max-time: 600 +cmd: testScan +args: -n ScanRead40 -l 100 T1 + +max-time: 1800 +cmd: testScan +args: -n ScanRead40RandomTable -l 100 T1 + +max-time: 3600 +cmd: testScan +args: -n ScanRead40RandomTable -l 1000 T2 + +max-time: 500 +cmd: testScan +args: -n ScanWithLocksAndInserts T6 + +max-time: 500 +cmd: testScan +args: -n ScanReadAbort T6 + +max-time: 500 +cmd: testScan +args: -n ScanReadAbort15 T6 + +max-time: 500 +cmd: testScan +args: -n ScanReadAbort240 T6 + +max-time: 500 +cmd: testScan +args: -n ScanUpdateAbort16 T6 + +max-time: 3600 +cmd: testScan +args: -n ScanReadRestart T1 T6 T13 + +max-time: 500 +cmd: testScan +args: -n ScanUpdateRestart T6 + +max-time: 500 +cmd: testScan +args: -n CheckGetValue T6 + +max-time: 500 +cmd: testScan +args: -n CloseWithoutStop T6 + +max-time: 500 +cmd: testScan +args: -n NextScanWhenNoMore T6 + +max-time: 500 +cmd: testScan +args: -n ExecuteScanWithoutOpenScan T6 + +max-time: 500 +cmd: testScan +args: -n OnlyOpenScanOnce T6 + +max-time: 500 +cmd: testScan +args: -n OnlyOneOpInScanTrans T6 + +max-time: 500 +cmd: testScan +args: -n OnlyOneOpBeforeOpenScan T6 + +max-time: 500 +cmd: testScan +args: -n OnlyOneScanPerTrans T6 + +max-time: 500 +cmd: testScan +args: -n NoCloseTransaction T6 + +max-time: 500 +cmd: testScan +args: -n CheckInactivityTimeOut T6 + +max-time: 500 +cmd: testScan +args: -n CheckInactivityBeforeClose T6 + +max-time: 500 +cmd: testScan +args: -n CheckAfterTerror T6 + +max-time: 500 +cmd: testScan +args: -n ScanReadError5021 T1 + +max-time: 500 +cmd: testScan +args: -n ScanReaderror5022 T1 + +max-time: 500 +cmd: testScan +args: -n ScanReadError5023 T1 + +max-time: 500 +cmd: testScan +args: -n ScanReadError5024 T1 + +max-time: 500 +cmd: testScan +args: -n ScanReadError5025 T1 + +max-time: 500 +cmd: testScan +args: -n ScanReadError5030 T1 + +max-time: 500 +cmd: testScan +args: -n InsertDelete T1 T6 + +max-time: 500 +cmd: testScan +args: -n CheckAfterTerror T1 + +max-time: 500 +cmd: testScan +args: -n ScanReadWhileNodeIsDown T1 + +max-time: 500 +cmd: testScan +args: -n ScanRestart T1 + +# OLD FLEX +max-time: 500 +cmd: flexBench +args: -c 25 -t 10 + +max-time: 500 +cmd: flexHammer +args: -r 5 -t 32 + +# +# DICT TESTS +max-time: 1500 +cmd: testDict +args: -n CreateAndDrop + +max-time: 1500 +cmd: testDict +args: -n CreateAndDropWithData + +max-time: 1500 +cmd: testDict +args: -n CreateAndDropDuring T6 T10 + +max-time: 1500 +cmd: testDict +args: -n CreateInvalidTables + +max-time: 1500 +cmd: testDict +args: -n CreateTableWhenDbIsFull T6 + +max-time: 1500 +cmd: testDict +args: -n CreateMaxTables T6 + +max-time: 500 +cmd: testDict +args: -n FragmentTypeSingle T1 + +max-time: 1500 +cmd: testDict +args: -n FragmentTypeAll T1 T6 T7 T8 + +max-time: 1500 +cmd: testDict +args: -n FragmentTypeAllLarge T1 T6 T7 T8 + +max-time: 1500 +cmd: testDict +args: -n TemporaryTables T1 T6 T7 T8 + +# +# TEST NDBAPI +# +max-time: 500 +cmd: testDataBuffers +args: + +# Testsuite: testNdbApi +# Number of tests: 5 +max-time: 500 +cmd: testNdbApi +args: -n MaxNdb T6 + +max-time: 500 +cmd: testNdbApi +args: -n MaxTransactions T1 T6 T7 T8 T13 + +max-time: 500 +cmd: testNdbApi +args: -n MaxOperations T1 T6 T7 T8 T13 + +max-time: 500 +cmd: testNdbApi +args: -n MaxGetValue T1 T6 T7 T8 T13 + +max-time: 500 +cmd: testNdbApi +args: -n MaxEqual + +max-time: 500 +cmd: testNdbApi +args: -n DeleteNdb T1 T6 + +max-time: 500 +cmd: testNdbApi +args: -n WaitUntilReady T1 T6 T7 T8 T13 + +max-time: 500 +cmd: testNdbApi +args: -n GetOperationNoTab T6 + +max-time: 500 +cmd: testNdbApi +args: -n NdbErrorOperation T6 + +max-time: 500 +cmd: testNdbApi +args: -n MissingOperation T6 + +max-time: 500 +cmd: testNdbApi +args: -n GetValueInUpdate T6 + +max-time: 500 +cmd: testNdbApi +args: -n UpdateWithoutKeys T6 + +max-time: 500 +cmd: testNdbApi +args: -n UpdateWithoutValues T6 + +#max-time: 500 +#cmd: testInterpreter +#args: T1 +# +max-time: 1500 +cmd: testOperations +args: -n ReadRead + +max-time: 1500 +cmd: testOperations +args: -n ReadReadEx + +max-time: 1500 +cmd: testOperations +args: -n ReadInsert + +max-time: 1500 +cmd: testOperations +args: -n ReadUpdate + +max-time: 1500 +cmd: testOperations +args: -n ReadDelete + +max-time: 1500 +cmd: testOperations +args: -n FReadRead + +max-time: 1500 +cmd: testOperations +args: -n FReadReadEx + +max-time: 1500 +cmd: testOperations +args: -n FReadInsert + +max-time: 1500 +cmd: testOperations +args: -n FReadUpdate + +max-time: 1500 +cmd: testOperations +args: -n FReadDelete + +max-time: 1500 +cmd: testOperations +args: -n ReadExRead + +max-time: 1500 +cmd: testOperations +args: -n ReadExReadEx + +max-time: 1500 +cmd: testOperations +args: -n ReadExInsert + +max-time: 1500 +cmd: testOperations +args: -n ReadExUpdate + +max-time: 1500 +cmd: testOperations +args: -n ReadExDelete + +max-time: 1500 +cmd: testOperations +args: -n InsertRead + +max-time: 1500 +cmd: testOperations +args: -n InsertReadEx + +max-time: 1500 +cmd: testOperations +args: -n InsertInsert + +max-time: 1500 +cmd: testOperations +args: -n InsertUpdate + +max-time: 1500 +cmd: testOperations +args: -n InsertDelete + +max-time: 1500 +cmd: testOperations +args: -n UpdateRead + +max-time: 1500 +cmd: testOperations +args: -n UpdateReadEx + +max-time: 1500 +cmd: testOperations +args: -n UpdateInsert + +max-time: 1500 +cmd: testOperations +args: -n UpdateUpdate + +max-time: 1500 +cmd: testOperations +args: -n UpdateDelete + +max-time: 1500 +cmd: testOperations +args: -n DeleteRead + +max-time: 1500 +cmd: testOperations +args: -n DeleteReadEx + +max-time: 1500 +cmd: testOperations +args: -n DeleteInsert + +max-time: 1500 +cmd: testOperations +args: -n DeleteUpdate + +max-time: 1500 +cmd: testOperations +args: -n DeleteDelete + +max-time: 1500 +cmd: testOperations +args: -n ReadSimpleRead + +max-time: 1500 +cmd: testOperations +args: -n ReadDirtyRead + +max-time: 1500 +cmd: testOperations +args: -n FReadSimpleRead + +max-time: 1500 +cmd: testOperations +args: -n FReadDirtyRead + +max-time: 1500 +cmd: testOperations +args: -n ReadExSimpleRead + +max-time: 1500 +cmd: testOperations +args: -n ReadExDirtyRead + +max-time: 1500 +cmd: testOperations +args: -n InsertSimpleRead + +max-time: 1500 +cmd: testOperations +args: -n InsertDirtyRead + +max-time: 1500 +cmd: testOperations +args: -n UpdateSimpleRead + +max-time: 1500 +cmd: testOperations +args: -n UpdateDirtyRead + +max-time: 1500 +cmd: testOperations +args: -n DeleteSimpleRead + +max-time: 1500 +cmd: testOperations +args: -n DeleteDirtyRead + +max-time: 1500 +cmd: testTransactions +args: -n ReadRead + +max-time: 1500 +cmd: testTransactions +args: -n ReadReadEx + +max-time: 1500 +cmd: testTransactions +args: -n ReadInsert + +max-time: 1500 +cmd: testTransactions +args: -n ReadUpdate + +max-time: 1500 +cmd: testTransactions +args: -n ReadDelete + +max-time: 1500 +cmd: testTransactions +args: -n ReadExRead + +max-time: 1500 +cmd: testTransactions +args: -n ReadExReadEx + +max-time: 1500 +cmd: testTransactions +args: -n ReadExInsert + +max-time: 1500 +cmd: testTransactions +args: -n ReadExUpdate + +max-time: 1500 +cmd: testTransactions +args: -n ReadExDelete + +max-time: 1500 +cmd: testTransactions +args: -n InsertRead + +max-time: 1500 +cmd: testTransactions +args: -n InsertReadEx + +max-time: 1500 +cmd: testTransactions +args: -n InsertInsert + +max-time: 1500 +cmd: testTransactions +args: -n InsertUpdate + +max-time: 1500 +cmd: testTransactions +args: -n InsertDelete + +max-time: 1500 +cmd: testTransactions +args: -n UpdateRead + +max-time: 1500 +cmd: testTransactions +args: -n UpdateReadEx + +max-time: 1500 +cmd: testTransactions +args: -n UpdateInsert + +max-time: 1500 +cmd: testTransactions +args: -n UpdateUpdate + +max-time: 1500 +cmd: testTransactions +args: -n UpdateDelete + +max-time: 1500 +cmd: testTransactions +args: -n DeleteRead + +max-time: 1500 +cmd: testTransactions +args: -n DeleteReadEx + +max-time: 1500 +cmd: testTransactions +args: -n DeleteInsert + +max-time: 1500 +cmd: testTransactions +args: -n DeleteUpdate + +max-time: 1500 +cmd: testTransactions +args: -n DeleteDelete + +max-time: 1500 +cmd: testTransactions +args: -n ReadSimpleRead + +max-time: 1500 +cmd: testTransactions +args: -n ReadDirtyRead + +max-time: 1500 +cmd: testTransactions +args: -n ReadExSimpleRead + +max-time: 1500 +cmd: testTransactions +args: -n ReadExDirtyRead + +max-time: 1500 +cmd: testTransactions +args: -n InsertSimpleRead + +max-time: 1500 +cmd: testTransactions +args: -n InsertDirtyRead + +max-time: 1500 +cmd: testTransactions +args: -n UpdateSimpleRead + +max-time: 1500 +cmd: testTransactions +args: -n UpdateDirtyRead + +max-time: 1500 +cmd: testTransactions +args: -n DeleteSimpleRead + +max-time: 1500 +cmd: testTransactions +args: -n DeleteDirtyRead + +max-time: 1500 +cmd: testTransactions +args: -n ReadScan + +max-time: 1500 +cmd: testTransactions +args: -n ReadScanHl + +max-time: 1500 +cmd: testTransactions +args: -n ReadScanEx + +max-time: 1500 +cmd: testTransactions +args: -n ScanRead + +max-time: 1500 +cmd: testTransactions +args: -n ScanReadEx + +max-time: 1500 +cmd: testTransactions +args: -n ScanSimpleRead + +max-time: 1500 +cmd: testTransactions +args: -n ScanDirtyRead + +max-time: 1500 +cmd: testTransactions +args: -n ScanInsert + +max-time: 1500 +cmd: testTransactions +args: -n ScanUpdate + +max-time: 1500 +cmd: testTransactions +args: -n ScanDelete + +max-time: 1500 +cmd: testTransactions +args: -n ScanScan + +max-time: 1500 +cmd: testTransactions +args: -n ScanScanHl + +max-time: 1500 +cmd: testTransactions +args: -n ScanScanEx + +max-time: 1500 +cmd: testTransactions +args: -n ScanHlRead + +max-time: 1500 +cmd: testTransactions +args: -n ScanHlReadEx + +max-time: 1500 +cmd: testTransactions +args: -n ScanHlSimpleRead + +max-time: 1500 +cmd: testTransactions +args: -n ScanHlDirtyRead + +max-time: 1500 +cmd: testTransactions +args: -n ScanHlInsert + +max-time: 1500 +cmd: testTransactions +args: -n ScanHlUpdate + +max-time: 1500 +cmd: testTransactions +args: -n ScanHlDelete + +max-time: 1500 +cmd: testTransactions +args: -n ScanHlScan + +max-time: 1500 +cmd: testTransactions +args: -n ScanHlScanHl + +max-time: 1500 +cmd: testTransactions +args: -n ScanHlScanEx + +max-time: 1500 +cmd: testTransactions +args: -n ScanExRead + +max-time: 1500 +cmd: testTransactions +args: -n ScanExReadEx + +max-time: 1500 +cmd: testTransactions +args: -n ScanExSimpleRead + +max-time: 1500 +cmd: testTransactions +args: -n ScanExDirtyRead + +max-time: 1500 +cmd: testTransactions +args: -n ScanExInsert + +max-time: 1500 +cmd: testTransactions +args: -n ScanExUpdate + +max-time: 1500 +cmd: testTransactions +args: -n ScanExDelete + +max-time: 1500 +cmd: testTransactions +args: -n ScanExScan + +max-time: 1500 +cmd: testTransactions +args: -n ScanExScanHl + +max-time: 1500 +cmd: testTransactions +args: -n ScanExScanEx + +max-time: 1500 +cmd: testTransactions +args: -n ReadExScan + +max-time: 1500 +cmd: testTransactions +args: -n ReadExScanHl + +max-time: 1500 +cmd: testTransactions +args: -n ReadExScanEx + +max-time: 1500 +cmd: testTransactions +args: -n InsertScan + +max-time: 1500 +cmd: testTransactions +args: -n InsertScanHl + +max-time: 1500 +cmd: testTransactions +args: -n InsertScanEx + +max-time: 1500 +cmd: testTransactions +args: -n UpdateScan + +max-time: 1500 +cmd: testTransactions +args: -n UpdateScanHl + +max-time: 1500 +cmd: testTransactions +args: -n UpdateScanEx + +max-time: 1500 +cmd: testTransactions +args: -n DeleteScan + +max-time: 1500 +cmd: testTransactions +args: -n DeleteScanHl + +max-time: 1500 +cmd: testTransactions +args: -n DeleteScanEx + +max-time: 1500 +cmd: testRestartGci +args: T6 + +max-time: 600 +cmd: testBlobs +args: + +max-time: 2500 +cmd: testOIBasic +args: + +# +# +# SYSTEM RESTARTS +# +max-time: 1500 +cmd: testSystemRestart +args: -n SR1 T1 + +max-time: 1500 +cmd: testSystemRestart +args: -n SR1 T6 + +max-time: 1500 +cmd: testSystemRestart +args: -n SR1 T7 + +max-time: 1500 +cmd: testSystemRestart +args: -n SR1 T8 + +max-time: 1500 +cmd: testSystemRestart +args: -n SR2 T1 + +max-time: 1500 +cmd: testSystemRestart +args: -n SR2 T6 + +max-time: 1500 +cmd: testSystemRestart +args: -n SR2 T7 + diff --git a/ndb/test/run-test/daily-devel-tests.txt b/ndb/test/run-test/daily-devel-tests.txt new file mode 100644 index 00000000000..15fa4db4abc --- /dev/null +++ b/ndb/test/run-test/daily-devel-tests.txt @@ -0,0 +1,204 @@ +# +# INDEX +# +max-time: 1500 +cmd: testIndex +args: -n CreateAll T1 T6 T13 + +#-m 7200 1: testIndex -n InsertDeleteGentle T7 +max-time: 3600 +cmd: testIndex +args: -n InsertDelete T1 T10 + +#-m 3600 1: testIndex -n CreateLoadDropGentle T7 +max-time: 3600 +cmd: testIndex +args: -n CreateLoadDrop T1 T10 + +# +# BACKUP +# +max-time: 600 +cmd: testBackup +args: -n BackupOne T1 T6 T3 I3 + +#max-time: 600 +#cmd: testBackup +#args: -n BackupBank T6 +# +# +# MGMAPI AND MGSRV +# +max-time: 1800 +cmd: testMgm +args: -n SingleUserMode T1 + +# +# +# SYSTEM RESTARTS +# +max-time: 1500 +cmd: testSystemRestart +args: -n SR_UNDO T1 + +max-time: 1500 +cmd: testSystemRestart +args: -n SR_UNDO T6 + +max-time: 1500 +cmd: testSystemRestart +args: -n SR_UNDO T7 + +max-time: 1500 +cmd: testSystemRestart +args: -n SR_UNDO T8 + +max-time: 1500 +cmd: testSystemRestart +args: -n SR3 T6 + +max-time: 1500 +cmd: testSystemRestart +args: -n SR4 T6 + +# +max-time: 1500 +cmd: testSystemRestart +args: -n SR_FULLDB T1 + +# +# NODE RESTARTS +# +max-time: 2500 +cmd: testNodeRestart +args: -n NoLoad T6 T8 T13 + +max-time: 2500 +cmd: testNodeRestart +args: -n PkRead T6 T8 T13 + +max-time: 2500 +cmd: testNodeRestart +args: -l 1 -n PkReadPkUpdate + +max-time: 2500 +cmd: testNodeRestart +args: -l 1 -n ReadUpdateScan + +max-time: 2500 +cmd: testNodeRestart +args: -n Terror T6 T13 + +max-time: 2500 +cmd: testNodeRestart +args: -n FullDb T6 T13 + +max-time: 2500 +cmd: testNodeRestart +args: -n RestartRandomNode T6 T13 + +max-time: 2500 +cmd: testNodeRestart +args: -n RestartRandomNodeError T6 T13 + +max-time: 2500 +cmd: testNodeRestart +args: -n RestartRandomNodeInitial T6 T13 + +max-time: 3600 +cmd: testNodeRestart +args: -l 1 -n RestartNFDuringNR T6 T13 + +max-time: 2500 +cmd: testNodeRestart +args: -n RestartMasterNodeError T6 T8 T13 + +max-time: 3600 +cmd: testNodeRestart +args: -n RestartNodeDuringLCP T6 + +max-time: 2500 +cmd: testNodeRestart +args: -n TwoNodeFailure T6 T8 T13 + +max-time: 2500 +cmd: testNodeRestart +args: -n TwoMasterNodeFailure T6 T8 T13 + +max-time: 2500 +cmd: testNodeRestart +args: -n FiftyPercentFail T6 T8 T13 + +max-time: 2500 +cmd: testNodeRestart +args: -n RestartAllNodes T6 T8 T13 + +max-time: 2500 +cmd: testNodeRestart +args: -n RestartAllNodesAbort T6 T8 T13 + +max-time: 2500 +cmd: testNodeRestart +args: -n RestartAllNodesError9999 T6 T8 T13 + +max-time: 2500 +cmd: testNodeRestart +args: -n FiftyPercentStopAndWait T6 T8 T13 + +#max-time: 500 +#cmd: testNodeRestart +#args: -n StopOnError T1 +# +# +max-time: 2500 +cmd: testIndex +args: -n NFNR1 T6 T13 + +max-time: 2500 +cmd: testIndex +args: -n NFNR2 T6 T13 + +max-time: 2500 +cmd: testIndex +args: -n NFNR3 T6 T13 + +max-time: 2500 +cmd: testIndex +args: -n BuildDuring T6 + +max-time: 2500 +cmd: testIndex +args: -l 2 -n SR1 T6 T13 + +max-time: 2500 +cmd: testIndex +args: -n NFNR1_O T6 T13 + +max-time: 2500 +cmd: testIndex +args: -n NFNR2_O T6 T13 + +max-time: 2500 +cmd: testIndex +args: -n NFNR3_O T6 T13 + +max-time: 2500 +cmd: testIndex +args: -n BuildDuring_O T6 + +max-time: 2500 +cmd: testIndex +args: -l 2 -n SR1_O T6 T13 + +max-time: 500 +cmd: testIndex +args: -n MixedTransaction T1 + +max-time: 2500 +cmd: testDict +args: -n NF1 T1 T6 T13 + +max-time: 2500 +cmd: test_event +args: -n BasicEventOperation T1 T6 + diff --git a/ndb/test/run-test/main.cpp b/ndb/test/run-test/main.cpp index 9e318b0219e..6f1899fdbe2 100644 --- a/ndb/test/run-test/main.cpp +++ b/ndb/test/run-test/main.cpp @@ -106,13 +106,6 @@ main(int argc, const char ** argv){ if(!setup_hosts(g_config)) goto end; - if(!start_processes(g_config, atrt_process::NDB_MGM)) - goto end; - - if(!connect_ndb_mgm(g_config)){ - goto end; - } - /** * Main loop */ @@ -122,25 +115,32 @@ main(int argc, const char ** argv){ */ if(restart){ g_logger.info("(Re)starting ndb processes"); + if(!stop_processes(g_config, atrt_process::NDB_MGM)) + goto end; + if(!stop_processes(g_config, atrt_process::NDB_DB)) goto end; - if(!wait_ndb(g_config, NDB_MGM_NODE_STATUS_NO_CONTACT)) + if(!start_processes(g_config, atrt_process::NDB_MGM)) goto end; + if(!connect_ndb_mgm(g_config)){ + goto end; + } + if(!start_processes(g_config, atrt_process::NDB_DB)) goto end; - + if(!wait_ndb(g_config, NDB_MGM_NODE_STATUS_NOT_STARTED)) goto end; - + for(Uint32 i = 0; i<3; i++) if(wait_ndb(g_config, NDB_MGM_NODE_STATUS_STARTED)) goto started; - + goto end; - -started: + + started: g_logger.info("Ndb start completed"); } @@ -211,7 +211,7 @@ started: (result == 0 ? "OK" : "FAILED"), result); if(g_report_file != 0){ - fprintf(g_report_file, "%s %s ; %d ; %d ; %d\n", + fprintf(g_report_file, "%s %s ; %d ; %d ; %ld\n", test_case.m_command.c_str(), test_case.m_args.c_str(), test_no, result, elapsed); @@ -447,7 +447,6 @@ setup_config(atrt_config& config){ proc.m_proc.m_owner = "atrt"; proc.m_proc.m_group = "group"; proc.m_proc.m_cwd.assign(dir).append("/run/"); - proc.m_proc.m_env.assfmt("LD_LIBRARY_PATH=%s/lib/mysql", dir.c_str()); proc.m_proc.m_stdout = "log.out"; proc.m_proc.m_stderr = "2>&1"; proc.m_proc.m_runas = proc.m_host->m_user; @@ -460,7 +459,7 @@ setup_config(atrt_config& config){ proc.m_proc.m_path.assign(dir).append("/libexec/ndb_mgmd"); proc.m_proc.m_args = "-n -c initconfig.txt"; proc.m_proc.m_cwd.appfmt("%d.ndb_mgmd", index); - connect_string.appfmt(";host=%s:%d", + connect_string.appfmt("host=%s:%d;", proc.m_hostname.c_str(), proc.m_ndb_mgm_port); } else if(split1[0] == "ndb"){ proc.m_type = atrt_process::NDB_DB; @@ -502,10 +501,10 @@ setup_config(atrt_config& config){ // Setup connect string for(size_t i = 0; i<config.m_processes.size(); i++){ - config.m_processes[i].m_proc.m_env.appfmt(" NDB_CONNECTSTRING=nodeid=%d%s", - i+1, connect_string.c_str()); + config.m_processes[i].m_proc.m_env.assfmt("NDB_CONNECTSTRING=%s", + connect_string.c_str()); } - + end: fclose(f); return result; @@ -615,11 +614,22 @@ wait_ndb(atrt_config& config, int goal){ /** * 1) retreive current state */ - state = ndb_mgm_get_status(handle); - if(state == 0){ - g_logger.critical("Unable to poll db state"); - return false; - } + state = 0; + do { + state = ndb_mgm_get_status(handle); + if(state == 0){ + const int err = ndb_mgm_get_latest_error(handle); + g_logger.error("Unable to poll db state: %d %s %s", + ndb_mgm_get_latest_error(handle), + ndb_mgm_get_latest_error_msg(handle), + ndb_mgm_get_latest_error_desc(handle)); + if(err == NDB_MGM_SERVER_NOT_CONNECTED && connect_ndb_mgm(config)){ + g_logger.error("Reconnected..."); + continue; + } + return false; + } + } while(state == 0); NdbAutoPtr<void> tmp(state); min2 = goal; @@ -791,6 +801,10 @@ update_status(atrt_config& config, int){ proc.m_proc.m_id, proc.m_hostname.c_str(), proc.m_proc.m_path.c_str()); + for(size_t j = 0; j<h_procs.size(); j++){ + g_logger.error("found: %d %s", h_procs[j].m_id, + h_procs[j].m_path.c_str()); + } return false; } } @@ -924,9 +938,11 @@ gather_result(atrt_config& config, int * result){ BaseString tmp = g_gather_progname; for(size_t i = 0; i<config.m_processes.size(); i++){ atrt_process & proc = config.m_processes[i]; - tmp.appfmt(" %s:%s", - proc.m_hostname.c_str(), - proc.m_proc.m_cwd.c_str()); + if(proc.m_proc.m_path != ""){ + tmp.appfmt(" %s:%s", + proc.m_hostname.c_str(), + proc.m_proc.m_cwd.c_str()); + } } const int r1 = system(tmp.c_str()); @@ -970,3 +986,7 @@ setup_hosts(atrt_config& config){ } return true; } + +template class Vector<Vector<SimpleCpcClient::Process> >; +template class Vector<atrt_host>; +template class Vector<atrt_process>; diff --git a/ndb/test/src/HugoAsynchTransactions.cpp b/ndb/test/src/HugoAsynchTransactions.cpp index 2af22b5f48d..f75293f5a14 100644 --- a/ndb/test/src/HugoAsynchTransactions.cpp +++ b/ndb/test/src/HugoAsynchTransactions.cpp @@ -165,12 +165,13 @@ HugoAsynchTransactions::pkUpdateRecordsAsynch(Ndb* pNdb, allocRows(trans*operations); allocTransactions(trans); + int a, t, r; for (int i = 0; i < batch; i++) { // For each batch while (cRecords < records*batch) { cTrans = 0; cReadIndex = 0; - for (int t = 0; t < trans; t++) { // For each transaction + for (t = 0; t < trans; t++) { // For each transaction transactions[t] = pNdb->startTransaction(); if (transactions[t] == NULL) { ERR(pNdb->getNdbError()); @@ -187,7 +188,7 @@ HugoAsynchTransactions::pkUpdateRecordsAsynch(Ndb* pNdb, // Read // Define primary keys check = pOp->readTupleExclusive(); - for (int a = 0; a < tab.getNoOfColumns(); a++) { + for (a = 0; a < tab.getNoOfColumns(); a++) { if (tab.getColumn(a)->getPrimaryKey() == true) { if (equalForAttr(pOp, a, cReadRecords) != 0){ ERR(transactions[t]->getNdbError()); @@ -197,7 +198,7 @@ HugoAsynchTransactions::pkUpdateRecordsAsynch(Ndb* pNdb, } } // Define attributes to read - for (int a = 0; a < tab.getNoOfColumns(); a++) { + for (a = 0; a < tab.getNoOfColumns(); a++) { if ((rows[cReadIndex]->attributeStore(a) = pOp->getValue(tab.getColumn(a)->getName())) == 0) { ERR(transactions[t]->getNdbError()); @@ -225,7 +226,7 @@ HugoAsynchTransactions::pkUpdateRecordsAsynch(Ndb* pNdb, pNdb->sendPollNdb(3000, 0, 0); // Verify the data! - for (int r = 0; r < trans*operations; r++) { + for (r = 0; r < trans*operations; r++) { if (calc.verifyRowValues(rows[r]) != 0) { g_info << "|- Verify failed..." << endl; // Close all transactions @@ -239,7 +240,7 @@ HugoAsynchTransactions::pkUpdateRecordsAsynch(Ndb* pNdb, // Update cTrans = 0; cIndex = 0; - for (int t = 0; t < trans; t++) { // For each transaction + for (t = 0; t < trans; t++) { // For each transaction for (int k = 0; k < operations; k++) { // For each operation NdbOperation* pOp = transactions[t]->getNdbOperation(tab.getName()); if (pOp == NULL) { @@ -258,7 +259,7 @@ HugoAsynchTransactions::pkUpdateRecordsAsynch(Ndb* pNdb, } // Set search condition for the record - for (int a = 0; a < tab.getNoOfColumns(); a++) { + for (a = 0; a < tab.getNoOfColumns(); a++) { if (tab.getColumn(a)->getPrimaryKey() == true) { if (equalForAttr(pOp, a, cRecords) != 0) { ERR(transactions[t]->getNdbError()); @@ -269,7 +270,7 @@ HugoAsynchTransactions::pkUpdateRecordsAsynch(Ndb* pNdb, } // Update the record - for (int a = 0; a < tab.getNoOfColumns(); a++) { + for (a = 0; a < tab.getNoOfColumns(); a++) { if (tab.getColumn(a)->getPrimaryKey() == false) { if (setValueForAttr(pOp, a, cRecords, updates) != 0) { ERR(transactions[t]->getNdbError()); @@ -298,7 +299,7 @@ HugoAsynchTransactions::pkUpdateRecordsAsynch(Ndb* pNdb, pNdb->sendPollNdb(3000, 0, 0); // Close all transactions - for (int t = 0; t < cTrans; t++) { + for (t = 0; t < cTrans; t++) { pNdb->closeTransaction(transactions[t]); } @@ -346,6 +347,7 @@ HugoAsynchTransactions::executeAsynchOperation(Ndb* pNdb, int cTrans = 0; int cRecords = 0; int cIndex = 0; + int a,t,r; transactionsCompleted = 0; allocTransactions(trans); @@ -354,7 +356,7 @@ HugoAsynchTransactions::executeAsynchOperation(Ndb* pNdb, while (cRecords < records*batch) { cTrans = 0; cIndex = 0; - for (int t = 0; t < trans; t++) { // For each transaction + for (t = 0; t < trans; t++) { // For each transaction transactions[t] = pNdb->startTransaction(); if (transactions[t] == NULL) { ERR(pNdb->getNdbError()); @@ -379,7 +381,7 @@ HugoAsynchTransactions::executeAsynchOperation(Ndb* pNdb, } // Set a calculated value for each attribute in this table - for (int a = 0; a < tab.getNoOfColumns(); a++) { + for (a = 0; a < tab.getNoOfColumns(); a++) { if (setValueForAttr(pOp, a, cRecords, 0 ) != 0) { ERR(transactions[t]->getNdbError()); pNdb->closeTransaction(transactions[t]); @@ -394,7 +396,7 @@ HugoAsynchTransactions::executeAsynchOperation(Ndb* pNdb, case NO_READ: // Define primary keys check = pOp->readTuple(); - for (int a = 0; a < tab.getNoOfColumns(); a++) { + for (a = 0; a < tab.getNoOfColumns(); a++) { if (tab.getColumn(a)->getPrimaryKey() == true) { if (equalForAttr(pOp, a, cRecords) != 0){ ERR(transactions[t]->getNdbError()); @@ -404,7 +406,7 @@ HugoAsynchTransactions::executeAsynchOperation(Ndb* pNdb, } } // Define attributes to read - for (int a = 0; a < tab.getNoOfColumns(); a++) { + for (a = 0; a < tab.getNoOfColumns(); a++) { if ((rows[cIndex]->attributeStore(a) = pOp->getValue(tab.getColumn(a)->getName())) == 0) { ERR(transactions[t]->getNdbError()); @@ -423,7 +425,7 @@ HugoAsynchTransactions::executeAsynchOperation(Ndb* pNdb, } // Define primary keys - for (int a = 0; a < tab.getNoOfColumns(); a++) { + for (a = 0; a < tab.getNoOfColumns(); a++) { if (tab.getColumn(a)->getPrimaryKey() == true){ if (equalForAttr(pOp, a, cRecords) != 0) { ERR(transactions[t]->getNdbError()); @@ -462,7 +464,7 @@ HugoAsynchTransactions::executeAsynchOperation(Ndb* pNdb, switch (theOperation) { case NO_READ: // Verify the data! - for (int r = 0; r < trans*operations; r++) { + for (r = 0; r < trans*operations; r++) { if (calc.verifyRowValues(rows[r]) != 0) { g_info << "|- Verify failed..." << endl; // Close all transactions @@ -476,11 +478,11 @@ HugoAsynchTransactions::executeAsynchOperation(Ndb* pNdb, case NO_INSERT: case NO_UPDATE: case NO_DELETE: - abort(); + break; } // Close all transactions - for (int t = 0; t < cTrans; t++) { + for (t = 0; t < cTrans; t++) { pNdb->closeTransaction(transactions[t]); } diff --git a/ndb/test/src/HugoCalculator.cpp b/ndb/test/src/HugoCalculator.cpp index 55aa96a4909..147c8b104d8 100644 --- a/ndb/test/src/HugoCalculator.cpp +++ b/ndb/test/src/HugoCalculator.cpp @@ -28,7 +28,8 @@ HugoCalculator::HugoCalculator(const NdbDictionary::Table& tab) : m_tab(tab) { // The "id" column of this table is found in the first integer column - for (int i=0; i<m_tab.getNoOfColumns(); i++){ + int i; + for (i=0; i<m_tab.getNoOfColumns(); i++){ const NdbDictionary::Column* attr = m_tab.getColumn(i); if (attr->getType() == NdbDictionary::Column::Unsigned){ m_idCol = i; @@ -37,7 +38,7 @@ HugoCalculator::HugoCalculator(const NdbDictionary::Table& tab) : m_tab(tab) { } // The "number of updates" column for this table is found in the last column - for (int i=m_tab.getNoOfColumns()-1; i>=0; i--){ + for (i=m_tab.getNoOfColumns()-1; i>=0; i--){ const NdbDictionary::Column* attr = m_tab.getColumn(i); if (attr->getType() == NdbDictionary::Column::Unsigned){ m_updatesCol = i; @@ -102,7 +103,8 @@ HugoCalculator::calcValue(int record, // Fill buf with some pattern so that we can detect // anomalies in the area that we don't fill with chars - for (int i = 0; i<attr->getLength(); i++) + int i; + for (i = 0; i<attr->getLength(); i++) buf[i] = ((i+2) % 255); // Calculate length of the string to create. We want the string @@ -116,7 +118,7 @@ HugoCalculator::calcValue(int record, else len++; } - for(int i=0; i < len; i++) + for(i=0; i < len; i++) buf[i] = a[((val^i)%25)]; buf[len] = 0; } diff --git a/ndb/test/src/HugoOperations.cpp b/ndb/test/src/HugoOperations.cpp index 91263aa29b4..7c05cb86a93 100644 --- a/ndb/test/src/HugoOperations.cpp +++ b/ndb/test/src/HugoOperations.cpp @@ -40,6 +40,9 @@ int HugoOperations::closeTransaction(Ndb* pNdb){ } pTrans = NULL; + m_result_sets.clear(); + m_executed_result_sets.clear(); + return NDBT_OK; } @@ -51,7 +54,7 @@ int HugoOperations::pkReadRecord(Ndb* pNdb, int recordNo, bool exclusive, int numRecords){ - + int a; allocRows(numRecords); int check; for(int r=0; r < numRecords; r++){ @@ -71,7 +74,7 @@ int HugoOperations::pkReadRecord(Ndb* pNdb, } // Define primary keys - for(int a = 0; a<tab.getNoOfColumns(); a++){ + for(a = 0; a<tab.getNoOfColumns(); a++){ if (tab.getColumn(a)->getPrimaryKey() == true){ if(equalForAttr(pOp, a, r+recordNo) != 0){ ERR(pTrans->getNdbError()); @@ -81,7 +84,7 @@ int HugoOperations::pkReadRecord(Ndb* pNdb, } // Define attributes to read - for(int a = 0; a<tab.getNoOfColumns(); a++){ + for(a = 0; a<tab.getNoOfColumns(); a++){ if((rows[r]->attributeStore(a) = pOp->getValue(tab.getColumn(a)->getName())) == 0) { ERR(pTrans->getNdbError()); @@ -95,7 +98,7 @@ int HugoOperations::pkReadRecord(Ndb* pNdb, int HugoOperations::pkDirtyReadRecord(Ndb* pNdb, int recordNo, int numRecords){ - + int a; allocRows(numRecords); int check; for(int r=0; r < numRecords; r++){ @@ -113,7 +116,7 @@ int HugoOperations::pkDirtyReadRecord(Ndb* pNdb, } // Define primary keys - for(int a = 0; a<tab.getNoOfColumns(); a++){ + for(a = 0; a<tab.getNoOfColumns(); a++){ if (tab.getColumn(a)->getPrimaryKey() == true){ if(equalForAttr(pOp, a, r+recordNo) != 0){ ERR(pTrans->getNdbError()); @@ -123,7 +126,7 @@ int HugoOperations::pkDirtyReadRecord(Ndb* pNdb, } // Define attributes to read - for(int a = 0; a<tab.getNoOfColumns(); a++){ + for(a = 0; a<tab.getNoOfColumns(); a++){ if((rows[r]->attributeStore(a) = pOp->getValue(tab.getColumn(a)->getName())) == 0) { ERR(pTrans->getNdbError()); @@ -137,7 +140,7 @@ int HugoOperations::pkDirtyReadRecord(Ndb* pNdb, int HugoOperations::pkSimpleReadRecord(Ndb* pNdb, int recordNo, int numRecords){ - + int a; allocRows(numRecords); int check; for(int r=0; r < numRecords; r++){ @@ -155,7 +158,7 @@ int HugoOperations::pkSimpleReadRecord(Ndb* pNdb, } // Define primary keys - for(int a = 0; a<tab.getNoOfColumns(); a++){ + for(a = 0; a<tab.getNoOfColumns(); a++){ if (tab.getColumn(a)->getPrimaryKey() == true){ if(equalForAttr(pOp, a, r+recordNo) != 0){ ERR(pTrans->getNdbError()); @@ -165,7 +168,7 @@ int HugoOperations::pkSimpleReadRecord(Ndb* pNdb, } // Define attributes to read - for(int a = 0; a<tab.getNoOfColumns(); a++){ + for(a = 0; a<tab.getNoOfColumns(); a++){ if((rows[r]->attributeStore(a) = pOp->getValue(tab.getColumn(a)->getName())) == 0) { ERR(pTrans->getNdbError()); @@ -180,7 +183,7 @@ int HugoOperations::pkUpdateRecord(Ndb* pNdb, int recordNo, int numRecords, int updatesValue){ - + int a; allocRows(numRecords); int check; for(int r=0; r < numRecords; r++){ @@ -197,7 +200,7 @@ int HugoOperations::pkUpdateRecord(Ndb* pNdb, } // Define primary keys - for(int a = 0; a<tab.getNoOfColumns(); a++){ + for(a = 0; a<tab.getNoOfColumns(); a++){ if (tab.getColumn(a)->getPrimaryKey() == true){ if(equalForAttr(pOp, a, r+recordNo) != 0){ ERR(pTrans->getNdbError()); @@ -207,7 +210,7 @@ int HugoOperations::pkUpdateRecord(Ndb* pNdb, } // Define attributes to update - for(int a = 0; a<tab.getNoOfColumns(); a++){ + for(a = 0; a<tab.getNoOfColumns(); a++){ if (tab.getColumn(a)->getPrimaryKey() == false){ if(setValueForAttr(pOp, a, recordNo+r, updatesValue ) != 0){ ERR(pTrans->getNdbError()); @@ -224,7 +227,7 @@ int HugoOperations::pkInsertRecord(Ndb* pNdb, int numRecords, int updatesValue){ - int check; + int a, check; for(int r=0; r < numRecords; r++){ NdbOperation* pOp = pTrans->getNdbOperation(tab.getName()); if (pOp == NULL) { @@ -239,7 +242,7 @@ int HugoOperations::pkInsertRecord(Ndb* pNdb, } // Define primary keys - for(int a = 0; a<tab.getNoOfColumns(); a++){ + for(a = 0; a<tab.getNoOfColumns(); a++){ if (tab.getColumn(a)->getPrimaryKey() == true){ if(equalForAttr(pOp, a, r+recordNo) != 0){ ERR(pTrans->getNdbError()); @@ -249,7 +252,7 @@ int HugoOperations::pkInsertRecord(Ndb* pNdb, } // Define attributes to update - for(int a = 0; a<tab.getNoOfColumns(); a++){ + for(a = 0; a<tab.getNoOfColumns(); a++){ if (tab.getColumn(a)->getPrimaryKey() == false){ if(setValueForAttr(pOp, a, recordNo+r, updatesValue ) != 0){ ERR(pTrans->getNdbError()); @@ -265,7 +268,7 @@ int HugoOperations::pkDeleteRecord(Ndb* pNdb, int recordNo, int numRecords){ - int check; + int a, check; for(int r=0; r < numRecords; r++){ NdbOperation* pOp = pTrans->getNdbOperation(tab.getName()); if (pOp == NULL) { @@ -280,7 +283,7 @@ int HugoOperations::pkDeleteRecord(Ndb* pNdb, } // Define primary keys - for(int a = 0; a<tab.getNoOfColumns(); a++){ + for(a = 0; a<tab.getNoOfColumns(); a++){ if (tab.getColumn(a)->getPrimaryKey() == true){ if(equalForAttr(pOp, a, r+recordNo) != 0){ ERR(pTrans->getNdbError()); @@ -291,110 +294,70 @@ int HugoOperations::pkDeleteRecord(Ndb* pNdb, } return NDBT_OK; } - -int HugoOperations::scanReadRecords(Ndb* pNdb, - Uint32 parallelism, ScanLock lock){ - - NdbConnection * pCon = pNdb->hupp(pTrans); +#if 0 +NdbResultSet* +HugoOperations::scanReadRecords(Ndb* pNdb, ScanLock lock){ + NDBT_ResultRow * m_tmpRow = new NDBT_ResultRow(tab); - ScanTmp tmp(pCon, m_tmpRow); - tmp.m_op = ScanTmp::READ; - NdbOperation* pOp = pCon->getNdbOperation(tab.getName()); + NdbScanOperation* pOp = pTrans->getNdbScanOperation(tab.getName()); if (pOp == NULL) { - ERR(pCon->getNdbError()); - return NDBT_FAILED; + ERR(pTrans->getNdbError()); + return 0; } + int check = 0; + NdbResultSet * rs = 0; switch(lock){ case SL_ReadHold: - check = pOp->openScanReadHoldLock(parallelism); + rs = pOp->readTuples(NdbScanOperation::LM_Read, 1, 1); break; case SL_Exclusive: - check = pOp->openScanExclusive(parallelism); + rs = pOp->readTuples(NdbScanOperation::LM_Exclusive, 1, 1); break; case SL_Read: default: - check = pOp->openScanRead(parallelism); + rs = pOp->readTuples(NdbScanOperation::LM_Dirty, 1, 1); } - if( check == -1 ) { - ERR(pCon->getNdbError()); - return NDBT_FAILED; + if( rs == 0) { + ERR(pTrans->getNdbError()); + return 0; } check = pOp->interpret_exit_ok(); if( check == -1 ) { - ERR(pCon->getNdbError()); - return NDBT_FAILED; + ERR(pTrans->getNdbError()); + return 0; } // Define attributes to read for(int a = 0; a<tab.getNoOfColumns(); a++){ if((m_tmpRow->attributeStore(a) = pOp->getValue(tab.getColumn(a)->getName())) == 0) { - ERR(pCon->getNdbError()); - return NDBT_FAILED; + ERR(pTrans->getNdbError()); + return 0; } } - - check = tmp.pTrans->executeScan(); - if( check == -1 ) { - NdbError err = tmp.pTrans->getNdbError(); - ERR(err); - return err.code; - } - - tmp.m_delete = false; - m_scans.push_back(tmp); - - return 0; + return rs; } -int HugoOperations::executeScanRead(Ndb* pNdb){ - - int check = 0; - for(Uint32 i = 0; i<m_scans.size(); i++){ - ScanTmp & tmp = m_scans[i]; - check = run(tmp); - if(check != 0){ - return check; - } - } - while(m_scans.size() > 0){ - ScanTmp & tmp = m_scans[m_scans.size() - 1]; - if(tmp.m_op != ScanTmp::DONE) - abort(); - - tmp.pTrans->close(); - delete tmp.m_tmpRow; - m_scans.erase(m_scans.size() - 1); - } - if(check != 0){ - return check; +int +HugoOperations::readTuples(NdbResultSet* rs){ + int res = 0; + while((res = rs->nextResult()) == 0){ } - + if(res != 1) + return NDBT_FAILED; return NDBT_OK; } +#endif int HugoOperations::execute_Commit(Ndb* pNdb, AbortOption eao){ int check = 0; - while(m_scans.size() > 0){ - ScanTmp & tmp = m_scans[m_scans.size() - 1]; - if(tmp.m_op != ScanTmp::DONE) - abort(); - - tmp.pTrans->close(); - delete tmp.m_tmpRow; - m_scans.erase(m_scans.size() - 1); - } - if(check != 0){ - return check; - } - check = pTrans->execute(Commit, eao); if( check == -1 ) { @@ -409,55 +372,41 @@ int HugoOperations::execute_Commit(Ndb* pNdb, return NDBT_FAILED; return err.code; } - return NDBT_OK; -} -int -HugoOperations::run(ScanTmp & tmp){ - int count = 0; - if(tmp.m_op == ScanTmp::DONE) - abort(); + for(int i = 0; i<m_result_sets.size(); i++){ + m_executed_result_sets.push_back(m_result_sets[i]); - int eof = tmp.pTrans->nextScanResult(true) ; - while(eof == 0){ - count++; - switch(tmp.m_op){ - case ScanTmp::READ: - case ScanTmp::UPDATE: - case ScanTmp::DELETE: - break; - case ScanTmp::DONE: - abort(); + int rows = m_result_sets[i].records; + NdbResultSet* rs = m_result_sets[i].m_result_set; + int res = rs->nextResult(); + switch(res){ + case 1: + return 626; + case -1: + const NdbError err = pTrans->getNdbError(); + ERR(err); + return (err.code > 0 ? err.code : NDBT_FAILED); } - rows.push_back(tmp.m_tmpRow->clone()); - eof = tmp.pTrans->nextScanResult(false); - } - tmp.m_op = ScanTmp::DONE; - if (eof == -1) { - deallocRows(); - NdbError err = tmp.pTrans->getNdbError(); - ERR(err); - return err.code; - } + // A row found - if(count == 0) - return 626; + switch(rows){ + case 0: + return 4000; + default: + m_result_sets[i].records--; + break; + } + } - return 0; + m_result_sets.clear(); + + return NDBT_OK; } int HugoOperations::execute_NoCommit(Ndb* pNdb, AbortOption eao){ int check; - for(Uint32 i = 0; i<m_scans.size(); i++){ - ScanTmp & tmp = m_scans[i]; - check = run(tmp); - if(check != 0){ - return check; - } - } - check = pTrans->execute(NoCommit, eao); if( check == -1 ) { @@ -472,6 +421,35 @@ int HugoOperations::execute_NoCommit(Ndb* pNdb, AbortOption eao){ return NDBT_FAILED; return err.code; } + + for(int i = 0; i<m_result_sets.size(); i++){ + m_executed_result_sets.push_back(m_result_sets[i]); + + int rows = m_result_sets[i].records; + NdbResultSet* rs = m_result_sets[i].m_result_set; + int res = rs->nextResult(); + switch(res){ + case 1: + return 626; + case -1: + const NdbError err = pTrans->getNdbError(); + ERR(err); + return (err.code > 0 ? err.code : NDBT_FAILED); + } + + // A row found + + switch(rows){ + case 0: + return 4000; + default: + case 1: + break; + } + } + + m_result_sets.clear(); + return NDBT_OK; } @@ -697,16 +675,13 @@ HugoOperations::refresh() { NdbConnection* t = getTransaction(); if(t) t->refresh(); - for(Uint32 i = 0; i<m_scans.size(); i++){ - if(m_scans[i].pTrans) - m_scans[i].pTrans->refresh(); - } } int HugoOperations::indexReadRecords(Ndb*, const char * idxName, int recordNo, bool exclusive, int numRecords){ + int a; allocRows(numRecords); int check; for(int r=0; r < numRecords; r++){ @@ -726,7 +701,7 @@ int HugoOperations::indexReadRecords(Ndb*, const char * idxName, int recordNo, } // Define primary keys - for(int a = 0; a<tab.getNoOfColumns(); a++){ + for(a = 0; a<tab.getNoOfColumns(); a++){ if (tab.getColumn(a)->getPrimaryKey() == true){ if(equalForAttr(pOp, a, r+recordNo) != 0){ ERR(pTrans->getNdbError()); @@ -736,7 +711,7 @@ int HugoOperations::indexReadRecords(Ndb*, const char * idxName, int recordNo, } // Define attributes to read - for(int a = 0; a<tab.getNoOfColumns(); a++){ + for(a = 0; a<tab.getNoOfColumns(); a++){ if((rows[r]->attributeStore(a) = pOp->getValue(tab.getColumn(a)->getName())) == 0) { ERR(pTrans->getNdbError()); @@ -753,7 +728,7 @@ HugoOperations::indexUpdateRecord(Ndb*, int recordNo, int numRecords, int updatesValue){ - + int a; allocRows(numRecords); int check; for(int r=0; r < numRecords; r++){ @@ -770,7 +745,7 @@ HugoOperations::indexUpdateRecord(Ndb*, } // Define primary keys - for(int a = 0; a<tab.getNoOfColumns(); a++){ + for(a = 0; a<tab.getNoOfColumns(); a++){ if (tab.getColumn(a)->getPrimaryKey() == true){ if(equalForAttr(pOp, a, r+recordNo) != 0){ ERR(pTrans->getNdbError()); @@ -780,7 +755,7 @@ HugoOperations::indexUpdateRecord(Ndb*, } // Define attributes to update - for(int a = 0; a<tab.getNoOfColumns(); a++){ + for(a = 0; a<tab.getNoOfColumns(); a++){ if (tab.getColumn(a)->getPrimaryKey() == false){ if(setValueForAttr(pOp, a, recordNo+r, updatesValue ) != 0){ ERR(pTrans->getNdbError()); @@ -791,3 +766,35 @@ HugoOperations::indexUpdateRecord(Ndb*, } return NDBT_OK; } + +int +HugoOperations::scanReadRecords(Ndb* pNdb, NdbScanOperation::LockMode lm, + int records){ + + allocRows(records); + NdbScanOperation * pOp = pTrans->getNdbScanOperation(tab.getName()); + + if(!pOp) + return -1; + + NdbResultSet * rs = pOp->readTuples(lm, 1, 1); + + if(!rs){ + return -1; + } + + for(int a = 0; a<tab.getNoOfColumns(); a++){ + if((rows[0]->attributeStore(a) = + pOp->getValue(tab.getColumn(a)->getName())) == 0) { + ERR(pTrans->getNdbError()); + return NDBT_FAILED; + } + } + + RsPair p = {rs, records}; + m_result_sets.push_back(p); + + return 0; +} + +template class Vector<HugoOperations::RsPair>; diff --git a/ndb/test/src/HugoTransactions.cpp b/ndb/test/src/HugoTransactions.cpp index 7f12484ddc8..05039562c76 100644 --- a/ndb/test/src/HugoTransactions.cpp +++ b/ndb/test/src/HugoTransactions.cpp @@ -46,9 +46,9 @@ HugoTransactions::scanReadRecords(Ndb* pNdb, int retryAttempt = 0; const int retryMax = 100; - int check; + int check, a; 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; @@ -97,7 +96,7 @@ HugoTransactions::scanReadRecords(Ndb* pNdb, return NDBT_FAILED; } - for(int a = 0; a<tab.getNoOfColumns(); a++){ + for(a = 0; a<tab.getNoOfColumns(); a++){ if((row.attributeStore(a) = pOp->getValue(tab.getColumn(a)->getName())) == 0) { ERR(pTrans->getNdbError()); @@ -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; a<tab.getNoOfColumns(); a++){ - if (tab.getColumn(a)->getPrimaryKey() == 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,9 +215,12 @@ 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; + int check, a; NdbConnection *pTrans; NdbOperation *pOp; @@ -371,7 +269,7 @@ HugoTransactions::scanUpdateRecords1(Ndb* pNdb, } // Read all attributes from this table - for(int a=0; a<tab.getNoOfColumns(); a++){ + for(a=0; a<tab.getNoOfColumns(); a++){ if((row.attributeStore(a) = pOp->getValue(tab.getColumn(a)->getName())) == NULL){ ERR(pTrans->getNdbError()); pNdb->closeTransaction(pTrans); @@ -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,9 +382,12 @@ 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; + int check, a; NdbConnection *pTrans; NdbOperation *pOp; @@ -535,7 +436,7 @@ HugoTransactions::scanUpdateRecords2(Ndb* pNdb, } // Read all attributes from this table - for(int a=0; a<tab.getNoOfColumns(); a++){ + for(a=0; a<tab.getNoOfColumns(); a++){ if((row.attributeStore(a) = pOp->getValue(tab.getColumn(a)->getName())) == NULL){ ERR(pTrans->getNdbError()); pNdb->closeTransaction(pTrans); @@ -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; a<tab.getNoOfColumns(); a++){ - if (tab.getColumn(a)->getPrimaryKey() == 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, @@ -678,7 +553,7 @@ HugoTransactions::scanUpdateRecords3(Ndb* pNdb, int parallelism){ int retryAttempt = 0; const int retryMax = 100; - int check; + int check, a; NdbConnection *pTrans; NdbScanOperation *pOp; @@ -717,7 +592,7 @@ HugoTransactions::scanUpdateRecords3(Ndb* pNdb, } // Read all attributes from this table - for(int a=0; a<tab.getNoOfColumns(); a++){ + for(a=0; a<tab.getNoOfColumns(); a++){ if((row.attributeStore(a) = pOp->getValue(tab.getColumn(a)->getName())) == NULL){ ERR(pTrans->getNdbError()); pNdb->closeTransaction(pTrans); @@ -759,8 +634,7 @@ HugoTransactions::scanUpdateRecords3(Ndb* pNdb, } const int updates = calc.getUpdatesValue(&row) + 1; const int r = calc.getIdValue(&row); - - for(int a = 0; a<tab.getNoOfColumns(); a++){ + for(a = 0; a<tab.getNoOfColumns(); a++){ if (tab.getColumn(a)->getPrimaryKey() == false){ if(setValueForAttr(pUp, a, r, updates ) != 0){ ERR(pTrans->getNdbError()); @@ -780,7 +654,7 @@ HugoTransactions::scanUpdateRecords3(Ndb* pNdb, if(check != -1){ check = pTrans->execute(Commit); - pTrans->releaseCompletedOperations(); + pTrans->restart(); } const NdbError err = pTrans->getNdbError(); @@ -794,7 +668,7 @@ HugoTransactions::scanUpdateRecords3(Ndb* pNdb, return NDBT_FAILED; } } - + const NdbError err = pTrans->getNdbError(); if( check == -1 ) { pNdb->closeTransaction(pTrans); @@ -819,12 +693,14 @@ HugoTransactions::loadTable(Ndb* pNdb, int records, int batch, bool allowConstraintViolation, - int doSleep){ - int check; + int doSleep, + bool oneTrans){ + int check, a; int retryAttempt = 0; int retryMax = 5; NdbConnection *pTrans; NdbOperation *pOp; + bool first_batch = true; const int org = batch; const int cols = tab.getNoOfColumns(); @@ -833,7 +709,7 @@ HugoTransactions::loadTable(Ndb* pNdb, batch = (batch * 256); // -> 512 -> 65536k per commit batch = batch/bytes; // batch = batch == 0 ? 1 : batch; - + if(batch != org){ g_info << "batch = " << org << " rowsize = " << bytes << " -> rows/commit = " << batch << endl; @@ -841,7 +717,7 @@ HugoTransactions::loadTable(Ndb* pNdb, g_info << "|- Inserting records..." << endl; for (int c=0 ; c<records ; ){ - + bool closeTrans; if (retryAttempt >= retryMax){ g_info << "Record " << c << " could not be inserted, has retried " << retryAttempt << " times " << endl; @@ -852,19 +728,22 @@ HugoTransactions::loadTable(Ndb* pNdb, if (doSleep > 0) NdbSleep_MilliSleep(doSleep); - pTrans = pNdb->startTransaction(); - - if (pTrans == NULL) { - const NdbError err = pNdb->getNdbError(); + if (first_batch || !oneTrans) { + first_batch = false; + pTrans = pNdb->startTransaction(); + + if (pTrans == NULL) { + const NdbError err = pNdb->getNdbError(); - if (err.status == NdbError::TemporaryError){ - ERR(err); - NdbSleep_MilliSleep(50); - retryAttempt++; - continue; + if (err.status == NdbError::TemporaryError){ + ERR(err); + NdbSleep_MilliSleep(50); + retryAttempt++; + continue; + } + ERR(err); + return NDBT_FAILED; } - ERR(err); - return NDBT_FAILED; } for(int b = 0; b < batch && c+b<records; b++){ @@ -884,7 +763,7 @@ HugoTransactions::loadTable(Ndb* pNdb, } // Set a calculated value for each attribute in this table - for (int a = 0; a<tab.getNoOfColumns(); a++){ + for (a = 0; a<tab.getNoOfColumns(); a++){ if(setValueForAttr(pOp, a, c+b, 0 ) != 0){ ERR(pTrans->getNdbError()); pNdb->closeTransaction(pTrans); @@ -894,7 +773,13 @@ HugoTransactions::loadTable(Ndb* pNdb, } // Execute the transaction and insert the record - check = pTrans->execute( Commit ); + if (!oneTrans || (c + batch) >= records) { + closeTrans = true; + check = pTrans->execute( Commit ); + } else { + closeTrans = false; + check = pTrans->execute( NoCommit ); + } if(check == -1 ) { const NdbError err = pTrans->getNdbError(); pNdb->closeTransaction(pTrans); @@ -937,8 +822,10 @@ HugoTransactions::loadTable(Ndb* pNdb, break; } } - else{ - pNdb->closeTransaction(pTrans); + else{ + if (closeTrans) { + pNdb->closeTransaction(pTrans); + } } // Step to next record @@ -951,7 +838,7 @@ HugoTransactions::loadTable(Ndb* pNdb, int HugoTransactions::fillTable(Ndb* pNdb, int batch){ - int check; + int check, a, b; int retryAttempt = 0; int retryMax = 5; NdbConnection *pTrans; @@ -982,7 +869,7 @@ HugoTransactions::fillTable(Ndb* pNdb, return NDBT_FAILED; } - for(int b = 0; b < batch; b++){ + for(b = 0; b < batch; b++){ pOp = pTrans->getNdbOperation(tab.getName()); if (pOp == NULL) { @@ -999,7 +886,7 @@ HugoTransactions::fillTable(Ndb* pNdb, } // Set a calculated value for each attribute in this table - for (int a = 0; a<tab.getNoOfColumns(); a++){ + for (a = 0; a<tab.getNoOfColumns(); a++){ if(setValueForAttr(pOp, a, c+b, 0 ) != 0){ ERR(pTrans->getNdbError()); pNdb->closeTransaction(pTrans); @@ -1138,7 +1025,7 @@ int HugoTransactions::eventOperation(Ndb* pNdb, void* pstats, int records) { int myXXXXX = XXXXX++; - + Uint32 i; const char function[] = "HugoTransactions::eventOperation: "; struct receivedEvent* recInsertEvent; NdbAutoObjArrayPtr<struct receivedEvent> @@ -1155,7 +1042,7 @@ HugoTransactions::eventOperation(Ndb* pNdb, void* pstats, stats.n_duplicates = 0; stats.n_inconsistent_gcis = 0; - for (int i = 0; i < records; i++) { + for (i = 0; i < records; i++) { recInsertEvent[i].pk = 0xFFFFFFFF; recInsertEvent[i].count = 0; recInsertEvent[i].event = 0xFFFFFFFF; @@ -1263,7 +1150,7 @@ HugoTransactions::eventOperation(Ndb* pNdb, void* pstats, } g_info << "overrun " << overrun << " pk " << pk; - for (int i = 1; i < noEventColumnName; i++) { + for (i = 1; i < noEventColumnName; i++) { if (recAttr[i]->isNULL() >= 0) { // we have a value g_info << " post[" << i << "]="; if (recAttr[i]->isNULL() == 0) // we have a non-null value @@ -1306,7 +1193,7 @@ HugoTransactions::eventOperation(Ndb* pNdb, void* pstats, if (stats.n_updates > 0) { stats.n_consecutive++; } - for (Uint32 i = 0; i < (Uint32)records/3; i++) { + for (i = 0; i < (Uint32)records/3; i++) { if (recInsertEvent[i].pk != i) { stats.n_consecutive ++; ndbout << "missing insert pk " << i << endl; @@ -1345,7 +1232,7 @@ HugoTransactions::pkReadRecords(Ndb* pNdb, int r = 0; int retryAttempt = 0; const int retryMax = 100; - int check; + int check, a; NdbConnection *pTrans; NdbOperation *pOp; @@ -1397,7 +1284,7 @@ HugoTransactions::pkReadRecords(Ndb* pNdb, } // Define primary keys - for(int a = 0; a<tab.getNoOfColumns(); a++){ + for(a = 0; a<tab.getNoOfColumns(); a++){ if (tab.getColumn(a)->getPrimaryKey() == true){ if(equalForAttr(pOp, a, r+b) != 0){ ERR(pTrans->getNdbError()); @@ -1408,7 +1295,7 @@ HugoTransactions::pkReadRecords(Ndb* pNdb, } // Define attributes to read - for(int a = 0; a<tab.getNoOfColumns(); a++){ + for(a = 0; a<tab.getNoOfColumns(); a++){ if((rows[b]->attributeStore(a) = pOp->getValue(tab.getColumn(a)->getName())) == 0) { ERR(pTrans->getNdbError()); @@ -1471,13 +1358,13 @@ HugoTransactions::pkUpdateRecords(Ndb* pNdb, int r = 0; int retryAttempt = 0; const int retryMax = 100; - int check; + int check, a, b; NdbConnection *pTrans; NdbOperation *pOp; allocRows(batch); - g_info << "|- Updating records..." << endl; + g_info << "|- Updating records (batch=" << batch << ")..." << endl; while (r < records){ if (retryAttempt >= retryMax){ @@ -1503,7 +1390,7 @@ HugoTransactions::pkUpdateRecords(Ndb* pNdb, return NDBT_FAILED; } - for(int b = 0; b<batch && (r+b) < records; b++){ + for(b = 0; b<batch && (r+b) < records; b++){ pOp = pTrans->getNdbOperation(tab.getName()); if (pOp == NULL) { ERR(pTrans->getNdbError()); @@ -1519,7 +1406,7 @@ HugoTransactions::pkUpdateRecords(Ndb* pNdb, } // Define primary keys - for(int a = 0; a<tab.getNoOfColumns(); a++){ + for(a = 0; a<tab.getNoOfColumns(); a++){ if (tab.getColumn(a)->getPrimaryKey() == true){ if(equalForAttr(pOp, a, r+b) != 0){ ERR(pTrans->getNdbError()); @@ -1530,7 +1417,7 @@ HugoTransactions::pkUpdateRecords(Ndb* pNdb, } // Define attributes to read - for(int a = 0; a<tab.getNoOfColumns(); a++){ + for(a = 0; a<tab.getNoOfColumns(); a++){ if((rows[b]->attributeStore(a) = pOp->getValue(tab.getColumn(a)->getName())) == 0) { ERR(pTrans->getNdbError()); @@ -1556,7 +1443,7 @@ HugoTransactions::pkUpdateRecords(Ndb* pNdb, return NDBT_FAILED; } - for(int b = 0; b<batch && (b+r)<records; b++){ + for(b = 0; b<batch && (b+r)<records; b++){ if (calc.verifyRowValues(rows[b]) != 0){ pNdb->closeTransaction(pTrans); return NDBT_FAILED; @@ -1579,7 +1466,7 @@ HugoTransactions::pkUpdateRecords(Ndb* pNdb, return NDBT_FAILED; } - for(int a = 0; a<tab.getNoOfColumns(); a++){ + for(a = 0; a<tab.getNoOfColumns(); a++){ if (tab.getColumn(a)->getPrimaryKey() == true){ if(equalForAttr(pUpdOp, a, r+b) != 0){ ERR(pTrans->getNdbError()); @@ -1589,7 +1476,7 @@ HugoTransactions::pkUpdateRecords(Ndb* pNdb, } } - for(int a = 0; a<tab.getNoOfColumns(); a++){ + for(a = 0; a<tab.getNoOfColumns(); a++){ if (tab.getColumn(a)->getPrimaryKey() == false){ if(setValueForAttr(pUpdOp, a, r+b, updates ) != 0){ ERR(pTrans->getNdbError()); @@ -1639,7 +1526,7 @@ HugoTransactions::pkInterpretedUpdateRecords(Ndb* pNdb, int r = 0; int retryAttempt = 0; const int retryMax = 100; - int check; + int check, a; NdbConnection *pTrans; while (r < records){ @@ -1679,7 +1566,7 @@ HugoTransactions::pkInterpretedUpdateRecords(Ndb* pNdb, } // Define primary keys - for(int a = 0; a<tab.getNoOfColumns(); a++){ + for(a = 0; a<tab.getNoOfColumns(); a++){ if (tab.getColumn(a)->getPrimaryKey() == true){ if(equalForAttr(pOp, a, r) != 0){ ERR(pTrans->getNdbError()); @@ -1690,7 +1577,7 @@ HugoTransactions::pkInterpretedUpdateRecords(Ndb* pNdb, } // Read update value - for(int a = 0; a<tab.getNoOfColumns(); a++){ + for(a = 0; a<tab.getNoOfColumns(); a++){ if (calc.isUpdateCol(a) == true){ if((row.attributeStore(a) = pOp->getValue(tab.getColumn(a)->getName())) == 0) { @@ -1735,7 +1622,7 @@ HugoTransactions::pkInterpretedUpdateRecords(Ndb* pNdb, } // PKs - for(int a = 0; a<tab.getNoOfColumns(); a++){ + for(a = 0; a<tab.getNoOfColumns(); a++){ if (tab.getColumn(a)->getPrimaryKey() == true){ if(equalForAttr(pUpdOp, a, r) != 0){ ERR(pTrans->getNdbError()); @@ -1746,7 +1633,7 @@ HugoTransactions::pkInterpretedUpdateRecords(Ndb* pNdb, } // Update col - for(int a = 0; a<tab.getNoOfColumns(); a++){ + for(a = 0; a<tab.getNoOfColumns(); a++){ if ((tab.getColumn(a)->getPrimaryKey() == false) && (calc.isUpdateCol(a) == true)){ @@ -1763,7 +1650,7 @@ HugoTransactions::pkInterpretedUpdateRecords(Ndb* pNdb, } // Remaining attributes - for(int a = 0; a<tab.getNoOfColumns(); a++){ + for(a = 0; a<tab.getNoOfColumns(); a++){ if ((tab.getColumn(a)->getPrimaryKey() == false) && (calc.isUpdateCol(a) == false)){ if(setValueForAttr(pUpdOp, a, r, updates ) != 0){ @@ -1818,7 +1705,7 @@ HugoTransactions::pkDelRecords(Ndb* pNdb, int r = 0; int retryAttempt = 0; const int retryMax = 100; - int check; + int check, a; NdbConnection *pTrans; NdbOperation *pOp; @@ -1863,7 +1750,7 @@ HugoTransactions::pkDelRecords(Ndb* pNdb, } // Define primary keys - for(int a = 0; a<tab.getNoOfColumns(); a++){ + for(a = 0; a<tab.getNoOfColumns(); a++){ if (tab.getColumn(a)->getPrimaryKey() == true){ if(equalForAttr(pOp, a, r) != 0){ ERR(pTrans->getNdbError()); @@ -1933,7 +1820,7 @@ HugoTransactions::lockRecords(Ndb* pNdb, int r = 0; int retryAttempt = 0; const int retryMax = 100; - int check; + int check, a, b; NdbConnection *pTrans; NdbOperation *pOp; @@ -1970,7 +1857,7 @@ HugoTransactions::lockRecords(Ndb* pNdb, return NDBT_FAILED; } - for(int b = 0; (b<lockBatch) && (r+b < records); b++){ + for(b = 0; (b<lockBatch) && (r+b < records); b++){ pOp = pTrans->getNdbOperation(tab.getName()); if (pOp == NULL) { ERR(pTrans->getNdbError()); @@ -1986,7 +1873,7 @@ HugoTransactions::lockRecords(Ndb* pNdb, } // Define primary keys - for(int a = 0; a<tab.getNoOfColumns(); a++){ + for(a = 0; a<tab.getNoOfColumns(); a++){ if (tab.getColumn(a)->getPrimaryKey() == true){ if(equalForAttr(pOp, a, r+b) != 0){ ERR(pTrans->getNdbError()); @@ -1997,7 +1884,7 @@ HugoTransactions::lockRecords(Ndb* pNdb, } // Define attributes to read - for(int a = 0; a<tab.getNoOfColumns(); a++){ + for(a = 0; a<tab.getNoOfColumns(); a++){ if((rows[b]->attributeStore(a) = pOp->getValue(tab.getColumn(a)->getName())) == 0) { ERR(pTrans->getNdbError()); @@ -2080,10 +1967,10 @@ HugoTransactions::indexReadRecords(Ndb* pNdb, int r = 0; int retryAttempt = 0; const int retryMax = 100; - int check; + int check, a; NdbConnection *pTrans; NdbOperation *pOp; - NdbScanOperation *sOp; + NdbIndexScanOperation *sOp; NdbResultSet * rs; const NdbDictionary::Index* pIndex @@ -2134,7 +2021,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); @@ -2152,7 +2039,7 @@ HugoTransactions::indexReadRecords(Ndb* pNdb, } // Define primary keys - for(int a = 0; a<tab.getNoOfColumns(); a++){ + for(a = 0; a<tab.getNoOfColumns(); a++){ if (tab.getColumn(a)->getPrimaryKey() == true){ if(equalForAttr(pOp, a, r+b) != 0){ ERR(pTrans->getNdbError()); @@ -2163,7 +2050,7 @@ HugoTransactions::indexReadRecords(Ndb* pNdb, } // Define attributes to read - for(int a = 0; a<tab.getNoOfColumns(); a++){ + for(a = 0; a<tab.getNoOfColumns(); a++){ if((rows[b]->attributeStore(a) = pOp->getValue(tab.getColumn(a)->getName())) == 0) { ERR(pTrans->getNdbError()); @@ -2231,7 +2118,7 @@ HugoTransactions::indexUpdateRecords(Ndb* pNdb, int r = 0; int retryAttempt = 0; const int retryMax = 100; - int check; + int check, a, b; NdbConnection *pTrans; NdbOperation *pOp; NdbScanOperation * sOp; @@ -2268,7 +2155,7 @@ HugoTransactions::indexUpdateRecords(Ndb* pNdb, return NDBT_FAILED; } - for(int b = 0; b<batchsize && (b+r)<records; b++){ + for(b = 0; b<batchsize && (b+r)<records; b++){ if(!ordered){ pOp = pTrans->getNdbIndexOperation(idxName, tab.getName()); if (pOp == NULL) { @@ -2284,7 +2171,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); @@ -2296,7 +2183,7 @@ HugoTransactions::indexUpdateRecords(Ndb* pNdb, } // Define primary keys - for(int a = 0; a<tab.getNoOfColumns(); a++){ + for(a = 0; a<tab.getNoOfColumns(); a++){ if (tab.getColumn(a)->getPrimaryKey() == true){ if(equalForAttr(pOp, a, r+b) != 0){ ERR(pTrans->getNdbError()); @@ -2307,7 +2194,7 @@ HugoTransactions::indexUpdateRecords(Ndb* pNdb, } // Define attributes to read - for(int a = 0; a<tab.getNoOfColumns(); a++){ + for(a = 0; a<tab.getNoOfColumns(); a++){ if((rows[b]->attributeStore(a) = pOp->getValue(tab.getColumn(a)->getName())) == 0) { ERR(pTrans->getNdbError()); @@ -2338,7 +2225,7 @@ HugoTransactions::indexUpdateRecords(Ndb* pNdb, return NDBT_FAILED; } - for(int b = 0; b<batchsize && (b+r)<records; b++){ + for(b = 0; b<batchsize && (b+r)<records; b++){ if (calc.verifyRowValues(rows[b]) != 0){ pNdb->closeTransaction(pTrans); return NDBT_FAILED; @@ -2367,7 +2254,7 @@ HugoTransactions::indexUpdateRecords(Ndb* pNdb, } if(!ordered){ - for(int a = 0; a<tab.getNoOfColumns(); a++){ + for(a = 0; a<tab.getNoOfColumns(); a++){ if (tab.getColumn(a)->getPrimaryKey() == true){ if(equalForAttr(pUpdOp, a, r+b) != 0){ ERR(pTrans->getNdbError()); @@ -2378,7 +2265,7 @@ HugoTransactions::indexUpdateRecords(Ndb* pNdb, } } - for(int a = 0; a<tab.getNoOfColumns(); a++){ + for(a = 0; a<tab.getNoOfColumns(); a++){ if (tab.getColumn(a)->getPrimaryKey() == false){ if(setValueForAttr(pUpdOp, a, r+b, updates ) != 0){ ERR(pTrans->getNdbError()); @@ -2415,4 +2302,4 @@ HugoTransactions::indexUpdateRecords(Ndb* pNdb, return NDBT_OK; } - +template class Vector<NDBT_ResultRow*>; diff --git a/ndb/test/src/NDBT_Table.cpp b/ndb/test/src/NDBT_Table.cpp index 485377e690a..d283cdf5912 100644 --- a/ndb/test/src/NDBT_Table.cpp +++ b/ndb/test/src/NDBT_Table.cpp @@ -19,35 +19,6 @@ #include <NDBT.hpp> class NdbOut& -operator <<(class NdbOut& ndbout, const NDBT_Attribute & attr){ - - NdbDictionary::Column::Type type = attr.getType(); - - ndbout << attr.getName() << " " << type; - - switch(type){ - case NdbDictionary::Column::Decimal: - ndbout << "(" << attr.getScale() << ", " << attr.getPrecision() << ")"; - break; - default: - break; - } - - if(attr.getLength() != 1) - ndbout << "[" << attr.getLength() << "]"; - - if(attr.getNullable()) - ndbout << " NULL"; - else - ndbout << " NOT NULL"; - - if(attr.getPrimaryKey()) - ndbout << " PRIMARY KEY"; - - return ndbout; -} - -class NdbOut& operator <<(class NdbOut& ndbout, const NDBT_Table & tab) { ndbout << "-- " << tab.getName() << " --" << endl; diff --git a/ndb/test/src/NDBT_Tables.cpp b/ndb/test/src/NDBT_Tables.cpp index 548e755a3fb..ff6db3e892c 100644 --- a/ndb/test/src/NDBT_Tables.cpp +++ b/ndb/test/src/NDBT_Tables.cpp @@ -297,7 +297,7 @@ NDBT_Table T14("T14", sizeof(T14Attribs)/sizeof(NDBT_Attribute), T14Attribs); */ static const -NDBT_Attribute C2_PORTS_Attribs[] = { +NDBT_Attribute I1_Cols[] = { NDBT_Attribute("ID", NdbDictionary::Column::Unsigned, true), NDBT_Attribute("PORT", NdbDictionary::Column::Char, 16, true), NDBT_Attribute("ACCESSNODE", NdbDictionary::Column::Char, 16, true), @@ -310,11 +310,19 @@ NDBT_Attribute C2_PORTS_Attribs[] = { }; static -NDBT_Table C2_PORTS("C2_PORTS", sizeof(C2_PORTS_Attribs)/sizeof(NDBT_Attribute), C2_PORTS_Attribs); +const +char* I1_Indexes[] = { + "UNIQUE", "ID", "PORT", "ACCESSNODE", "POP", "PORTSTATE", 0, + 0 +}; + +static +NDBT_Table I1("I1", sizeof(I1_Cols)/sizeof(NDBT_Attribute), I1_Cols + );// ,I1_Indexes); static const -NDBT_Attribute C2_SERVICES_Attribs[] = { +NDBT_Attribute I2_Cols[] = { NDBT_Attribute("ID", NdbDictionary::Column::Unsigned, true), NDBT_Attribute("PORT", NdbDictionary::Column::Char, 16, true), NDBT_Attribute("ACCESSNODE", NdbDictionary::Column::Char, 16, true), @@ -331,12 +339,20 @@ NDBT_Attribute C2_SERVICES_Attribs[] = { NDBT_Attribute("UPDATES", NdbDictionary::Column::Unsigned) }; +const +char* I2_Indexes[] = { + "ORDERED", "CUSTOMER_ID", 0, + "ORDERED", "NUM_IP", 0, + 0 +}; + static -NDBT_Table C2_SERVICES("C2_SERVICES", sizeof(C2_SERVICES_Attribs)/sizeof(NDBT_Attribute), C2_SERVICES_Attribs); +NDBT_Table I2("I2", sizeof(I2_Cols)/sizeof(NDBT_Attribute), I2_Cols + );//, I2_Indexes); static const -NDBT_Attribute C2_CLIENTS_Attribs[] = { +NDBT_Attribute I3_Cols[] = { NDBT_Attribute("ID", NdbDictionary::Column::Unsigned, true), NDBT_Attribute("PORT", NdbDictionary::Column::Char, 16), // SI2 NDBT_Attribute("ACCESSNODE", NdbDictionary::Column::Char, 16), // SI2 @@ -355,8 +371,17 @@ NDBT_Attribute C2_CLIENTS_Attribs[] = { NDBT_Attribute("UPDATES", NdbDictionary::Column::Unsigned) }; +const +char* I3_Indexes[] = { + "UNIQUE", "ID", 0, + "ORDERED", "MAC", 0, + "ORDERED", "GW", 0, + 0 +}; + static -NDBT_Table C2_CLIENTS("C2_CLIENTS", sizeof(C2_CLIENTS_Attribs)/sizeof(NDBT_Attribute), C2_CLIENTS_Attribs); +NDBT_Table I3("I3", sizeof(I3_Cols)/sizeof(NDBT_Attribute), I3_Cols + ); // ,I3_Indexes); // Define array with pointer to all tables static @@ -377,10 +402,23 @@ NDBT_Table *test_tables[]= &T12, &T13, &T14, - &C2_PORTS, - &C2_SERVICES, - &C2_CLIENTS + &I1, + &I2, + &I3 +}; + +struct NDBT_IndexList { + const char * m_table; + const char ** m_indexes; +}; +static +const +NDBT_IndexList indexes[] = { + "I1", I1_Indexes, + "I2", I2_Indexes, + "I3", I3_Indexes, + 0, 0 }; static @@ -430,7 +468,7 @@ NDBT_Table F2("F2", sizeof(F2Attribs)/sizeof(NDBT_Attribute), F2Attribs); /* F3 * - * Error: Too many primary keys defined, 16 is max? + * Error: Too many primary keys defined, 32 is max */ static const @@ -452,10 +490,26 @@ NDBT_Attribute F3Attribs[] = { NDBT_Attribute("KOL15", NdbDictionary::Column::Unsigned, 1, true), NDBT_Attribute("KOL16", NdbDictionary::Column::Unsigned, 1, true), NDBT_Attribute("KOL17", NdbDictionary::Column::Unsigned, 1, true), - NDBT_Attribute("KOL20", NdbDictionary::Column::Unsigned), - NDBT_Attribute("KOL30", NdbDictionary::Column::Unsigned), + NDBT_Attribute("KOL18", NdbDictionary::Column::Unsigned, 1, true), + NDBT_Attribute("KOL19", NdbDictionary::Column::Unsigned, 1, true), + NDBT_Attribute("KOL20", NdbDictionary::Column::Unsigned, 1, true), + NDBT_Attribute("KOL21", NdbDictionary::Column::Unsigned, 1, true), + NDBT_Attribute("KOL22", NdbDictionary::Column::Unsigned, 1, true), + NDBT_Attribute("KOL23", NdbDictionary::Column::Unsigned, 1, true), + NDBT_Attribute("KOL24", NdbDictionary::Column::Unsigned, 1, true), + NDBT_Attribute("KOL25", NdbDictionary::Column::Unsigned, 1, true), + NDBT_Attribute("KOL26", NdbDictionary::Column::Unsigned, 1, true), + NDBT_Attribute("KOL27", NdbDictionary::Column::Unsigned, 1, true), + NDBT_Attribute("KOL28", NdbDictionary::Column::Unsigned, 1, true), + NDBT_Attribute("KOL29", NdbDictionary::Column::Unsigned, 1, true), + NDBT_Attribute("KOL30", NdbDictionary::Column::Unsigned, 1, true), + NDBT_Attribute("KOL31", NdbDictionary::Column::Unsigned, 1, true), + NDBT_Attribute("KOL32", NdbDictionary::Column::Unsigned, 1, true), + NDBT_Attribute("KOL33", NdbDictionary::Column::Unsigned, 1, true), NDBT_Attribute("KOL40", NdbDictionary::Column::Unsigned), - NDBT_Attribute("KOL50", NdbDictionary::Column::Unsigned) + NDBT_Attribute("KOL50", NdbDictionary::Column::Unsigned), + NDBT_Attribute("KOL60", NdbDictionary::Column::Unsigned), + NDBT_Attribute("KOL70", NdbDictionary::Column::Unsigned) }; static @@ -678,17 +732,18 @@ NdbDictionary::Table* NDBT_Tables::getTable(const char* _nam){ // Search tables list to find a table NDBT_Table* tab = NULL; - for (int i=0; i<numTestTables; i++){ + int i; + for (i=0; i<numTestTables; i++){ if (strcmp(test_tables[i]->getName(), _nam) == 0){ return test_tables[i]; } } - for (int i=0; i<numFailTables; i++){ + for (i=0; i<numFailTables; i++){ if (strcmp(fail_tables[i]->getName(), _nam) == 0){ return fail_tables[i]; } } - for (int i=0; i<numUtilTables; i++){ + for (i=0; i<numUtilTables; i++){ if (strcmp(util_tables[i]->getName(), _nam) == 0){ return util_tables[i]; } @@ -746,26 +801,13 @@ NDBT_Tables::getNumTables(){ int NDBT_Tables::createAllTables(Ndb* pNdb, bool _temp, bool existsOk){ - + for (int i=0; i < NDBT_Tables::getNumTables(); i++){ - - const NdbDictionary::Table* tab = NDBT_Tables::getTable(i); - if (tab == NULL){ - return NDBT_ProgramExit(NDBT_FAILED); - } - - // Set temporary table - NdbDictionary::Table tmpTab(* tab); - tmpTab.setStoredTable(_temp? 0 : 1); - - int r = pNdb->getDictionary()->createTable(tmpTab); - int err = pNdb->getDictionary()->getNdbError().code; - if(r == -1){ - if (existsOk && err == 721) - ; - else { - return NDBT_FAILED; - } + pNdb->getDictionary()->dropTable(NDBT_Tables::getTable(i)->getName()); + int ret= createTable(pNdb, + NDBT_Tables::getTable(i)->getName(), _temp, existsOk); + if(ret){ + return ret; } } return NDBT_OK; @@ -777,7 +819,8 @@ NDBT_Tables::createAllTables(Ndb* pNdb){ } int -NDBT_Tables::createTable(Ndb* pNdb, const char* _name, bool _temp){ +NDBT_Tables::createTable(Ndb* pNdb, const char* _name, bool _temp, + bool existsOk){ const NdbDictionary::Table* tab = NDBT_Tables::getTable(_name); if (tab == NULL){ @@ -787,10 +830,61 @@ NDBT_Tables::createTable(Ndb* pNdb, const char* _name, bool _temp){ return NDBT_WRONGARGS; } - NdbDictionary::Table tmpTab(* tab); - tmpTab.setStoredTable(_temp ? 0 : 1); + int r = 0; + do { + NdbDictionary::Table tmpTab(* tab); + tmpTab.setStoredTable(_temp ? 0 : 1); + + r = pNdb->getDictionary()->createTable(tmpTab); + if(r == -1){ + if(!existsOk){ + ndbout << "Error: " << pNdb->getDictionary()->getNdbError() << endl; + break; + } + if(pNdb->getDictionary()->getNdbError().code != 721){ + ndbout << "Error: " << pNdb->getDictionary()->getNdbError() << endl; + break; + } + r = 0; + } + + Uint32 i = 0; + for(i = 0; indexes[i].m_table != 0; i++){ + if(strcmp(indexes[i].m_table, _name) != 0) + continue; + Uint32 j = 0; + while(indexes[i].m_indexes[j] != 0){ + NdbDictionary::Index tmpIndx; + BaseString name; + name.assfmt("%s$NDBT_IDX%d", _name, j); + tmpIndx.setName(name.c_str()); + tmpIndx.setTable(_name); + bool logging = !_temp; + if(strcmp(indexes[i].m_indexes[j], "ORDERED") == 0){ + logging = false; + tmpIndx.setType(NdbDictionary::Index::OrderedIndex); + } else if(strcmp(indexes[i].m_indexes[j], "UNIQUE") == 0){ + tmpIndx.setType(NdbDictionary::Index::UniqueHashIndex); + } else { + ndbout << "Unknown index type"; + abort(); + } + tmpIndx.setLogging(logging); + + j++; + while(indexes[i].m_indexes[j] != 0){ + tmpIndx.addIndexColumn(indexes[i].m_indexes[j]); + j++; + } + j++; + if(pNdb->getDictionary()->createIndex(tmpIndx) != 0){ + ndbout << pNdb->getDictionary()->getNdbError() << endl; + return NDBT_FAILED; + } + } + } + } while(false); - int r = pNdb->getDictionary()->createTable(tmpTab); return r; } @@ -815,7 +909,7 @@ NDBT_Tables::dropAllTables(Ndb* pNdb){ int NDBT_Tables::print(const char * _name){ - const NdbDictionary::Table* tab = NDBT_Tables::getTable(_name); + const NDBT_Table * tab = (const NDBT_Table*)NDBT_Tables::getTable(_name); if (tab == NULL){ ndbout << "Could not print table " << _name << ", it doesn't exist in list of tables " @@ -835,7 +929,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/NDBT_Test.cpp b/ndb/test/src/NDBT_Test.cpp index 4cd2c96486b..b1691c379a9 100644 --- a/ndb/test/src/NDBT_Test.cpp +++ b/ndb/test/src/NDBT_Test.cpp @@ -132,6 +132,17 @@ void NDBT_Context::setProperty(const char* _name, Uint32 _val){ assert(b == true); NdbMutex_Unlock(propertyMutexPtr); } +void +NDBT_Context::decProperty(const char * name){ + NdbMutex_Lock(propertyMutexPtr); + Uint32 val = 0; + if(props.get(name, &val)){ + assert(val > 0); + props.put(name, (val - 1), true); + } + NdbCondition_Broadcast(propertyCondPtr); + NdbMutex_Unlock(propertyMutexPtr); +} void NDBT_Context::setProperty(const char* _name, const char* _val){ NdbMutex_Lock(propertyMutexPtr); @@ -336,24 +347,24 @@ NDBT_TestCaseImpl1::NDBT_TestCaseImpl1(NDBT_TestSuite* psuite, NDBT_TestCaseImpl1::~NDBT_TestCaseImpl1(){ NdbCondition_Destroy(waitThreadsCondPtr); NdbMutex_Destroy(waitThreadsMutexPtr); - - for(size_t i = 0; i < initializers.size(); i++) + size_t i; + for(i = 0; i < initializers.size(); i++) delete initializers[i]; initializers.clear(); - for(size_t i = 0; i < verifiers.size(); i++) + for(i = 0; i < verifiers.size(); i++) delete verifiers[i]; verifiers.clear(); - for(size_t i = 0; i < finalizers.size(); i++) + for(i = 0; i < finalizers.size(); i++) delete finalizers[i]; finalizers.clear(); - for(size_t i = 0; i < steps.size(); i++) + for(i = 0; i < steps.size(); i++) delete steps[i]; steps.clear(); results.clear(); - for(size_t i = 0; i < testTables.size(); i++) + for(i = 0; i < testTables.size(); i++) delete testTables[i]; testTables.clear(); - for(size_t i = 0; i < testResults.size(); i++) + for(i = 0; i < testResults.size(); i++) delete testResults[i]; testResults.clear(); @@ -487,7 +498,8 @@ void NDBT_TestCaseImpl1::waitSteps(){ waitThreadsMutexPtr); unsigned completedSteps = 0; - for(unsigned i=0; i<steps.size(); i++){ + unsigned i; + for(i=0; i<steps.size(); i++){ if (results[i] != NORESULT){ completedSteps++; if (results[i] == NDBT_OK) @@ -501,7 +513,7 @@ void NDBT_TestCaseImpl1::waitSteps(){ NdbMutex_Unlock(waitThreadsMutexPtr); void *status; - for(unsigned i=0; i<steps.size();i++){ + for(i=0; i<steps.size();i++){ NdbThread_WaitFor(threads[i], &status); NdbThread_Destroy(&threads[i]); } @@ -633,12 +645,12 @@ int NDBT_TestCaseImpl1::runSteps(NDBT_Context* ctx){ numStepsOk = 0; numStepsFail = 0; numStepsCompleted = 0; - - for (unsigned i = 0; i < steps.size(); i++) + unsigned i; + for (i = 0; i < steps.size(); i++) startStepInThread(i, ctx); waitSteps(); - for(unsigned i = 0; i < steps.size(); i++) + for(i = 0; i < steps.size(); i++) if (results[i] != NDBT_OK) res = NDBT_FAILED; return res; @@ -808,18 +820,19 @@ void NDBT_TestSuite::execute(Ndb* ndb, const NdbDictionary::Table* pTab, const NdbDictionary::Table* pTab2 = pDict->getTable(pTab->getName()); if (createTable == true){ - if (pTab2 != 0 && !pTab->equal(* pTab2)){ + if(pTab2 != 0 && pDict->dropTable(pTab->getName()) != 0){ numTestsFail++; numTestsExecuted++; - g_err << "ERROR0: Failed to create table " << pTab->getName() << endl; + g_err << "ERROR0: Failed to drop table " << pTab->getName() << endl; tests[t]->saveTestResult(pTab, FAILED_TO_CREATE); continue; } - - if(pTab2 == 0 && pDict->createTable(* pTab) != 0){ + + if(NDBT_Tables::createTable(ndb, pTab->getName()) != 0){ numTestsFail++; numTestsExecuted++; - g_err << "ERROR1: Failed to create table " << pTab->getName() << endl; + g_err << "ERROR1: Failed to create table " << pTab->getName() + << pDict->getNdbError() << endl; tests[t]->saveTestResult(pTab, FAILED_TO_CREATE); continue; } @@ -994,6 +1007,7 @@ int NDBT_TestSuite::execute(int argc, const char** argv){ res = executeAll(_testname); } else { testSuiteTimer.doStart(); + Ndb ndb("TEST_DB"); ndb.init(); for(int i = optind; i<argc; i++){ executeOne(argv[i], _testname); } @@ -1091,20 +1105,20 @@ void NDBT_TestCaseImpl1::print(){ abort(); } } - - for(unsigned i=0; i<initializers.size(); i++){ + unsigned i; + for(i=0; i<initializers.size(); i++){ ndbout << "Initializers[" << i << "]: " << endl; initializers[i]->print(); } - for(unsigned i=0; i<steps.size(); i++){ + for(i=0; i<steps.size(); i++){ ndbout << "Step[" << i << "]: " << endl; steps[i]->print(); } - for(unsigned i=0; i<verifiers.size(); i++){ + for(i=0; i<verifiers.size(); i++){ ndbout << "Verifier[" << i << "]: " << endl; verifiers[i]->print(); } - for(unsigned i=0; i<finalizers.size(); i++){ + for(i=0; i<finalizers.size(); i++){ ndbout << "Finalizer[" << i << "]: " << endl; finalizers[i]->print(); } @@ -1116,6 +1130,11 @@ void NDBT_Step::print(){ } - - - +template class Vector<NDBT_TestCase*>; +template class Vector<NDBT_TestCaseResult*>; +template class Vector<NDBT_Step*>; +template class Vector<NdbThread*>; +template class Vector<NDBT_Verifier*>; +template class Vector<NDBT_Initializer*>; +template class Vector<NDBT_Finalizer*>; +template class Vector<const NdbDictionary::Table*>; diff --git a/ndb/test/src/NdbBackup.cpp b/ndb/test/src/NdbBackup.cpp index 169034e0c07..a40c6ba7d7c 100644 --- a/ndb/test/src/NdbBackup.cpp +++ b/ndb/test/src/NdbBackup.cpp @@ -69,17 +69,24 @@ NdbBackup::getFileSystemPathForNode(int _node_id){ /** * Fetch configuration from management server */ - ConfigRetriever cr; + ConfigRetriever cr(0, NODE_TYPE_API); + ndb_mgm_configuration * p = 0; - ndb_mgm_configuration * p = cr.getConfig(host, port, 0); - if(p == 0){ - const char * s = cr.getErrorString(); - if(s == 0) - s = "No error given!"; + BaseString tmp; tmp.assfmt("%s:%d", host.c_str(), port); + NdbMgmHandle handle = ndb_mgm_create_handle(); + if(handle == 0 || ndb_mgm_connect(handle, tmp.c_str()) != 0 || + (p = ndb_mgm_get_configuration(handle, 0)) == 0){ - ndbout << "Could not fetch configuration" << endl; - ndbout << s << endl; - return NULL; + const char * s = 0; + if(p == 0 && handle != 0){ + s = ndb_mgm_get_latest_error_msg(handle); + if(s == 0) + s = "No error given!"; + + ndbout << "Could not fetch configuration" << endl; + ndbout << s << endl; + return NULL; + } } /** @@ -90,7 +97,8 @@ NdbBackup::getFileSystemPathForNode(int _node_id){ ndbout << "Invalid configuration fetched, DB missing" << endl; return NULL; } - unsigned int type = 123456; + + unsigned int type = NODE_TYPE_DB + 1; if(iter.get(CFG_TYPE_OF_SECTION, &type) || type != NODE_TYPE_DB){ ndbout <<"type = " << type << endl; ndbout <<"Invalid configuration fetched, I'm wrong type of node" << endl; @@ -141,31 +149,18 @@ NdbBackup::execRestore(bool _restore_data, ndbout << "res: " << res << endl; -#if 0 - snprintf(buf, 255, "ndb_restore -c \"nodeid=%d;host=%s\" -n %d -b %d %s %s %s/BACKUP/BACKUP-%d", - ownNodeId, - addr, - _node_id, - _backup_id, - _restore_data?"-r":"", - _restore_meta?"-m":"", - path, - _backup_id); - + snprintf(buf, 255, "%sndb_restore -c \"host=%s\" -n %d -b %d %s %s .", +#if 1 + "", +#else + "valgrind --leak-check=yes -v " #endif - - snprintf(buf, 255, "ndb_restore -c \"nodeid=%d;host=%s\" -n %d -b %d %s %s .", - ownNodeId, - addr, + addr.c_str(), _node_id, _backup_id, _restore_data?"-r":"", _restore_meta?"-m":""); - // path, - // _backup_id); - - ndbout << "buf: "<< buf <<endl; res = system(buf); diff --git a/ndb/test/src/NdbRestarter.cpp b/ndb/test/src/NdbRestarter.cpp index b731cccb259..4d6d3ddc001 100644 --- a/ndb/test/src/NdbRestarter.cpp +++ b/ndb/test/src/NdbRestarter.cpp @@ -33,13 +33,11 @@ NdbRestarter::NdbRestarter(const char* _addr): connected(false), - addr(_addr), - host(NULL), port(-1), handle(NULL), m_config(0) { - if (addr == NULL){ + if (_addr == NULL){ LocalConfig lcfg; if(!lcfg.init()){ lcfg.printError(); @@ -48,32 +46,32 @@ NdbRestarter::NdbRestarter(const char* _addr): return; } - if (lcfg.items == 0){ + if (lcfg.ids.size() == 0){ g_err << "NdbRestarter - No management servers configured in local config file" << endl; return; } - for (int i = 0; i<lcfg.items; i++){ - MgmtSrvrId * m = lcfg.ids[i]; + for (int i = 0; i<lcfg.ids.size(); i++){ + MgmtSrvrId * m = &lcfg.ids[i]; switch(m->type){ case MgmId_TCP: char buf[255]; - snprintf(buf, 255, "%s:%d", m->data.tcp.remoteHost, m->data.tcp.port); - addr = strdup(buf); - host = strdup(m->data.tcp.remoteHost); - port = m->data.tcp.port; + snprintf(buf, 255, "%s:%d", m->name.c_str(), m->port); + addr.assign(buf); + host.assign(m->name.c_str()); + port = m->port; + return; break; case MgmId_File: break; default: break; } - if (addr != NULL) - break; } + } else { + addr.assign(_addr); } - } NdbRestarter::~NdbRestarter(){ @@ -398,10 +396,10 @@ NdbRestarter::connect(){ g_err << "handle == NULL" << endl; return -1; } - g_info << "Connecting to mgmsrv at " << addr << endl; - if (ndb_mgm_connect(handle, addr) == -1) { + g_info << "Connecting to mgmsrv at " << addr.c_str() << endl; + if (ndb_mgm_connect(handle, addr.c_str()) == -1) { MGMERR(handle); - g_err << "Connection to " << addr << " failed" << endl; + g_err << "Connection to " << addr.c_str() << " failed" << endl; return -1; } @@ -672,3 +670,5 @@ NdbRestarter::getConfig(){ m_config = ndb_mgm_get_configuration(handle, 0); return m_config; } + +template class Vector<ndb_mgm_node_state>; diff --git a/ndb/test/src/NdbRestarts.cpp b/ndb/test/src/NdbRestarts.cpp index f6a85d69fc2..b649a60d98b 100644 --- a/ndb/test/src/NdbRestarts.cpp +++ b/ndb/test/src/NdbRestarts.cpp @@ -625,9 +625,9 @@ int restartNFDuringNR(NdbRestarter& _restarter, const NdbRestarts::NdbRestart* _restart){ myRandom48Init(NdbTick_CurrentMillisecond()); - + int i; const int sz = sizeof(NFDuringNR_codes)/sizeof(NFDuringNR_codes[0]); - for(int i = 0; i<sz; i++){ + for(i = 0; i<sz; i++){ int randomId = myRandom48(_restarter.getNumDbNodes()); int nodeId = _restarter.getDbNodeId(randomId); int error = NFDuringNR_codes[i]; @@ -673,7 +673,7 @@ int restartNFDuringNR(NdbRestarter& _restarter, if(NdbEnv_GetEnv("USER", buf, 256) == 0 || strcmp(buf, "ejonore") != 0) return NDBT_OK; - for(int i = 0; i<sz; i++){ + for(i = 0; i<sz; i++){ const int randomId = myRandom48(_restarter.getNumDbNodes()); int nodeId = _restarter.getDbNodeId(randomId); const int error = NFDuringNR_codes[i]; @@ -753,14 +753,14 @@ NRDuringLCP_NonMaster_codes[] = { int restartNodeDuringLCP(NdbRestarter& _restarter, const NdbRestarts::NdbRestart* _restart) { - + int i; // Master int val = DumpStateOrd::DihMinTimeBetweenLCP; CHECK(_restarter.dumpStateAllNodes(&val, 1) == 0, "Failed to set LCP to min value"); // Set LCP to min val int sz = sizeof(NRDuringLCP_Master_codes)/ sizeof(NRDuringLCP_Master_codes[0]); - for(int i = 0; i<sz; i++) { + for(i = 0; i<sz; i++) { int error = NRDuringLCP_Master_codes[i]; int masterNodeId = _restarter.getMasterNodeId(); @@ -798,7 +798,7 @@ int restartNodeDuringLCP(NdbRestarter& _restarter, // NON-Master sz = sizeof(NRDuringLCP_NonMaster_codes)/ sizeof(NRDuringLCP_NonMaster_codes[0]); - for(int i = 0; i<sz; i++) { + for(i = 0; i<sz; i++) { int error = NRDuringLCP_NonMaster_codes[i]; int nodeId = getRandomNodeId(_restarter); diff --git a/ndb/test/src/UtilTransactions.cpp b/ndb/test/src/UtilTransactions.cpp index 3ef31a2f535..9f3f1d33587 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 @@ -403,7 +412,7 @@ UtilTransactions::clearTable3(Ndb* pNdb, if(check != -1){ check = pTrans->execute(Commit); - pTrans->releaseCompletedOperations(); + pTrans->restart(); } err = pTrans->getNdbError(); @@ -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->restart(); 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,30 +560,17 @@ 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, NDBT_ResultRow & row, @@ -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(); @@ -1168,7 +1040,7 @@ UtilTransactions::readRowFromTableAndIndex(Ndb* pNdb, NdbDictionary::Index::Type indexType= pIndex->getType(); int retryAttempt = 0; const int retryMax = 100; - int check; + int check, a; NdbConnection *pTrans1=NULL; NdbResultSet *cursor= NULL; NdbOperation *pOp; @@ -1228,7 +1100,7 @@ UtilTransactions::readRowFromTableAndIndex(Ndb* pNdb, #if VERBOSE printf("PK: "); #endif - for(int a = 0; a<tab.getNoOfColumns(); a++){ + for(a = 0; a<tab.getNoOfColumns(); a++){ const NdbDictionary::Column* attr = tab.getColumn(a); if (attr->getPrimaryKey() == true){ if (pOp->equal(attr->getName(), row.attributeStore(a)->aRef()) != 0){ @@ -1247,7 +1119,7 @@ UtilTransactions::readRowFromTableAndIndex(Ndb* pNdb, #if VERBOSE printf("Reading %u attributes: ", tab.getNoOfColumns()); #endif - for(int a = 0; a<tab.getNoOfColumns(); a++){ + for(a = 0; a<tab.getNoOfColumns(); a++){ if((tabRow.attributeStore(a) = pOp->getValue(tab.getColumn(a)->getName())) == 0) { ERR(pTrans1->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) { @@ -1298,7 +1170,7 @@ UtilTransactions::readRowFromTableAndIndex(Ndb* pNdb, #if VERBOSE printf("SI: "); #endif - for(int a = 0; a<(int)pIndex->getNoOfColumns(); a++){ + for(a = 0; a<(int)pIndex->getNoOfColumns(); a++){ const NdbDictionary::Column * col = pIndex->getColumn(a); int r; @@ -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()); } } @@ -1328,7 +1200,7 @@ UtilTransactions::readRowFromTableAndIndex(Ndb* pNdb, #if VERBOSE printf("Reading %u attributes: ", tab.getNoOfColumns()); #endif - for(int a = 0; a<tab.getNoOfColumns(); a++){ + for(a = 0; a<tab.getNoOfColumns(); a++){ void* pCheck; if (pIndexOp) diff --git a/ndb/test/tools/cpcc.cpp b/ndb/test/tools/cpcc.cpp index e768d707bbc..e30d458ffee 100644 --- a/ndb/test/tools/cpcc.cpp +++ b/ndb/test/tools/cpcc.cpp @@ -192,7 +192,7 @@ main(int argc, const char** argv){ ,{ "rm", 0, arg_flag, &rm, "-c rm", "undefine process(es)" } }; const int num_args = 10; - + int i; int optind = 0; char desc[] = "[host:[port]]\n"; @@ -215,13 +215,13 @@ main(int argc, const char** argv){ Expression * m_expr = 0; - for(int i = optind; i<argc; i++){ + for(i = optind; i<argc; i++){ add_host(g_hosts, argv[i]); } OrExpr * orE = new OrExpr(new Operate(cmd, g_settings), true); m_expr = orE; - for(int i = optind; i<argc; i++){ + for(i = optind; i<argc; i++){ BaseString tmp(argv[i]); Vector<BaseString> split; tmp.split(split, ":"); @@ -347,3 +347,5 @@ Operate::evaluate(SimpleCpcClient* c, const SimpleCpcClient::Process & pp){ return true; } +template class Vector<Expression*>; +template class Vector<SimpleCpcClient*>; diff --git a/ndb/test/tools/create_index.cpp b/ndb/test/tools/create_index.cpp index dc9e6c606d6..f883755ea24 100644 --- a/ndb/test/tools/create_index.cpp +++ b/ndb/test/tools/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; c<tab->getNoOfColumns(); c++) - ind.addIndexColumn(tab->getColumn(c)->getName()); - + for(int c = 0; c<tab->getNoOfColumns(); 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/test/tools/hugoPkReadRecord.cpp b/ndb/test/tools/hugoPkReadRecord.cpp index ac17ffffee8..85f20bd2060 100644 --- a/ndb/test/tools/hugoPkReadRecord.cpp +++ b/ndb/test/tools/hugoPkReadRecord.cpp @@ -43,7 +43,7 @@ int main(int argc, const char** argv) }; int num_args = sizeof(args) / sizeof(args[0]); - int optind = 0; + int optind = 0, i; if(getarg(args, num_args, argc, argv, &optind) || argv[optind] == NULL) { arg_printusage(args, num_args, argv[0], "table name\n"); @@ -80,7 +80,7 @@ int main(int argc, const char** argv) } op->readTuple(); NdbRecAttr** data = new NdbRecAttr*[table->getNoOfColumns()]; - for (int i = 0; i < table->getNoOfColumns(); i++) + for (i = 0; i < table->getNoOfColumns(); i++) { const NdbDictionary::Column* c = table->getColumn(i); if (c->getPrimaryKey()) @@ -93,11 +93,10 @@ int main(int argc, const char** argv) data[i] = op->getValue(c->getName(), NULL); } } - if (conn->execute(Commit) == 0) { // Print column names - for (int i = 0; i < table->getNoOfColumns(); i++) + for (i = 0; i < table->getNoOfColumns(); i++) { const NdbDictionary::Column* c = table->getColumn(i); @@ -111,7 +110,7 @@ int main(int argc, const char** argv) { g_info << hex; } - for (int i = 0; i < table->getNoOfColumns(); i++) + for (i = 0; i < table->getNoOfColumns(); i++) { NdbRecAttr* a = data[i]; switch(a->getType()) diff --git a/ndb/tools/delete_all.cpp b/ndb/tools/delete_all.cpp index dabd9a0e8fa..5110947c6a2 100644 --- a/ndb/tools/delete_all.cpp +++ b/ndb/tools/delete_all.cpp @@ -143,7 +143,7 @@ int clear_table(Ndb* pNdb, const NdbDictionary::Table* pTab, int parallelism) if(check != -1){ check = pTrans->execute(Commit); - pTrans->releaseCompletedOperations(); + pTrans->restart(); } err = pTrans->getNdbError(); diff --git a/ndb/tools/desc.cpp b/ndb/tools/desc.cpp index a5ff11edca9..e5b98c4c8e9 100644 --- a/ndb/tools/desc.cpp +++ b/ndb/tools/desc.cpp @@ -73,7 +73,8 @@ int main(int argc, const char** argv){ ndbout << "-- Indexes -- " << endl; ndbout << "PRIMARY KEY("; - for (unsigned j= 0; j < pTab->getNoOfPrimaryKeys(); j++) + unsigned j; + for (j= 0; j < pTab->getNoOfPrimaryKeys(); j++) { const NdbDictionary::Column * col = pTab->getColumn(j); ndbout << col->getName(); @@ -82,7 +83,7 @@ int main(int argc, const char** argv){ } ndbout << ") - UniqueHashIndex" << endl; - for (unsigned j= 0; j < list.count; j++) { + for (j= 0; j < list.count; j++) { NdbDictionary::Dictionary::List::Element& elt = list.elements[j]; const NdbDictionary::Index *pIdx = dict->getIndex(elt.name, argv[i]); if (!pIdx){ diff --git a/ndb/tools/select_all.cpp b/ndb/tools/select_all.cpp index 34f63a095bb..329ed87bc48 100644 --- a/ndb/tools/select_all.cpp +++ b/ndb/tools/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(); diff --git a/ndb/tools/select_count.cpp b/ndb/tools/select_count.cpp index cae91feb378..2c43af20e64 100644 --- a/ndb/tools/select_count.cpp +++ b/ndb/tools/select_count.cpp @@ -30,8 +30,7 @@ static int select_count(Ndb* pNdb, const NdbDictionary::Table* pTab, int parallelism, int* count_rows, - UtilTransactions::ScanLock lock, - NdbConnection* pBuddyTrans=0); + UtilTransactions::ScanLock lock); int main(int argc, const char** argv){ const char* _dbname = "TEST_DB"; @@ -95,14 +94,13 @@ int select_count(Ndb* pNdb, const NdbDictionary::Table* pTab, int parallelism, int* count_rows, - UtilTransactions::ScanLock lock, - NdbConnection* pBuddyTrans){ + UtilTransactions::ScanLock lock){ int retryAttempt = 0; const int retryMax = 100; int check; NdbConnection *pTrans; - NdbOperation *pOp; + NdbScanOperation *pOp; while (true){ @@ -112,7 +110,7 @@ select_count(Ndb* pNdb, const NdbDictionary::Table* pTab, return NDBT_FAILED; } - pTrans = pNdb->hupp(pBuddyTrans); + pTrans = pNdb->startTransaction(); if (pTrans == NULL) { const NdbError err = pNdb->getNdbError(); @@ -124,26 +122,27 @@ select_count(Ndb* pNdb, const NdbDictionary::Table* pTab, ERR(err); return NDBT_FAILED; } - pOp = pTrans->getNdbOperation(pTab->getName()); + pOp = pTrans->getNdbScanOperation(pTab->getName()); if (pOp == NULL) { ERR(pTrans->getNdbError()); pNdb->closeTransaction(pTrans); return NDBT_FAILED; } + NdbResultSet * rs; switch(lock){ case UtilTransactions::SL_ReadHold: - check = pOp->openScanReadHoldLock(parallelism); + rs = pOp->readTuples(NdbScanOperation::LM_Read, 0, parallelism); break; case UtilTransactions::SL_Exclusive: - check = pOp->openScanExclusive(parallelism); + rs = pOp->readTuples(NdbScanOperation::LM_Exclusive, 0, parallelism); break; case UtilTransactions::SL_Read: default: - check = pOp->openScanRead(parallelism); + rs = pOp->readTuples(NdbScanOperation::LM_Dirty, 0, parallelism); } - if( check == -1 ) { + if( rs == 0 ) { ERR(pTrans->getNdbError()); pNdb->closeTransaction(pTrans); return NDBT_FAILED; @@ -156,7 +155,7 @@ select_count(Ndb* pNdb, const NdbDictionary::Table* pTab, return NDBT_FAILED; } - check = pTrans->executeScan(); + check = pTrans->execute(NoCommit); if( check == -1 ) { ERR(pTrans->getNdbError()); pNdb->closeTransaction(pTrans); @@ -165,11 +164,11 @@ select_count(Ndb* pNdb, const NdbDictionary::Table* pTab, int eof; int rows = 0; - eof = pTrans->nextScanResult(); + eof = rs->nextResult(); while(eof == 0){ rows++; - eof = pTrans->nextScanResult(); + eof = rs->nextResult(); } if (eof == -1) { const NdbError err = pTrans->getNdbError(); diff --git a/ndb/tools/waiter.cpp b/ndb/tools/waiter.cpp index 7ce2739a157..86d34066c55 100644 --- a/ndb/tools/waiter.cpp +++ b/ndb/tools/waiter.cpp @@ -22,21 +22,26 @@ #include <NdbSleep.h> #include <getarg.h> #include <kernel/ndb_limits.h> -#include "../src/common/mgmcommon/LocalConfig.hpp" +#include "../include/mgmcommon/LocalConfig.hpp" #include <NDBT.hpp> int -waitClusterStarted(const char* _addr, unsigned int _timeout= 120); +waitClusterStatus(const char* _addr, + ndb_mgm_node_status _status= NDB_MGM_NODE_STATUS_STARTED, + unsigned int _timeout= 120); int main(int argc, const char** argv){ const char* _hostName = NULL; + int _no_contact = 0; int _help = 0; struct getargs args[] = { + { "no-contact", 0, arg_flag, &_no_contact, "Wait for cluster no contact", "" }, { "usage", '?', arg_flag, &_help, "Print help", "" } }; + int num_args = sizeof(args) / sizeof(args[0]); int optind = 0; char desc[] = @@ -62,13 +67,13 @@ int main(int argc, const char** argv){ return NDBT_ProgramExit(NDBT_FAILED); } - for (int i = 0; i<lcfg.items; i++) + for (int i = 0; i<lcfg.ids.size();i++) { - MgmtSrvrId * m = lcfg.ids[i]; + MgmtSrvrId * m = &lcfg.ids[i]; switch(m->type){ case MgmId_TCP: - snprintf(buf, 255, "%s:%d", m->data.tcp.remoteHost, m->data.tcp.port); + snprintf(buf, 255, "%s:%d", m->name.c_str(), m->port); _hostName = buf; break; case MgmId_File: @@ -86,7 +91,10 @@ int main(int argc, const char** argv){ } } - if (waitClusterStarted(_hostName) != 0) + if (_no_contact) { + if (waitClusterStatus(_hostName, NDB_MGM_NODE_STATUS_NO_CONTACT) != 0) + return NDBT_ProgramExit(NDBT_FAILED); + } else if (waitClusterStatus(_hostName) != 0) return NDBT_ProgramExit(NDBT_FAILED); return NDBT_ProgramExit(NDBT_OK); @@ -121,7 +129,8 @@ getStatus(){ retries++; continue; } - for (int i = 0; i < status->no_of_nodes; i++){ + int count = status->no_of_nodes; + for (int i = 0; i < count; i++){ node = &status->node_states[i]; switch(node->node_type){ case NDB_MGM_NODE_TYPE_NDB: @@ -142,7 +151,7 @@ getStatus(){ apiNodes.clear(); free(status); status = NULL; - i = status->no_of_nodes; + count = 0; ndbout << "kalle"<< endl; break; @@ -164,9 +173,10 @@ getStatus(){ } int -waitClusterStarted(const char* _addr, unsigned int _timeout) +waitClusterStatus(const char* _addr, + ndb_mgm_node_status _status, + unsigned int _timeout) { - ndb_mgm_node_status _status = NDB_MGM_NODE_STATUS_STARTED; int _startphase = -1; int _nodes[MAX_NDB_NODES]; @@ -290,10 +300,12 @@ waitClusterStarted(const char* _addr, unsigned int _timeout) allInState = false; } } - g_info << "Waiting for cluster enter state" + g_info << "Waiting for cluster enter state " << ndb_mgm_get_node_status_string(_status)<< endl; NdbSleep_SecSleep(1); attempts++; } return 0; } + +template class Vector<ndb_mgm_node_state>; |