diff options
Diffstat (limited to 'ndb/test')
80 files changed, 6187 insertions, 2688 deletions
diff --git a/ndb/test/include/HugoCalculator.hpp b/ndb/test/include/HugoCalculator.hpp index b782eb003a3..03de46cd7ea 100644 --- a/ndb/test/include/HugoCalculator.hpp +++ b/ndb/test/include/HugoCalculator.hpp @@ -31,14 +31,7 @@ class HugoCalculator { public: HugoCalculator(const NdbDictionary::Table& tab); Int32 calcValue(int record, int attrib, int updates) const; -#if 0 - U_Int32 calcValue(int record, int attrib, int updates) const; - U_Int64 calcValue(int record, int attrib, int updates) const; - Int64 calcValue(int record, int attrib, int updates) const; - float calcValue(int record, int attrib, int updates) const; - double calcValue(int record, int attrib, int updates) const; -#endif - const char* calcValue(int record, int attrib, int updates, char* buf) const; + const char* calcValue(int record, int attrib, int updates, char* buf, int len) const; int verifyRowValues(NDBT_ResultRow* const pRow) const; int getIdValue(NDBT_ResultRow* const pRow) const; diff --git a/ndb/test/include/HugoOperations.hpp b/ndb/test/include/HugoOperations.hpp index 34b2edc2ae8..82fd5529fa2 100644 --- a/ndb/test/include/HugoOperations.hpp +++ b/ndb/test/include/HugoOperations.hpp @@ -24,11 +24,14 @@ class HugoOperations : public UtilTransactions { public: - HugoOperations(const NdbDictionary::Table&); + HugoOperations(const NdbDictionary::Table&, + const NdbDictionary::Index* idx = 0); + ~HugoOperations(); int startTransaction(Ndb*); + int setTransaction(NdbTransaction*); int closeTransaction(Ndb*); - NdbConnection* getTransaction(); + NdbTransaction* getTransaction(); void refresh(); void setTransactionId(Uint64); @@ -42,6 +45,10 @@ public: int recordNo, int numRecords = 1, int updatesValue = 0); + + int pkWritePartialRecord(Ndb*, + int recordNo, + int numRecords = 1); int pkReadRecord(Ndb*, int recordNo, @@ -73,10 +80,13 @@ public: int attrId, int rowId, int updateId); + int equalForAttr(NdbOperation*, int attrId, int rowId); - + + int setValues(NdbOperation*, int rowId, int updateId); + int verifyUpdatesValue(int updatesValue, int _numRows = 0); int indexReadRecords(Ndb*, const char * idxName, int recordNo, @@ -93,8 +103,11 @@ public: NdbScanOperation::LM_CommittedRead, int numRecords = 1); + NdbIndexScanOperation* pIndexScanOp; - int execute_async(Ndb*, ExecType, AbortOption = AbortOnError); + NDBT_ResultRow& get_row(Uint32 idx) { return *rows[idx];} + + int execute_async(Ndb*, NdbTransaction::ExecType, NdbTransaction::AbortOption = NdbTransaction::AbortOnError); int wait_async(Ndb*, int timeout = -1); protected: @@ -106,16 +119,14 @@ protected: Vector<BaseString> savedRecords; - struct RsPair { NdbResultSet* m_result_set; int records; }; + struct RsPair { NdbScanOperation* m_result_set; int records; }; Vector<RsPair> m_result_sets; Vector<RsPair> m_executed_result_sets; - NdbConnection* pTrans; - int m_async_reply; int m_async_return; - friend void HugoOperations_async_callback(int, NdbConnection*, void*); - void callback(int res, NdbConnection*); + friend void HugoOperations_async_callback(int, NdbTransaction*, void*); + void callback(int res, NdbTransaction*); }; #endif diff --git a/ndb/test/include/HugoTransactions.hpp b/ndb/test/include/HugoTransactions.hpp index b833f2ac629..5795bbc94c9 100644 --- a/ndb/test/include/HugoTransactions.hpp +++ b/ndb/test/include/HugoTransactions.hpp @@ -25,7 +25,8 @@ class HugoTransactions : public HugoOperations { public: - HugoTransactions(const NdbDictionary::Table&); + HugoTransactions(const NdbDictionary::Table&, + const NdbDictionary::Index* idx = 0); ~HugoTransactions(); int createEvent(Ndb*); int eventOperation(Ndb*, void* stats, @@ -41,7 +42,8 @@ public: int records, int abort = 0, int parallelism = 0, - NdbOperation::LockMode = NdbOperation::LM_Read); + NdbOperation::LockMode = NdbOperation::LM_Read, + int scan_flags = 0); int scanReadRecords(Ndb*, const NdbDictionary::Index*, @@ -49,7 +51,7 @@ public: int abort = 0, int parallelism = 0, NdbOperation::LockMode = NdbOperation::LM_Read, - bool sorted = false); + int scan_flags = 0); int pkReadRecords(Ndb*, int records, diff --git a/ndb/test/include/NDBT_Error.hpp b/ndb/test/include/NDBT_Error.hpp index ef107072465..6775a107196 100644 --- a/ndb/test/include/NDBT_Error.hpp +++ b/ndb/test/include/NDBT_Error.hpp @@ -91,7 +91,11 @@ private: ; \ } -#define ERR(error) ERR_OUT(g_err, error) +#define ERR(error) \ +{ \ + const NdbError &_error= (error); \ + ERR_OUT(g_err, _error); \ +} #define ERR_INFO(error) ERR_OUT(g_info, error) #endif diff --git a/ndb/test/include/NDBT_ResultRow.hpp b/ndb/test/include/NDBT_ResultRow.hpp index 6072d0ea510..cbb5d7f6c6a 100644 --- a/ndb/test/include/NDBT_ResultRow.hpp +++ b/ndb/test/include/NDBT_ResultRow.hpp @@ -27,7 +27,7 @@ public: const NdbRecAttr * attributeStore(int i) const ; const NdbRecAttr * attributeStore(const char* name) const ; - BaseString c_str(); + BaseString c_str() const ; NdbOut & header (NdbOut &) const; friend NdbOut & operator << (NdbOut&, const NDBT_ResultRow &); @@ -36,6 +36,11 @@ public: * Make copy of NDBT_ResultRow */ NDBT_ResultRow * clone() const; + + bool operator==(const NDBT_ResultRow&) const ; + bool operator!=(const NDBT_ResultRow& other) const { + return ! (*this == other); + } private: int cols; diff --git a/ndb/test/include/NDBT_Tables.hpp b/ndb/test/include/NDBT_Tables.hpp index aa78f7d4e2c..fb0df8aa35b 100644 --- a/ndb/test/include/NDBT_Tables.hpp +++ b/ndb/test/include/NDBT_Tables.hpp @@ -23,11 +23,13 @@ #include <NdbDictionary.hpp> #include <NDBT_Table.hpp> +typedef int (* NDBT_CreateTableHook)(Ndb*, NdbDictionary::Table&, int when); + class NDBT_Tables { public: - + static int createTable(Ndb* pNdb, const char* _name, bool _temp = false, - bool existsOK = false); + bool existsOK = false, NDBT_CreateTableHook = 0); 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 bcaa0bf4d40..027ac356e0c 100644 --- a/ndb/test/include/NDBT_Test.hpp +++ b/ndb/test/include/NDBT_Test.hpp @@ -25,6 +25,7 @@ #include <NdbCondition.h> #include <NdbTimer.hpp> #include <Vector.hpp> +#include <NdbApi.hpp> #include <NdbDictionary.hpp> class NDBT_Step; @@ -34,7 +35,9 @@ class NDBT_TestCaseImpl1; class NDBT_Context { public: - NDBT_Context(); + Ndb_cluster_connection& m_cluster_connection; + + NDBT_Context(Ndb_cluster_connection&); ~NDBT_Context(); const NdbDictionary::Table* getTab(); NDBT_TestSuite* getSuite(); @@ -121,7 +124,7 @@ public: NDBT_TESTFUNC* pfunc); virtual ~NDBT_Step() {} int execute(NDBT_Context*); - virtual int setUp() = 0; + virtual int setUp(Ndb_cluster_connection&) = 0; virtual void tearDown() = 0; void setContext(NDBT_Context*); NDBT_Context* getContext(); @@ -143,7 +146,7 @@ public: const char* pname, NDBT_TESTFUNC* pfunc); virtual ~NDBT_NdbApiStep() {} - virtual int setUp(); + virtual int setUp(Ndb_cluster_connection&); virtual void tearDown(); Ndb* getNdb(); @@ -350,10 +353,13 @@ public: int addTest(NDBT_TestCase* pTest); private: - int executeOne(const char* _tabname, const char* testname = NULL); - int executeAll(const char* testname = NULL); - - void execute(Ndb*, const NdbDictionary::Table*, const char* testname = NULL); + int executeOne(Ndb_cluster_connection&, + const char* _tabname, const char* testname = NULL); + int executeAll(Ndb_cluster_connection&, + const char* testname = NULL); + void execute(Ndb_cluster_connection&, + Ndb*, const NdbDictionary::Table*, const char* testname = NULL); + int report(const char* _tcname = NULL); int reportAllTables(const char* ); const char* name; @@ -426,7 +432,7 @@ C##suitname():NDBT_TestSuite(#suitname){ \ pt->addTable(tableName, false); #define NDBT_TESTSUITE_END(suitname) \ - } } ; C##suitname suitname; + } } ; C##suitname suitname // Helper functions for retrieving variables from NDBT_Step #define GETNDB(ps) ((NDBT_NdbApiStep*)ps)->getNdb() diff --git a/ndb/test/include/NdbSchemaOp.hpp b/ndb/test/include/NdbSchemaOp.hpp index e8ab542b00a..1edbc155643 100644 --- a/ndb/test/include/NdbSchemaOp.hpp +++ b/ndb/test/include/NdbSchemaOp.hpp @@ -79,29 +79,6 @@ }; /** - * Where attribute is stored. - * - * This is used to indicate whether a primary key - * should only be stored in the index storage and not in the data storage - * or if it should be stored in both places. - * The first alternative makes the attribute take less space, - * but makes it impossible to scan using attribute. - * - * @note Use NormalStorageAttribute for most cases. - * (IndexStorageAttribute should only be used on primary key - * attributes and only if you do not want to scan using the attribute.) - */ - enum StorageAttributeType { - NoStorageAttributeTypeDefined = -1, ///< <i>Missing explanation</i> - IndexStorageAttribute, ///< Attribute is only stored in - ///< index storage (ACC) - NormalStorageAttribute ///< Attribute values are stored - ///< both in the index (ACC) and - ///< in the data storage (TUP) - }; - - - /** * Type of fragmentation used for a table */ enum FragmentType { @@ -405,27 +382,7 @@ public: * the attribute. * <br> * Legal values: true, false - * @param aStType Stored in both index and data storage or - * only store in index data storage. - * <br> - * This parameter is only of interest for tuple - * key attributes. - * All tuple key attributes values are always stored - * in the index storage part. - * If this parameter is set to - * IndexStorageAttribute, then the attribute values - * will <em>only</em> be stored in the index - * storage part and <em>not</em> in the data - * storage part. - * <br> - * If there will be no scans using the primary - * key attribute and if the size of the attribute - * is large, then this might be of interest. - * A typical example is a table where - * http-addresses are used as primary key. - * <br> - * Legal values: NormalStorageAttribute, - * IndexStorageAttribute + * @param aStType Obsolete since wl-2066 * @param aDistributionKey Sometimes it is preferable to use a subset * of the primary key as the distribution key. * An example is TPC-C where it might be @@ -474,7 +431,7 @@ public: AttrType aAttrType = UnSigned, StorageMode aStorageMode = MMBased, bool nullable = false, - StorageAttributeType aStType= NormalStorageAttribute, + int aStType= 0, // obsolete int aDistributionKey = 0, int aDistributionGroup = 0, int aDistributionGroupNoOfBits = 16, @@ -491,7 +448,7 @@ public: AttrType aAttrType, StorageMode aStorageMode, NullAttributeType aNullAttr, - StorageAttributeType aStType = NormalStorageAttribute, + int aStType, // obsolete int aDistributionKey = 0, int aDistributionGroup = 0, int aDistributionGroupNoOfBits = 16){ @@ -569,6 +526,8 @@ convertColumnTypeToAttrType(NdbDictionary::Column::Type _type) case NdbDictionary::Column::Float: case NdbDictionary::Column::Olddecimal: case NdbDictionary::Column::Olddecimalunsigned: + case NdbDictionary::Column::Decimal: + case NdbDictionary::Column::Decimalunsigned: case NdbDictionary::Column::Double: return Float; case NdbDictionary::Column::Char: diff --git a/ndb/test/include/UtilTransactions.hpp b/ndb/test/include/UtilTransactions.hpp index 23902f3b317..333f5d98328 100644 --- a/ndb/test/include/UtilTransactions.hpp +++ b/ndb/test/include/UtilTransactions.hpp @@ -23,15 +23,13 @@ typedef int (ReadCallBackFn)(NDBT_ResultRow*); class UtilTransactions { public: - enum ScanLock { - SL_Read = 0, - SL_ReadHold = 1, - SL_Exclusive = 2 - }; - - UtilTransactions(const NdbDictionary::Table&); - UtilTransactions(Ndb* ndb, const char * tableName); - + UtilTransactions(const NdbDictionary::Table&, + const NdbDictionary::Index* idx = 0); + UtilTransactions(Ndb* ndb, + const char * tableName, const char * indexName = 0); + + int closeTransaction(Ndb*); + int clearTable(Ndb*, int records = 0, int parallelism = 0); @@ -70,6 +68,14 @@ public: int copyTableData(Ndb*, const char* destName); + /** + * Compare this table with other_table + * + * return 0 - on equality + * -1 - on error + * >0 - otherwise + */ + int compare(Ndb*, const char * other_table, int flags); private: static int takeOverAndDeleteRecord(Ndb*, @@ -114,6 +120,12 @@ private: protected: int m_defaultClearMethod; const NdbDictionary::Table& tab; + const NdbDictionary::Index* idx; + NdbConnection* pTrans; + + NdbOperation* getOperation(NdbConnection*, + NdbOperation::OperationType); + NdbScanOperation* getScanOperation(NdbConnection*); }; #endif diff --git a/ndb/test/ndbapi/Makefile.am b/ndb/test/ndbapi/Makefile.am index 7b4a96f5890..d83e9614eb5 100644 --- a/ndb/test/ndbapi/Makefile.am +++ b/ndb/test/ndbapi/Makefile.am @@ -31,7 +31,10 @@ testTimeout \ testTransactions \ testDeadlock \ test_event ndbapi_slow_select testReadPerf testLcp \ +testPartitioning \ +testBitfield \ DbCreate DbAsyncGenerator \ +test_event_multi_table \ testSRBank #flexTimedAsynch @@ -71,8 +74,11 @@ test_event_SOURCES = test_event.cpp ndbapi_slow_select_SOURCES = slow_select.cpp testReadPerf_SOURCES = testReadPerf.cpp testLcp_SOURCES = testLcp.cpp -DbCreate_SOURCES= bench/mainPopulate.cpp bench/dbPopulate.cpp bench/userInterface.cpp bench/dbPopulate.h bench/userInterface.h bench/testData.h bench/testDefinitions.h bench/ndb_schema.hpp bench/ndb_error.hpp -DbAsyncGenerator_SOURCES= bench/mainAsyncGenerator.cpp bench/asyncGenerator.cpp bench/ndb_async2.cpp bench/dbGenerator.h bench/macros.h bench/userInterface.h bench/testData.h bench/testDefinitions.h bench/ndb_schema.hpp bench/ndb_error.hpp +testPartitioning_SOURCES = testPartitioning.cpp +testBitfield_SOURCES = testBitfield.cpp +DbCreate_SOURCES = bench/mainPopulate.cpp bench/dbPopulate.cpp bench/userInterface.cpp bench/dbPopulate.h bench/userInterface.h bench/testData.h bench/testDefinitions.h bench/ndb_schema.hpp bench/ndb_error.hpp +DbAsyncGenerator_SOURCES = bench/mainAsyncGenerator.cpp bench/asyncGenerator.cpp bench/ndb_async2.cpp bench/dbGenerator.h bench/macros.h bench/userInterface.h bench/testData.h bench/testDefinitions.h bench/ndb_schema.hpp bench/ndb_error.hpp +test_event_multi_table_SOURCES = test_event_multi_table.cpp testSRBank_SOURCES = testSRBank.cpp INCLUDES_LOC = -I$(top_srcdir)/ndb/include/kernel @@ -90,6 +96,8 @@ testSRBank_LDADD = bank/libbank.a $(LDADD) # Don't update the files from bitkeeper %::SCCS/s.% + + windoze-dsp: flexBench.dsp testBasic.dsp testBlobs.dsp \ testScan.dsp diff --git a/ndb/test/ndbapi/ScanFunctions.hpp b/ndb/test/ndbapi/ScanFunctions.hpp index 6964f8c73a8..37389d9b7de 100644 --- a/ndb/test/ndbapi/ScanFunctions.hpp +++ b/ndb/test/ndbapi/ScanFunctions.hpp @@ -81,7 +81,6 @@ ScanFunctions::scanReadFunctions(Ndb* pNdb, int check; NdbConnection *pTrans = 0; NdbScanOperation *pOp = 0; - NdbResultSet *rs = 0; while (true){ if (retryAttempt >= retryMax){ @@ -111,12 +110,9 @@ ScanFunctions::scanReadFunctions(Ndb* pNdb, return NDBT_FAILED; } - - rs = pOp->readTuples(exclusive ? - NdbScanOperation::LM_Exclusive : - NdbScanOperation::LM_Read); - - if( rs == 0 ) { + if( pOp->readTuples(exclusive ? + NdbScanOperation::LM_Exclusive : + NdbScanOperation::LM_Read) ) { ERR(pTrans->getNdbError()); pNdb->closeTransaction(pTrans); return NDBT_FAILED; @@ -125,8 +121,7 @@ ScanFunctions::scanReadFunctions(Ndb* pNdb, if (action == OnlyOpenScanOnce){ // Call openScan one more time when it's already defined - NdbResultSet* rs2 = pOp->readTuples(NdbScanOperation::LM_Read); - if( rs2 == 0 ) { + if( pOp->readTuples(NdbScanOperation::LM_Read) ) { ERR(pTrans->getNdbError()); pNdb->closeTransaction(pTrans); return NDBT_FAILED; @@ -168,7 +163,7 @@ ScanFunctions::scanReadFunctions(Ndb* pNdb, bool abortTrans = (action==CloseWithoutStop); int eof; int rows = 0; - eof = rs->nextResult(); + eof = pOp->nextResult(); while(eof == 0){ rows++; @@ -178,7 +173,7 @@ ScanFunctions::scanReadFunctions(Ndb* pNdb, if (action != CloseWithoutStop){ // Test that we can closeTrans without stopScan - rs->close(); + pOp->close(); if( check == -1 ) { ERR(pTrans->getNdbError()); pNdb->closeTransaction(pTrans); @@ -201,7 +196,7 @@ ScanFunctions::scanReadFunctions(Ndb* pNdb, } } - eof = rs->nextResult(); + eof = pOp->nextResult(); } if (eof == -1) { const NdbError err = pTrans->getNdbError(); @@ -211,7 +206,7 @@ ScanFunctions::scanReadFunctions(Ndb* pNdb, // Be cruel, call nextScanResult after error for(int i=0; i<10; i++){ - eof = rs->nextResult(); + eof = pOp->nextResult(); if(eof == 0){ g_err << "nextScanResult returned eof = " << eof << endl << " That is an error when there are no more records" << endl; @@ -241,7 +236,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 = rs->nextResult(); + eof = pOp->nextResult(); if(eof == 0){ g_err << "nextScanResult returned eof = " << eof << endl << " That is an error when there are no more records" << endl; diff --git a/ndb/test/ndbapi/ScanInterpretTest.hpp b/ndb/test/ndbapi/ScanInterpretTest.hpp index e8a0d4b6dca..d4e9bbecc81 100644 --- a/ndb/test/ndbapi/ScanInterpretTest.hpp +++ b/ndb/test/ndbapi/ScanInterpretTest.hpp @@ -227,10 +227,7 @@ ScanInterpretTest::scanRead(Ndb* pNdb, return NDBT_FAILED; } - NdbResultSet * rs = pOp->readTuples(NdbScanOperation::LM_Read, - 0, parallelism); - - if( rs == 0 ) { + if( pOp->readTuples(NdbScanOperation::LM_Read, 0, parallelism) ) { ERR(pTrans->getNdbError()); pNdb->closeTransaction(pTrans); return NDBT_FAILED; @@ -262,14 +259,14 @@ ScanInterpretTest::scanRead(Ndb* pNdb, int rows = 0; NdbConnection* pInsTrans; - while((eof = rs->nextResult(true)) == 0){ + while((eof = pOp->nextResult(true)) == 0){ do { rows++; if (addRowToInsert(pNdb, pTrans) != 0){ pNdb->closeTransaction(pTrans); return NDBT_FAILED; } - } while((eof = rs->nextResult(false)) == 0); + } while((eof = pOp->nextResult(false)) == 0); check = pTrans->execute(Commit); if( check == -1 ) { @@ -349,9 +346,7 @@ ScanInterpretTest::scanReadVerify(Ndb* pNdb, return NDBT_FAILED; } - NdbResultSet * rs = pOp->readTuples(NdbScanOperation::LM_Read, - 0, parallelism); - if( rs == 0 ) { + if( pOp->readTuples(NdbScanOperation::LM_Read, 0, parallelism) ) { ERR(pTrans->getNdbError()); pNdb->closeTransaction(pTrans); return NDBT_FAILED; @@ -392,7 +387,7 @@ ScanInterpretTest::scanReadVerify(Ndb* pNdb, NdbConnection* pExistTrans; NdbConnection* pNoExistTrans; - while((eof = rs->nextResult(true)) == 0){ + while((eof = pOp->nextResult(true)) == 0){ pExistTrans = pNdb->startTransaction(); if (pExistTrans == NULL) { const NdbError err = pNdb->getNdbError(); @@ -424,7 +419,7 @@ ScanInterpretTest::scanReadVerify(Ndb* pNdb, return NDBT_FAILED; } } - } while((eof = rs->nextResult(false)) == 0); + } while((eof = pOp->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 346442367fc..37224fdd055 100644 --- a/ndb/test/ndbapi/bank/Bank.cpp +++ b/ndb/test/ndbapi/bank/Bank.cpp @@ -19,8 +19,8 @@ #include <NdbSleep.h> #include <UtilTransactions.hpp> -Bank::Bank(bool _init): - m_ndb("BANK"), +Bank::Bank(Ndb_cluster_connection& con, bool _init): + m_ndb(&con, "BANK"), m_maxAccount(-1), m_initialized(false) { @@ -661,8 +661,7 @@ int Bank::findLastGL(Uint64 &lastTime){ return NDBT_FAILED; } - NdbResultSet * rs = pOp->readTuples(); - if( rs == 0 ) { + if( pOp->readTuples() ) { ERR(pScanTrans->getNdbError()); m_ndb.closeTransaction(pScanTrans); return NDBT_FAILED; @@ -691,7 +690,7 @@ int Bank::findLastGL(Uint64 &lastTime){ int eof; int rows = 0; - eof = rs->nextResult(); + eof = pOp->nextResult(); lastTime = 0; while(eof == 0){ @@ -701,7 +700,7 @@ int Bank::findLastGL(Uint64 &lastTime){ if (t > lastTime) lastTime = t; - eof = rs->nextResult(); + eof = pOp->nextResult(); } if (eof == -1) { ERR(pScanTrans->getNdbError()); @@ -993,8 +992,7 @@ int Bank::sumTransactionsForGL(const Uint64 glTime, return NDBT_FAILED; } - NdbResultSet * rs = pOp->readTuplesExclusive(); - if( rs == 0 ) { + if( pOp->readTuplesExclusive()) { ERR(pScanTrans->getNdbError()); m_ndb.closeTransaction(pScanTrans); return NDBT_FAILED; @@ -1045,7 +1043,7 @@ int Bank::sumTransactionsForGL(const Uint64 glTime, int eof; int rows = 0; int rowsFound = 0; - eof = rs->nextResult(); + eof = pOp->nextResult(); while(eof == 0){ rows++; @@ -1069,7 +1067,7 @@ int Bank::sumTransactionsForGL(const Uint64 glTime, } } - eof = rs->nextResult(); + eof = pOp->nextResult(); if ((rows % 100) == 0){ // "refresh" ownner transaction every 100th row @@ -1153,8 +1151,7 @@ int Bank::performValidateGL(Uint64 glTime){ return NDBT_FAILED; } - NdbResultSet * rs = pOp->readTuples(); - if( rs == 0 ) { + if( pOp->readTuples() ) { ERR(pScanTrans->getNdbError()); m_ndb.closeTransaction(pScanTrans); return NDBT_FAILED; @@ -1233,7 +1230,7 @@ int Bank::performValidateGL(Uint64 glTime){ int rows = 0; int countGlRecords = 0; int result = NDBT_OK; - eof = rs->nextResult(); + eof = pOp->nextResult(); while(eof == 0){ rows++; @@ -1320,7 +1317,7 @@ int Bank::performValidateGL(Uint64 glTime){ } } - eof = rs->nextResult(); + eof = pOp->nextResult(); } if (eof == -1) { ERR(pScanTrans->getNdbError()); @@ -1417,8 +1414,7 @@ int Bank::getOldestPurgedGL(const Uint32 accountType, return NDBT_FAILED; } - NdbResultSet * rs = pOp->readTuples(); - if( rs == 0 ) { + if( pOp->readTuples() ) { ERR(pScanTrans->getNdbError()); m_ndb.closeTransaction(pScanTrans); return NDBT_FAILED; @@ -1461,7 +1457,7 @@ int Bank::getOldestPurgedGL(const Uint32 accountType, int eof; int rows = 0; - eof = rs->nextResult(); + eof = pOp->nextResult(); oldest = 0; while(eof == 0){ @@ -1475,7 +1471,7 @@ int Bank::getOldestPurgedGL(const Uint32 accountType, if (t > oldest) oldest = t; } - eof = rs->nextResult(); + eof = pOp->nextResult(); } if (eof == -1) { ERR(pScanTrans->getNdbError()); @@ -1509,8 +1505,7 @@ int Bank::getOldestNotPurgedGL(Uint64 &oldest, return NDBT_FAILED; } - NdbResultSet * rs = pOp->readTuples(); - if( rs == 0 ) { + if( pOp->readTuples() ) { ERR(pScanTrans->getNdbError()); m_ndb.closeTransaction(pScanTrans); return NDBT_FAILED; @@ -1553,7 +1548,7 @@ int Bank::getOldestNotPurgedGL(Uint64 &oldest, int eof; int rows = 0; - eof = rs->nextResult(); + eof = pOp->nextResult(); oldest = (Uint64)-1; found = false; @@ -1570,7 +1565,7 @@ int Bank::getOldestNotPurgedGL(Uint64 &oldest, accountTypeId = a; } } - eof = rs->nextResult(); + eof = pOp->nextResult(); } if (eof == -1) { ERR(pScanTrans->getNdbError()); @@ -1606,8 +1601,7 @@ int Bank::checkNoTransactionsOlderThan(const Uint32 accountType, return NDBT_FAILED; } - NdbResultSet * rs = pOp->readTuples(); - if( rs == 0 ) { + if( pOp->readTuples() ) { ERR(pScanTrans->getNdbError()); m_ndb.closeTransaction(pScanTrans); return NDBT_FAILED; @@ -1651,7 +1645,7 @@ int Bank::checkNoTransactionsOlderThan(const Uint32 accountType, int eof; int rows = 0; int found = 0; - eof = rs->nextResult(); + eof = pOp->nextResult(); while(eof == 0){ rows++; @@ -1667,7 +1661,7 @@ int Bank::checkNoTransactionsOlderThan(const Uint32 accountType, << " ti = " << ti << endl; found++; } - eof = rs->nextResult(); + eof = pOp->nextResult(); } if (eof == -1) { ERR(pScanTrans->getNdbError()); @@ -1850,8 +1844,7 @@ int Bank::findTransactionsToPurge(const Uint64 glTime, return NDBT_FAILED; } - NdbResultSet * rs = pOp->readTuplesExclusive(); - if( rs == 0 ) { + if( pOp->readTuplesExclusive() ) { ERR(pScanTrans->getNdbError()); m_ndb.closeTransaction(pScanTrans); return NDBT_FAILED; @@ -1888,7 +1881,7 @@ int Bank::findTransactionsToPurge(const Uint64 glTime, int eof; int rows = 0; int rowsFound = 0; - eof = rs->nextResult(); + eof = pOp->nextResult(); while(eof == 0){ rows++; @@ -1898,7 +1891,7 @@ int Bank::findTransactionsToPurge(const Uint64 glTime, if (a == accountType && t == glTime){ rowsFound++; // One record found - check = rs->deleteTuple(pTrans); + check = pOp->deleteCurrentTuple(pTrans); if (check == -1){ ERR(m_ndb.getNdbError()); m_ndb.closeTransaction(pScanTrans); @@ -1913,7 +1906,7 @@ int Bank::findTransactionsToPurge(const Uint64 glTime, return NDBT_FAILED; } } - eof = rs->nextResult(); + eof = pOp->nextResult(); } if (eof == -1) { ERR(pScanTrans->getNdbError()); @@ -2371,8 +2364,7 @@ int Bank::getSumAccounts(Uint32 &sumAccounts, return NDBT_FAILED; } - NdbResultSet * rs = pOp->readTuplesExclusive(); - if( rs == 0 ) { + if( pOp->readTuplesExclusive() ) { ERR(pScanTrans->getNdbError()); m_ndb.closeTransaction(pScanTrans); return NDBT_FAILED; @@ -2407,7 +2399,7 @@ int Bank::getSumAccounts(Uint32 &sumAccounts, } int eof; - eof = rs->nextResult(); + eof = pOp->nextResult(); while(eof == 0){ Uint32 b = balanceRec->u_32_value(); @@ -2419,7 +2411,7 @@ int Bank::getSumAccounts(Uint32 &sumAccounts, // << ", sum="<< sumAccounts << endl; // Take over the operation so that the lock is kept in db - NdbOperation* pLockOp = rs->updateTuple(pTrans); + NdbOperation* pLockOp = pOp->updateCurrentTuple(pTrans); if (pLockOp == NULL){ ERR(m_ndb.getNdbError()); m_ndb.closeTransaction(pScanTrans); @@ -2445,7 +2437,7 @@ int Bank::getSumAccounts(Uint32 &sumAccounts, return NDBT_FAILED; } - eof = rs->nextResult(); + eof = pOp->nextResult(); } if (eof == -1) { ERR(pScanTrans->getNdbError()); diff --git a/ndb/test/ndbapi/bank/Bank.hpp b/ndb/test/ndbapi/bank/Bank.hpp index 14e01df29d5..b80f02dae97 100644 --- a/ndb/test/ndbapi/bank/Bank.hpp +++ b/ndb/test/ndbapi/bank/Bank.hpp @@ -27,7 +27,7 @@ class Bank { public: - Bank(bool init = true); + Bank(Ndb_cluster_connection&, bool init = true); int createAndLoadBank(bool overWrite, int num_accounts=10); int dropBank(); diff --git a/ndb/test/ndbapi/bank/BankLoad.cpp b/ndb/test/ndbapi/bank/BankLoad.cpp index 39dc8097115..34947019a51 100644 --- a/ndb/test/ndbapi/bank/BankLoad.cpp +++ b/ndb/test/ndbapi/bank/BankLoad.cpp @@ -321,7 +321,7 @@ int Bank::loadGl(){ m_ndb.closeTransaction(pTrans); return NDBT_OK; -}; +} int Bank::getBalanceForAccountType(const Uint32 accountType, @@ -342,8 +342,7 @@ int Bank::getBalanceForAccountType(const Uint32 accountType, return NDBT_FAILED; } - NdbResultSet* rs = pOp->readTuples(); - if( rs == 0 ) { + if( pOp->readTuples() ) { ERR(pScanTrans->getNdbError()); m_ndb.closeTransaction(pScanTrans); return NDBT_FAILED; @@ -379,7 +378,7 @@ int Bank::getBalanceForAccountType(const Uint32 accountType, int eof; int rows = 0; - eof = rs->nextResult(); + eof = pOp->nextResult(); while(eof == 0){ rows++; @@ -391,7 +390,7 @@ int Bank::getBalanceForAccountType(const Uint32 accountType, balance += b; } - eof = rs->nextResult(); + eof = pOp->nextResult(); } if (eof == -1) { ERR(pScanTrans->getNdbError()); @@ -460,7 +459,7 @@ int Bank::loadAccountType(){ m_ndb.closeTransaction(pTrans); return NDBT_OK; -}; +} /** * Load ACCOUNT table diff --git a/ndb/test/ndbapi/bank/bankCreator.cpp b/ndb/test/ndbapi/bank/bankCreator.cpp index 301d8bda6d2..257255babc8 100644 --- a/ndb/test/ndbapi/bank/bankCreator.cpp +++ b/ndb/test/ndbapi/bank/bankCreator.cpp @@ -43,7 +43,13 @@ int main(int argc, const char** argv){ return NDBT_ProgramExit(NDBT_WRONGARGS); } - Bank bank; + Ndb_cluster_connection con; + if(con.connect(12, 5, 1) != 0) + { + return NDBT_ProgramExit(NDBT_FAILED); + } + + Bank bank(con); int overWriteExisting = true; if (bank.createAndLoadBank(overWriteExisting) != NDBT_OK) return NDBT_ProgramExit(NDBT_FAILED); diff --git a/ndb/test/ndbapi/bank/bankMakeGL.cpp b/ndb/test/ndbapi/bank/bankMakeGL.cpp index 9e2762ed8ae..cf373481e3e 100644 --- a/ndb/test/ndbapi/bank/bankMakeGL.cpp +++ b/ndb/test/ndbapi/bank/bankMakeGL.cpp @@ -43,7 +43,13 @@ int main(int argc, const char** argv){ return NDBT_ProgramExit(NDBT_WRONGARGS); } - Bank bank; + Ndb_cluster_connection con; + if(con.connect(12, 5, 1) != 0) + { + return NDBT_ProgramExit(NDBT_FAILED); + } + + Bank bank(con); if (bank.performMakeGLs() != 0) return NDBT_ProgramExit(NDBT_FAILED); diff --git a/ndb/test/ndbapi/bank/bankSumAccounts.cpp b/ndb/test/ndbapi/bank/bankSumAccounts.cpp index b576161b27b..034f70f8f95 100644 --- a/ndb/test/ndbapi/bank/bankSumAccounts.cpp +++ b/ndb/test/ndbapi/bank/bankSumAccounts.cpp @@ -43,7 +43,13 @@ int main(int argc, const char** argv){ return NDBT_ProgramExit(NDBT_WRONGARGS); } - Bank bank; + Ndb_cluster_connection con; + if(con.connect(12, 5, 1) != 0) + { + return NDBT_ProgramExit(NDBT_FAILED); + } + + Bank bank(con); if (bank.performSumAccounts() != 0) return NDBT_ProgramExit(NDBT_FAILED); diff --git a/ndb/test/ndbapi/bank/bankTimer.cpp b/ndb/test/ndbapi/bank/bankTimer.cpp index 874afd9c21e..298f85e1e43 100644 --- a/ndb/test/ndbapi/bank/bankTimer.cpp +++ b/ndb/test/ndbapi/bank/bankTimer.cpp @@ -46,7 +46,13 @@ int main(int argc, const char** argv){ return NDBT_ProgramExit(NDBT_WRONGARGS); } - Bank bank; + Ndb_cluster_connection con; + if(con.connect(12, 5, 1) != 0) + { + return NDBT_ProgramExit(NDBT_FAILED); + } + + Bank bank(con); if (bank.performIncreaseTime(_wait) != 0) return NDBT_ProgramExit(NDBT_FAILED); diff --git a/ndb/test/ndbapi/bank/bankTransactionMaker.cpp b/ndb/test/ndbapi/bank/bankTransactionMaker.cpp index e5ff9aeb918..f8e646b6553 100644 --- a/ndb/test/ndbapi/bank/bankTransactionMaker.cpp +++ b/ndb/test/ndbapi/bank/bankTransactionMaker.cpp @@ -46,7 +46,13 @@ int main(int argc, const char** argv){ return NDBT_ProgramExit(NDBT_WRONGARGS); } - Bank bank; + Ndb_cluster_connection con; + if(con.connect(12, 5, 1) != 0) + { + return NDBT_ProgramExit(NDBT_FAILED); + } + + Bank bank(con); if (bank.performTransactions(_wait) != 0) return NDBT_ProgramExit(NDBT_FAILED); diff --git a/ndb/test/ndbapi/bank/bankValidateAllGLs.cpp b/ndb/test/ndbapi/bank/bankValidateAllGLs.cpp index cf298ecc8e3..0c268121d8a 100644 --- a/ndb/test/ndbapi/bank/bankValidateAllGLs.cpp +++ b/ndb/test/ndbapi/bank/bankValidateAllGLs.cpp @@ -44,7 +44,13 @@ int main(int argc, const char** argv){ return NDBT_ProgramExit(NDBT_WRONGARGS); } - Bank bank; + Ndb_cluster_connection con; + if(con.connect(12, 5, 1) != 0) + { + return NDBT_ProgramExit(NDBT_FAILED); + } + + Bank bank(con); if (bank.performValidateAllGLs() != 0) return NDBT_ProgramExit(NDBT_FAILED); diff --git a/ndb/test/ndbapi/bank/testBank.cpp b/ndb/test/ndbapi/bank/testBank.cpp index 3ef2799cd3c..6be66d528b1 100644 --- a/ndb/test/ndbapi/bank/testBank.cpp +++ b/ndb/test/ndbapi/bank/testBank.cpp @@ -32,7 +32,7 @@ #include "Bank.hpp" int runCreateBank(NDBT_Context* ctx, NDBT_Step* step){ - Bank bank; + Bank bank(ctx->m_cluster_connection); int overWriteExisting = true; if (bank.createAndLoadBank(overWriteExisting) != NDBT_OK) return NDBT_FAILED; @@ -40,7 +40,7 @@ int runCreateBank(NDBT_Context* ctx, NDBT_Step* step){ } int runBankTimer(NDBT_Context* ctx, NDBT_Step* step){ - Bank bank; + Bank bank(ctx->m_cluster_connection); int wait = 30; // Max seconds between each "day" int yield = 1; // Loops before bank returns @@ -51,7 +51,7 @@ int runBankTimer(NDBT_Context* ctx, NDBT_Step* step){ } int runBankTransactions(NDBT_Context* ctx, NDBT_Step* step){ - Bank bank; + Bank bank(ctx->m_cluster_connection); int wait = 10; // Max ms between each transaction int yield = 100; // Loops before bank returns @@ -62,7 +62,7 @@ int runBankTransactions(NDBT_Context* ctx, NDBT_Step* step){ } int runBankGL(NDBT_Context* ctx, NDBT_Step* step){ - Bank bank; + Bank bank(ctx->m_cluster_connection); int yield = 20; // Loops before bank returns int result = NDBT_OK; @@ -76,7 +76,7 @@ int runBankGL(NDBT_Context* ctx, NDBT_Step* step){ } int runBankSum(NDBT_Context* ctx, NDBT_Step* step){ - Bank bank; + Bank bank(ctx->m_cluster_connection); int wait = 2000; // Max ms between each sum of accounts int yield = 1; // Loops before bank returns int result = NDBT_OK; @@ -91,7 +91,7 @@ int runBankSum(NDBT_Context* ctx, NDBT_Step* step){ } int runDropBank(NDBT_Context* ctx, NDBT_Step* step){ - Bank bank; + Bank bank(ctx->m_cluster_connection); if (bank.dropBank() != NDBT_OK) return NDBT_FAILED; return NDBT_OK; diff --git a/ndb/test/ndbapi/bench/userInterface.cpp b/ndb/test/ndbapi/bench/userInterface.cpp index 683552c3133..35e88183230 100644 --- a/ndb/test/ndbapi/bench/userInterface.cpp +++ b/ndb/test/ndbapi/bench/userInterface.cpp @@ -173,7 +173,7 @@ create_table_server(Ndb * pNdb){ String, MMBased, NotNullAttribute, - NormalStorageAttribute, + 0, 0, 1, 16); @@ -376,7 +376,7 @@ create_table_subscriber(Ndb * pNdb){ String, MMBased, NotNullAttribute, - NormalStorageAttribute, + 0, 0, 1, 16); @@ -494,7 +494,7 @@ create_table_session(Ndb * pNdb){ String, MMBased, NotNullAttribute, - NormalStorageAttribute, + 0, 0, 1, 16); diff --git a/ndb/test/ndbapi/bench/userInterface.h b/ndb/test/ndbapi/bench/userInterface.h index 9e3b6f8f2a5..bad61fcf171 100644 --- a/ndb/test/ndbapi/bench/userInterface.h +++ b/ndb/test/ndbapi/bench/userInterface.h @@ -101,7 +101,7 @@ extern "C" { typedef struct { struct Ndb_cluster_connection* pNCC; struct Ndb * pNDB; - struct NdbConnection * pCurrTrans; + struct NdbTransaction * pCurrTrans; } UserHandle; /*************************************************************** diff --git a/ndb/test/ndbapi/create_all_tabs.cpp b/ndb/test/ndbapi/create_all_tabs.cpp index 97236b98b36..f06078d67a2 100644 --- a/ndb/test/ndbapi/create_all_tabs.cpp +++ b/ndb/test/ndbapi/create_all_tabs.cpp @@ -47,7 +47,12 @@ int main(int argc, const char** argv){ } // Connect to Ndb - Ndb MyNdb( "TEST_DB" ); + Ndb_cluster_connection con; + if(con.connect(12, 5, 1) != 0) + { + return NDBT_ProgramExit(NDBT_FAILED); + } + Ndb MyNdb(&con, "TEST_DB" ); if(MyNdb.init() != 0){ ERR(MyNdb.getNdbError()); diff --git a/ndb/test/ndbapi/create_tab.cpp b/ndb/test/ndbapi/create_tab.cpp index 283c83d30e0..b35c8655236 100644 --- a/ndb/test/ndbapi/create_tab.cpp +++ b/ndb/test/ndbapi/create_tab.cpp @@ -77,8 +77,12 @@ int main(int argc, const char** argv){ */ // Connect to Ndb - Ndb::setConnectString(_connectstr); - Ndb MyNdb( "TEST_DB" ); + Ndb_cluster_connection con(_connectstr); + if(con.connect(12, 5, 1) != 0) + { + return NDBT_ProgramExit(NDBT_FAILED); + } + Ndb MyNdb(&con, "TEST_DB" ); if(MyNdb.init() != 0){ ERR(MyNdb.getNdbError()); diff --git a/ndb/test/ndbapi/drop_all_tabs.cpp b/ndb/test/ndbapi/drop_all_tabs.cpp index c024a81a5e6..f12d750916e 100644 --- a/ndb/test/ndbapi/drop_all_tabs.cpp +++ b/ndb/test/ndbapi/drop_all_tabs.cpp @@ -40,7 +40,13 @@ int main(int argc, const char** argv){ } // Connect to Ndb - Ndb MyNdb( "TEST_DB" ); + Ndb_cluster_connection con; + if(con.connect(12, 5, 1) != 0) + { + return NDBT_ProgramExit(NDBT_FAILED); + } + + Ndb MyNdb(&con, "TEST_DB" ); if(MyNdb.init() != 0){ ERR(MyNdb.getNdbError()); diff --git a/ndb/test/ndbapi/flexAsynch.cpp b/ndb/test/ndbapi/flexAsynch.cpp index 4b87b2c70ed..8a7dbec1561 100644 --- a/ndb/test/ndbapi/flexAsynch.cpp +++ b/ndb/test/ndbapi/flexAsynch.cpp @@ -16,6 +16,7 @@ +#include <ndb_global.h> #include "NdbApi.hpp" #include <NdbSchemaCon.hpp> #include <NdbMain.h> @@ -143,6 +144,8 @@ tellThreads(StartType what) ThreadStart[i] = what; } +static Ndb_cluster_connection *g_cluster_connection= 0; + NDB_COMMAND(flexAsynch, "flexAsynch", "flexAsynch", "flexAsynch", 65535) { ndb_init(); @@ -200,7 +203,14 @@ NDB_COMMAND(flexAsynch, "flexAsynch", "flexAsynch", "flexAsynch", 65535) setAttrNames(); setTableNames(); - Ndb * pNdb = new Ndb("TEST_DB"); + Ndb_cluster_connection con; + if(con.connect(12, 5, 1) != 0) + { + return NDBT_ProgramExit(NDBT_FAILED); + } + g_cluster_connection= &con; + + Ndb * pNdb = new Ndb(g_cluster_connection, "TEST_DB"); pNdb->init(); tNodeId = pNdb->getNodeId(); @@ -225,7 +235,7 @@ NDB_COMMAND(flexAsynch, "flexAsynch", "flexAsynch", "flexAsynch", 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, @@ -468,7 +478,7 @@ threadLoop(void* ThreadData) StartType tType; ThreadNdb* tabThread = (ThreadNdb*)ThreadData; int threadNo = tabThread->ThreadNo; - localNdb = new Ndb("TEST_DB"); + localNdb = new Ndb(g_cluster_connection, "TEST_DB"); localNdb->init(1024); localNdb->waitUntilReady(10000); unsigned int threadBase = (threadNo << 16) + tNodeId ; diff --git a/ndb/test/ndbapi/flexBench.cpp b/ndb/test/ndbapi/flexBench.cpp index cc2bfb391da..abddecfdc40 100644 --- a/ndb/test/ndbapi/flexBench.cpp +++ b/ndb/test/ndbapi/flexBench.cpp @@ -49,6 +49,7 @@ Arguments: * *************************************************** */ +#include <ndb_global.h> #include "NdbApi.hpp" #include <NdbMain.h> @@ -279,6 +280,8 @@ tellThreads(ThreadData* pt, StartType what) pt[i].threadStart = what; } +static Ndb_cluster_connection *g_cluster_connection= 0; + NDB_COMMAND(flexBench, "flexBench", "flexBench", "flexbench", 65535) { ndb_init(); @@ -326,8 +329,16 @@ NDB_COMMAND(flexBench, "flexBench", "flexBench", "flexbench", 65535) NdbThread_SetConcurrencyLevel(tNoOfThreads + 2); + Ndb_cluster_connection con; + if(con.connect(12, 5, 1) != 0) + { + return NDBT_ProgramExit(NDBT_FAILED); + } + + g_cluster_connection= &con; + Ndb* pNdb; - pNdb = new Ndb( "TEST_DB" ); + pNdb = new Ndb(&con, "TEST_DB" ); pNdb->init(); tNodeId = pNdb->getNodeId(); @@ -605,7 +616,7 @@ static void* flexBenchThread(void* pArg) attrValue = (int*)malloc(nReadBuffSize) ; attrRefValue = (int*)malloc(nRefBuffSize) ; pOps = (NdbOperation**)malloc(tNoOfTables*sizeof(NdbOperation*)) ; - pNdb = new Ndb( "TEST_DB" ); + pNdb = new Ndb(g_cluster_connection, "TEST_DB" ); if(!attrValue || !attrRefValue || !pOps || !pNdb){ // Check allocations to make sure we got all the memory we asked for diff --git a/ndb/test/ndbapi/flexHammer.cpp b/ndb/test/ndbapi/flexHammer.cpp index 13cd2d5e561..f254b1e5ccf 100644 --- a/ndb/test/ndbapi/flexHammer.cpp +++ b/ndb/test/ndbapi/flexHammer.cpp @@ -47,6 +47,7 @@ Revision history: * *************************************************** */ +#include <ndb_global.h> #include <NdbApi.hpp> #include <NdbMain.h> @@ -174,6 +175,8 @@ tellThreads(ThreadNdb* threadArrayP, const StartType what) threadArrayP[i].threadStart = what; } // for } // tellThreads + +static Ndb_cluster_connection *g_cluster_connection= 0; NDB_COMMAND(flexHammer, "flexHammer", "flexHammer", "flexHammer", 65535) //main(int argc, const char** argv) @@ -213,7 +216,13 @@ NDB_COMMAND(flexHammer, "flexHammer", "flexHammer", "flexHammer", 65535) // NdbThread_SetConcurrencyLevel(tNoOfThreads + 2); // Create and init Ndb object - pMyNdb = new Ndb("TEST_DB"); + Ndb_cluster_connection con; + if(con.connect(12, 5, 1) != 0) + { + return NDBT_ProgramExit(NDBT_FAILED); + } + g_cluster_connection= &con; + pMyNdb = new Ndb(g_cluster_connection, "TEST_DB"); pMyNdb->init(); // Wait for Ndb to become ready @@ -345,7 +354,7 @@ flexHammerThread(void* pArg) for (i = 0; i < MAXATTRSIZE; i++) attrValue[i] = 0; // Ndb object for each thread - pMyNdb = new Ndb( "TEST_DB" ); + pMyNdb = new Ndb(g_cluster_connection, "TEST_DB" ); pMyNdb->init(); if (pMyNdb->waitUntilReady(10000) != 0) { // Error, NDB is not ready diff --git a/ndb/test/ndbapi/flexTT.cpp b/ndb/test/ndbapi/flexTT.cpp index 8d5be2bb399..7cd5ac8e3b4 100644 --- a/ndb/test/ndbapi/flexTT.cpp +++ b/ndb/test/ndbapi/flexTT.cpp @@ -169,6 +169,8 @@ tellThreads(StartType what) ThreadStart[i] = what; } +static Ndb_cluster_connection *g_cluster_connection= 0; + NDB_COMMAND(flexTT, "flexTT", "flexTT", "flexTT", 65535) { ndb_init(); @@ -226,7 +228,14 @@ NDB_COMMAND(flexTT, "flexTT", "flexTT", "flexTT", 65535) setAttrNames(); setTableNames(); - Ndb * pNdb = new Ndb("TEST_DB"); + Ndb_cluster_connection con; + if(con.connect(12, 5, 1) != 0) + { + return NDBT_ProgramExit(NDBT_FAILED); + } + g_cluster_connection= &con; + + Ndb * pNdb = new Ndb(g_cluster_connection, "TEST_DB"); pNdb->init(); tNodeId = pNdb->getNodeId(); @@ -334,7 +343,7 @@ threadLoop(void* ThreadData) void * mem = malloc(sizeof(TransNdb)*tNoOfParallelTrans); TransNdb* pTransData = (TransNdb*)mem; - localNdb = new Ndb("TEST_DB"); + localNdb = new Ndb(g_cluster_connection, "TEST_DB"); localNdb->init(1024); localNdb->waitUntilReady(); diff --git a/ndb/test/ndbapi/flex_bench_mysql.cpp b/ndb/test/ndbapi/flex_bench_mysql.cpp index c15175bfb00..3efb7ee2094 100644 --- a/ndb/test/ndbapi/flex_bench_mysql.cpp +++ b/ndb/test/ndbapi/flex_bench_mysql.cpp @@ -397,6 +397,7 @@ NDB_COMMAND(flexBench, "flexBench", "flexBench", "flexbench", 65535) ndbout << "Connect failed" <<endl; returnValue = NDBT_FAILED; } + mysql.reconnect= 1; } if(returnValue == NDBT_OK){ mysql_set_server_option(&mysql, MYSQL_OPTION_MULTI_STATEMENTS_ON); @@ -712,6 +713,7 @@ static void* flexBenchThread(void* pArg) ndbout << "failed" << endl; return 0; } + mysql.reconnect= 1; ndbout << "ok" << endl; int r; diff --git a/ndb/test/ndbapi/slow_select.cpp b/ndb/test/ndbapi/slow_select.cpp index 625dbc34457..8d615fa5771 100644 --- a/ndb/test/ndbapi/slow_select.cpp +++ b/ndb/test/ndbapi/slow_select.cpp @@ -1,4 +1,5 @@ +#include <ndb_global.h> #include <NdbApi.hpp> #include <NdbOut.hpp> #include <NdbTick.h> @@ -8,18 +9,17 @@ S_Scan { const char * m_table; const char * m_index; NdbIndexScanOperation * m_scan; - NdbResultSet * m_result; Uint32 metaid; Uint32 match_count; Uint32 row_count; }; static S_Scan g_scans[] = { - { "affiliatestometa", "ind_affiliatestometa", 0, 0, 0, 0, 0 }, - { "media", "metaid", 0, 0, 0, 0, 0 }, - { "meta", "PRIMARY", 0, 0, 0, 0, 0 }, - { "artiststometamap", "PRIMARY", 0, 0, 0, 0, 0 }, - { "subgenrestometamap", "metaid", 0, 0, 0, 0, 0 } + { "affiliatestometa", "ind_affiliatestometa", 0, 0, 0, 0 }, + { "media", "metaid", 0, 0, 0, 0 }, + { "meta", "PRIMARY", 0, 0, 0, 0 }, + { "artiststometamap", "PRIMARY", 0, 0, 0, 0 }, + { "subgenrestometamap", "metaid", 0, 0, 0, 0 } }; #define require(x) if(!(x)) { ndbout << "LINE: " << __LINE__ << endl;abort(); } @@ -37,7 +37,14 @@ static void lookup(); int main(void){ ndb_init(); - Ndb g_ndb("test"); + + Ndb_cluster_connection con; + if(con.connect(12, 5, 1) != 0) + { + return 1; + } + + Ndb g_ndb(&con, "test"); g_ndb.init(1024); require(g_ndb.waitUntilReady() == 0); @@ -58,9 +65,8 @@ main(void){ g_scans[i].m_table); NdbIndexScanOperation* scan = g_scans[i].m_scan; require(scan); - g_scans[i].m_result = scan->readTuples(NdbScanOperation::LM_CommittedRead, - 0, 0, true); - require(g_scans[i].m_result); + require(scan->readTuples(NdbScanOperation::LM_CommittedRead, + 0, 0, true) == 0); } require(!g_scans[0].m_scan->setBound((Uint32)0, @@ -125,7 +131,7 @@ main(void){ //ndbout_c("%s - %d", g_scans[i].m_table, g_scans[i].metaid); for(i = 0; i<prev_F_sz; i++){ - int res = F[i]->m_result->nextResult(); + int res = F[i]->m_scan->nextResult(); if(res == -1) abort(); diff --git a/ndb/test/ndbapi/testBackup.cpp b/ndb/test/ndbapi/testBackup.cpp index 14198c250c7..1ab348e735f 100644 --- a/ndb/test/ndbapi/testBackup.cpp +++ b/ndb/test/ndbapi/testBackup.cpp @@ -271,7 +271,7 @@ int runDropTable(NDBT_Context* ctx, NDBT_Step* step){ #include "bank/Bank.hpp" int runCreateBank(NDBT_Context* ctx, NDBT_Step* step){ - Bank bank; + Bank bank(ctx->m_cluster_connection); int overWriteExisting = true; if (bank.createAndLoadBank(overWriteExisting, 10) != NDBT_OK) return NDBT_FAILED; @@ -279,7 +279,7 @@ int runCreateBank(NDBT_Context* ctx, NDBT_Step* step){ } int runBankTimer(NDBT_Context* ctx, NDBT_Step* step){ - Bank bank; + Bank bank(ctx->m_cluster_connection); int wait = 30; // Max seconds between each "day" int yield = 1; // Loops before bank returns @@ -290,7 +290,7 @@ int runBankTimer(NDBT_Context* ctx, NDBT_Step* step){ } int runBankTransactions(NDBT_Context* ctx, NDBT_Step* step){ - Bank bank; + Bank bank(ctx->m_cluster_connection); int wait = 10; // Max ms between each transaction int yield = 100; // Loops before bank returns @@ -301,7 +301,7 @@ int runBankTransactions(NDBT_Context* ctx, NDBT_Step* step){ } int runBankGL(NDBT_Context* ctx, NDBT_Step* step){ - Bank bank; + Bank bank(ctx->m_cluster_connection); int yield = 20; // Loops before bank returns int result = NDBT_OK; @@ -315,7 +315,7 @@ int runBankGL(NDBT_Context* ctx, NDBT_Step* step){ } int runBankSum(NDBT_Context* ctx, NDBT_Step* step){ - Bank bank; + Bank bank(ctx->m_cluster_connection); int wait = 2000; // Max ms between each sum of accounts int yield = 1; // Loops before bank returns int result = NDBT_OK; @@ -330,7 +330,7 @@ int runBankSum(NDBT_Context* ctx, NDBT_Step* step){ } int runDropBank(NDBT_Context* ctx, NDBT_Step* step){ - Bank bank; + Bank bank(ctx->m_cluster_connection); if (bank.dropBank() != NDBT_OK) return NDBT_FAILED; return NDBT_OK; @@ -404,7 +404,7 @@ int runRestoreBankAndVerify(NDBT_Context* ctx, NDBT_Step* step){ // To erase all tables from cache(s) // To be removed, maybe replaced by ndb.invalidate(); { - Bank bank; + Bank bank(ctx->m_cluster_connection); if (bank.dropBank() != NDBT_OK){ result = NDBT_FAILED; @@ -427,7 +427,7 @@ int runRestoreBankAndVerify(NDBT_Context* ctx, NDBT_Step* step){ ndbout << "Backup " << backupId << " restored" << endl; // Let bank verify - Bank bank; + Bank bank(ctx->m_cluster_connection); int wait = 0; int yield = 1; diff --git a/ndb/test/ndbapi/testBitfield.cpp b/ndb/test/ndbapi/testBitfield.cpp new file mode 100644 index 00000000000..e26f495f5a4 --- /dev/null +++ b/ndb/test/ndbapi/testBitfield.cpp @@ -0,0 +1,198 @@ + +#include <ndb_global.h> +#include <ndb_opts.h> +#include <NDBT.hpp> +#include <NdbApi.hpp> +#include <HugoTransactions.hpp> + +static const char* _dbname = "TEST_DB"; +static int g_loops = 7; + +static void usage() +{ + ndb_std_print_version(); +} +#if 0 +static my_bool +get_one_option(int optid, const struct my_option *opt __attribute__((unused)), + const char *argument) +{ + return ndb_std_get_one_option(optid, opt, argument ? argument : + "d:t:O,/tmp/testBitfield.trace"); +} +#endif + +static const NdbDictionary::Table* create_random_table(Ndb*); +static int transactions(Ndb*, const NdbDictionary::Table* tab); +static int unique_indexes(Ndb*, const NdbDictionary::Table* tab); +static int ordered_indexes(Ndb*, const NdbDictionary::Table* tab); +static int node_restart(Ndb*, const NdbDictionary::Table* tab); +static int system_restart(Ndb*, const NdbDictionary::Table* tab); + +int +main(int argc, char** argv){ + NDB_INIT(argv[0]); + const char *load_default_groups[]= { "mysql_cluster",0 }; + load_defaults("my",load_default_groups,&argc,&argv); + int ho_error; + + argc--; + argv++; + + Ndb_cluster_connection con(opt_connect_str); + if(con.connect(12, 5, 1)) + { + return NDBT_ProgramExit(NDBT_FAILED); + } + + + Ndb* pNdb; + pNdb = new Ndb(&con, _dbname); + pNdb->init(); + while (pNdb->waitUntilReady() != 0); + int res = NDBT_FAILED; + + NdbDictionary::Dictionary * dict = pNdb->getDictionary(); + + const NdbDictionary::Table* pTab = 0; + for (int i = 0; i < (argc ? argc : g_loops) ; i++) + { + res = NDBT_FAILED; + if(argc == 0) + { + pTab = create_random_table(pNdb); + } + else + { + dict->dropTable(argv[i]); + NDBT_Tables::createTable(pNdb, argv[i]); + pTab = dict->getTable(argv[i]); + } + + if (pTab == 0) + { + ndbout << "Failed to create table" << endl; + ndbout << dict->getNdbError() << endl; + break; + } + + if(transactions(pNdb, pTab)) + break; + + if(unique_indexes(pNdb, pTab)) + break; + + if(ordered_indexes(pNdb, pTab)) + break; + + if(node_restart(pNdb, pTab)) + break; + + if(system_restart(pNdb, pTab)) + break; + + dict->dropTable(pTab->getName()); + res = NDBT_OK; + } + + if(res != NDBT_OK && pTab) + { + dict->dropTable(pTab->getName()); + } + + delete pNdb; + return NDBT_ProgramExit(res); +} + +static +const NdbDictionary::Table* +create_random_table(Ndb* pNdb) +{ + do { + NdbDictionary::Table tab; + Uint32 cols = 1 + (rand() % (NDB_MAX_ATTRIBUTES_IN_TABLE - 1)); + Uint32 keys = NDB_MAX_NO_OF_ATTRIBUTES_IN_KEY; + Uint32 length = 4090; + Uint32 key_size = NDB_MAX_KEYSIZE_IN_WORDS; + + BaseString name; + name.assfmt("TAB_%d", rand() & 65535); + tab.setName(name.c_str()); + for(int i = 0; i<cols && length > 2; i++) + { + NdbDictionary::Column col; + name.assfmt("COL_%d", i); + col.setName(name.c_str()); + if(i == 0 || i == 1) + { + col.setType(NdbDictionary::Column::Unsigned); + col.setLength(1); + col.setNullable(false); + col.setPrimaryKey(i == 0); + tab.addColumn(col); + continue; + } + + col.setType(NdbDictionary::Column::Bit); + + Uint32 len = 1 + (rand() % (length - 1)); + col.setLength(len); length -= len; + int nullable = (rand() >> 16) & 1; + col.setNullable(nullable); length -= nullable; + col.setPrimaryKey(false); + tab.addColumn(col); + } + + pNdb->getDictionary()->dropTable(tab.getName()); + if(pNdb->getDictionary()->createTable(tab) == 0) + { + ndbout << (NDBT_Table&)tab << endl; + return pNdb->getDictionary()->getTable(tab.getName()); + } + } while(0); + return 0; +} + +static +int +transactions(Ndb* pNdb, const NdbDictionary::Table* tab) +{ + int i = 0; + HugoTransactions trans(* tab); + i |= trans.loadTable(pNdb, 1000); + i |= trans.pkReadRecords(pNdb, 1000, 13); + i |= trans.scanReadRecords(pNdb, 1000, 25); + i |= trans.pkUpdateRecords(pNdb, 1000, 37); + i |= trans.scanUpdateRecords(pNdb, 1000, 25); + i |= trans.pkDelRecords(pNdb, 500, 23); + i |= trans.clearTable(pNdb); + return i; +} + +static +int +unique_indexes(Ndb* pNdb, const NdbDictionary::Table* tab) +{ + return 0; +} + +static +int +ordered_indexes(Ndb* pNdb, const NdbDictionary::Table* tab) +{ + return 0; +} + +static +int +node_restart(Ndb* pNdb, const NdbDictionary::Table* tab) +{ + return 0; +} + +static +int +system_restart(Ndb* pNdb, const NdbDictionary::Table* tab) +{ + return 0; +} diff --git a/ndb/test/ndbapi/testBlobs.cpp b/ndb/test/ndbapi/testBlobs.cpp index efbdceac5a6..a88d7d21820 100644 --- a/ndb/test/ndbapi/testBlobs.cpp +++ b/ndb/test/ndbapi/testBlobs.cpp @@ -23,14 +23,13 @@ #include <NdbOut.hpp> #include <NdbTest.hpp> #include <NdbTick.h> -#include <ndb/src/ndbapi/NdbBlobImpl.hpp> struct Bcol { bool m_nullable; unsigned m_inline; unsigned m_partsize; unsigned m_stripe; - char m_btname[NdbBlobImpl::BlobTableNameSize]; + char m_btname[200]; Bcol(bool a, unsigned b, unsigned c, unsigned d) : m_nullable(a), m_inline(b), @@ -741,10 +740,9 @@ verifyBlobTable(const Bcol& b, const Bval& v, Uint32 pk1, bool exists) NdbRecAttr* ra_pk; NdbRecAttr* ra_part; NdbRecAttr* ra_data; - NdbResultSet* rs; CHK((g_con = g_ndb->startTransaction()) != 0); CHK((g_ops = g_con->getNdbScanOperation(b.m_btname)) != 0); - CHK((rs = g_ops->readTuples()) != 0); + CHK(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); @@ -758,7 +756,7 @@ verifyBlobTable(const Bcol& b, const Bval& v, Uint32 pk1, bool exists) memset(seen, 0, partcount); while (1) { int ret; - CHK((ret = rs->nextResult()) == 0 || ret == 1); + CHK((ret = g_ops->nextResult()) == 0 || ret == 1); if (ret == 1) break; if (pk1 != ra_pk->u_32_value()) @@ -1106,14 +1104,13 @@ readScan(int style, bool idx) DBG("--- " << "readScan" << (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); } - CHK((rs = g_ops->readTuples(NdbScanOperation::LM_Read)) != 0); + CHK(g_ops->readTuples(NdbScanOperation::LM_Read) == 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); @@ -1129,7 +1126,7 @@ readScan(int style, bool idx) int ret; tup.m_pk1 = (Uint32)-1; memset(tup.m_pk2, 'x', g_opt.m_pk2len); - CHK((ret = rs->nextResult(true)) == 0 || ret == 1); + CHK((ret = g_ops->nextResult(true)) == 0 || ret == 1); if (ret == 1) break; DBG("readScan" << (idx ? "Idx" : "") << " pk1=" << hex << tup.m_pk1); @@ -1159,14 +1156,13 @@ updateScan(int style, bool idx) 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); } - CHK((rs = g_ops->readTuples(NdbScanOperation::LM_Exclusive)) != 0); + CHK(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); @@ -1176,7 +1172,7 @@ updateScan(int style, bool idx) int ret; tup.m_pk1 = (Uint32)-1; memset(tup.m_pk2, 'x', g_opt.m_pk2len); - CHK((ret = rs->nextResult(true)) == 0 || ret == 1); + CHK((ret = g_ops->nextResult(true)) == 0 || ret == 1); if (ret == 1) break; DBG("updateScan" << (idx ? "Idx" : "") << " pk1=" << hex << tup.m_pk1); @@ -1185,7 +1181,7 @@ updateScan(int style, bool idx) // calculate new blob values calcBval(g_tups[k], false); tup.copyfrom(g_tups[k]); - CHK((g_opr = rs->updateTuple()) != 0); + CHK((g_opr = g_ops->updateCurrentTuple()) != 0); CHK(getBlobHandles(g_opr) == 0); if (style == 0) { CHK(setBlobValue(tup) == 0); @@ -1212,14 +1208,13 @@ deleteScan(bool idx) { 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->getNdbIndexScanOperation(g_opt.m_x2name, g_opt.m_tname)) != 0); } - CHK((rs = g_ops->readTuples(NdbScanOperation::LM_Exclusive)) != 0); + CHK(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); @@ -1229,11 +1224,11 @@ deleteScan(bool idx) int ret; tup.m_pk1 = (Uint32)-1; memset(tup.m_pk2, 'x', g_opt.m_pk2len); - CHK((ret = rs->nextResult()) == 0 || ret == 1); + CHK((ret = g_ops->nextResult()) == 0 || ret == 1); if (ret == 1) break; DBG("deleteScan" << (idx ? "Idx" : "") << " pk1=" << hex << tup.m_pk1); - CHK(rs->deleteTuple() == 0); + CHK(g_ops->deleteCurrentTuple() == 0); CHK(g_con->execute(NoCommit) == 0); Uint32 k = tup.m_pk1 - g_opt.m_pk1off; CHK(k < g_opt.m_rows && g_tups[k].m_exists); @@ -1611,12 +1606,11 @@ testperf() // scan read char { DBG("--- scan read char ---"); - NdbResultSet* rs; Uint32 a; char b[20]; CHK((g_con = g_ndb->startTransaction()) != 0); CHK((g_ops = g_con->getNdbScanOperation(tab.getName())) != 0); - CHK((rs = g_ops->readTuples(NdbScanOperation::LM_Read)) != 0); + CHK(g_ops->readTuples(NdbScanOperation::LM_Read) == 0); CHK(g_ops->getValue(cA, (char*)&a) != 0); CHK(g_ops->getValue(cB, b) != 0); CHK(g_con->execute(NoCommit) == 0); @@ -1626,7 +1620,7 @@ testperf() a = (Uint32)-1; b[0] = 0; int ret; - CHK((ret = rs->nextResult(true)) == 0 || ret == 1); + CHK((ret = g_ops->nextResult(true)) == 0 || ret == 1); if (ret == 1) break; CHK(a < g_opt.m_rowsperf && strcmp(b, "b") == 0); @@ -1641,12 +1635,11 @@ testperf() // scan read text { DBG("--- read text ---"); - NdbResultSet* rs; Uint32 a; char c[20]; CHK((g_con = g_ndb->startTransaction()) != 0); CHK((g_ops = g_con->getNdbScanOperation(tab.getName())) != 0); - CHK((rs = g_ops->readTuples(NdbScanOperation::LM_Read)) != 0); + CHK(g_ops->readTuples(NdbScanOperation::LM_Read) == 0); CHK(g_ops->getValue(cA, (char*)&a) != 0); CHK((g_bh1 = g_ops->getBlobHandle(cC)) != 0); CHK(g_con->execute(NoCommit) == 0); @@ -1656,7 +1649,7 @@ testperf() a = (Uint32)-1; c[0] = 0; int ret; - CHK((ret = rs->nextResult(true)) == 0 || ret == 1); + CHK((ret = g_ops->nextResult(true)) == 0 || ret == 1); if (ret == 1) break; Uint32 m = 20; diff --git a/ndb/test/ndbapi/testDataBuffers.cpp b/ndb/test/ndbapi/testDataBuffers.cpp index 03d52252334..aaecb6ee61e 100644 --- a/ndb/test/ndbapi/testDataBuffers.cpp +++ b/ndb/test/ndbapi/testDataBuffers.cpp @@ -209,7 +209,7 @@ makeOff(int k) } static int -testcase(int flag) +testcase(Ndb_cluster_connection&cc, int flag) { ndbout << "--- case " << flag << " ---" << endl; sprintf(tab, "TB%02d", flag); @@ -254,7 +254,7 @@ testcase(int flag) ndbout << "tab=" << tab << " cols=" << attrcnt << " size max=" << smax << " tot=" << stot << endl; - ndb = new Ndb("TEST_DB"); + ndb = new Ndb(&cc, "TEST_DB"); if (ndb->init() != 0) return ndberror("init"); if (ndb->waitUntilReady(30) < 0) @@ -443,9 +443,9 @@ testcase(int flag) if ((con = ndb->startTransaction()) == 0) return ndberror("startTransaction key=%d", key); if ((op = sop = con->getNdbScanOperation(tab)) == 0) - return ndberror("getNdbOperation key=%d", key); - if ((rs = sop->readTuples(1)) == 0) - return ndberror("openScanRead key=%d", key); + return ndberror("getNdbOperation key=%d", key); + if (sop->readTuples(1)) + return ndberror("openScanRead key=%d", key); { col& c = ccol[0]; if (op->load_const_u32(1, key) < 0) @@ -488,7 +488,7 @@ testcase(int flag) if (con->execute(NoCommit) < 0) return ndberror("executeScan key=%d", key); int ret, cnt = 0; - while ((ret = rs->nextResult()) == 0) { + while ((ret = sop->nextResult()) == 0) { if (key != newkey) return ndberror("unexpected key=%d newkey=%d", key, newkey); for (i = 1; i < attrcnt; i++) { @@ -606,10 +606,17 @@ NDB_COMMAND(testDataBuffers, "testDataBuffers", "testDataBuffers", "testDataBuff } } unsigned ok = true; + + Ndb_cluster_connection con; + if(con.connect(12, 5, 1)) + { + return NDBT_ProgramExit(NDBT_FAILED); + } + for (i = 1; 0 == loopcnt || i <= loopcnt; i++) { ndbout << "=== loop " << i << " ===" << endl; for (int flag = 0; flag < (1<<testbits); flag++) { - if (testcase(flag) < 0) { + if (testcase(con, flag) < 0) { ok = false; if (! kontinue) goto out; diff --git a/ndb/test/ndbapi/testDeadlock.cpp b/ndb/test/ndbapi/testDeadlock.cpp index eb985e815ac..0070a7ecc83 100644 --- a/ndb/test/ndbapi/testDeadlock.cpp +++ b/ndb/test/ndbapi/testDeadlock.cpp @@ -49,7 +49,7 @@ printusage() static Opt g_opt; static NdbMutex *ndbout_mutex= NULL; - +static Ndb_cluster_connection *g_cluster_connection= 0; #define DBG(x) \ do { \ if (! g_opt.m_dbg) break; \ @@ -91,7 +91,6 @@ struct Thr { NdbConnection* m_con; NdbScanOperation* m_scanop; NdbIndexScanOperation* m_indexscanop; - NdbResultSet* m_rs; // Thr(int no); ~Thr(); @@ -136,7 +135,6 @@ Thr::Thr(int no) m_con = 0; m_scanop = 0; m_indexscanop = 0; - m_rs = 0; } Thr::~Thr() @@ -219,7 +217,7 @@ Thr::exit() static int runstep_connect(Thr& thr) { - Ndb* ndb = thr.m_ndb = new Ndb("TEST_DB"); + Ndb* ndb = thr.m_ndb = new Ndb(g_cluster_connection, "TEST_DB"); CHN(ndb, ndb->init() == 0); CHN(ndb, ndb->waitUntilReady() == 0); DBG(thr << " connected"); @@ -374,7 +372,7 @@ wl1822_tx2_scanXY(Thr& thr) 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->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); @@ -383,7 +381,7 @@ wl1822_tx2_scanXY(Thr& thr) DBG("before row " << row); int ret; wl1822_bufA = wl1822_bufB = ~0; - CHN(con, (ret = rs->nextResult(true)) == 0); + CHN(con, (ret = scanop->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]]); @@ -419,14 +417,13 @@ wl1822_tx2_scanZ_close(Thr& thr) 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); + assert(ndb != 0 && con != 0 && scanop != 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); + CHN(con, (ret = scanop->nextResult(true)) == 0 || ret == 1); if (ret == 1) break; DBG("got row " << row << " a=" << wl1822_bufA << " b=" << wl1822_bufB); @@ -467,7 +464,7 @@ wl1822_main(char scantx) // run the steps for (unsigned i = 0; i < wl1822_stepcount; i++) { DBG("step " << i << " start"); - for (int n = 0; n < thrcount; n++) { + for (n = 0; n < thrcount; n++) { Thr& thr = *thrlist[n]; Runstep runstep = wl1822_step[i][n]; if (runstep != 0) @@ -506,10 +503,18 @@ NDB_COMMAND(testOdbcDriver, "testDeadlock", "testDeadlock", "testDeadlock", 6553 printusage(); return NDBT_ProgramExit(NDBT_WRONGARGS); } + + Ndb_cluster_connection con; + if(con.connect(12, 5, 1) != 0) + { + return NDBT_ProgramExit(NDBT_FAILED); + } + g_cluster_connection= &con; + 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); diff --git a/ndb/test/ndbapi/testDict.cpp b/ndb/test/ndbapi/testDict.cpp index 5f88342705a..dd5846f0d62 100644 --- a/ndb/test/ndbapi/testDict.cpp +++ b/ndb/test/ndbapi/testDict.cpp @@ -125,6 +125,16 @@ int runCreateTheTable(NDBT_Context* ctx, NDBT_Step* step){ return NDBT_OK; } +int runDropTheTable(NDBT_Context* ctx, NDBT_Step* step){ + Ndb* pNdb = GETNDB(step); + const NdbDictionary::Table* pTab = ctx->getTab(); + + // Try to create table in db + pNdb->getDictionary()->dropTable(pTab->getName()); + + return NDBT_OK; +} + int runCreateTableWhenDbIsFull(NDBT_Context* ctx, NDBT_Step* step){ Ndb* pNdb = GETNDB(step); int result = NDBT_OK; @@ -418,103 +428,99 @@ int runUseTableUntilStopped(NDBT_Context* ctx, NDBT_Step* step){ } -int runCreateMaxTables(NDBT_Context* ctx, NDBT_Step* step){ - int failures = 0; +int +runCreateMaxTables(NDBT_Context* ctx, NDBT_Step* step) +{ char tabName[256]; int numTables = ctx->getProperty("tables", 1000); Ndb* pNdb = GETNDB(step); - - for (int i = 0; i < numTables && failures < 5; i++){ + NdbDictionary::Dictionary* pDic = pNdb->getDictionary(); + int i = 0; + for (i = 0; i < numTables; i++) { BaseString::snprintf(tabName, 256, "MAXTAB%d", i); - - if (pNdb->waitUntilReady(30) != 0){ + if (pNdb->waitUntilReady(30) != 0) { // Db is not ready, return with failure return NDBT_FAILED; } - const NdbDictionary::Table* pTab = ctx->getTab(); - ndbout << "|- " << tabName << endl; - + //ndbout << "|- " << tabName << endl; // Set new name for T1 NdbDictionary::Table newTab(* pTab); newTab.setName(tabName); - + // Drop any old (or try to) + (void)pDic->dropTable(newTab.getName()); // Try to create table in db - if (newTab.createTableInDb(pNdb) != 0){ - ndbout << tabName << " coult not be created"<< endl; - failures++; - continue; + if (newTab.createTableInDb(pNdb) != 0) { + ndbout << tabName << " could not be created: " + << pDic->getNdbError() << endl; + if (pDic->getNdbError().code == 707 || + pDic->getNdbError().code == 708 || + pDic->getNdbError().code == 826 || + pDic->getNdbError().code == 827) + break; + return NDBT_FAILED; } - // Verify that table exists in db const NdbDictionary::Table* pTab3 = NDBT_Table::discoverTableFromDb(pNdb, tabName) ; if (pTab3 == NULL){ - ndbout << tabName << " was not found in DB"<< endl; - failures++; - continue; + ndbout << tabName << " was not found in DB: " + << pDic->getNdbError() << endl; + return NDBT_FAILED; } - - if (pTab->equal(*pTab3) == false){ - ndbout << "It was not equal" << endl; - failures++; + if (! newTab.equal(*pTab3)) { + ndbout << "It was not equal" << endl; abort(); + return NDBT_FAILED; } - - int records = 1000; + int records = ctx->getNumRecords(); HugoTransactions hugoTrans(*pTab3); - if (hugoTrans.loadTable(pNdb, records) != 0){ + if (hugoTrans.loadTable(pNdb, records) != 0) { ndbout << "It can NOT be loaded" << endl; - } else{ - ndbout << "It can be loaded" << endl; - - UtilTransactions utilTrans(*pTab3); - if (utilTrans.clearTable(pNdb, records, 64) != 0){ - ndbout << "It can NOT be cleared" << endl; - } else{ - ndbout << "It can be cleared" << endl; - } + return NDBT_FAILED; + } + UtilTransactions utilTrans(*pTab3); + if (utilTrans.clearTable(pNdb, records, 64) != 0) { + ndbout << "It can NOT be cleared" << endl; + return NDBT_FAILED; } - } - if (pNdb->waitUntilReady(30) != 0){ + if (pNdb->waitUntilReady(30) != 0) { // Db is not ready, return with failure return NDBT_FAILED; } + ctx->setProperty("maxtables", i); // HURRAAA! return NDBT_OK; } -int runDropMaxTables(NDBT_Context* ctx, NDBT_Step* step){ - int result = NDBT_OK; +int runDropMaxTables(NDBT_Context* ctx, NDBT_Step* step) +{ char tabName[256]; - int numTables = ctx->getProperty("tables", 1000); + int numTables = ctx->getProperty("maxtables", (Uint32)0); Ndb* pNdb = GETNDB(step); - - for (int i = 0; i < numTables; i++){ + NdbDictionary::Dictionary* pDic = pNdb->getDictionary(); + for (int i = 0; i < numTables; i++) { BaseString::snprintf(tabName, 256, "MAXTAB%d", i); - - if (pNdb->waitUntilReady(30) != 0){ + if (pNdb->waitUntilReady(30) != 0) { // Db is not ready, return with failure return NDBT_FAILED; } - // Verify that table exists in db const NdbDictionary::Table* pTab3 = NDBT_Table::discoverTableFromDb(pNdb, tabName) ; - if (pTab3 == NULL){ - ndbout << tabName << " was not found in DB"<< endl; - continue; + if (pTab3 == NULL) { + ndbout << tabName << " was not found in DB: " + << pDic->getNdbError() << endl; + return NDBT_FAILED; } - - // Try to drop table in db - if (pNdb->getDictionary()->dropTable(pTab3->getName()) != 0){ - ndbout << tabName << " coult not be dropped"<< endl; - result = NDBT_FAILED; + if (pDic->dropTable(pTab3->getName()) != 0) { + ndbout << tabName << " could not be dropped: " + << pDic->getNdbError() << endl; + return NDBT_FAILED; } - } - return result; + return NDBT_OK; } int runTestFragmentTypes(NDBT_Context* ctx, NDBT_Step* step){ @@ -524,13 +530,6 @@ int runTestFragmentTypes(NDBT_Context* ctx, NDBT_Step* step){ int result = NDBT_OK; NdbRestarter restarter; - // enum FragmentType { - // Unknown = 0, - // Single = 1, ///< Only one fragment - // All = 2, ///< Default value. One fragment per node group - // AllLarge = 3 ///< Sixten fragments per node group. - // }; - if (pNdb->waitUntilReady(30) != 0){ // Db is not ready, return with failure return NDBT_FAILED; @@ -547,6 +546,7 @@ int runTestFragmentTypes(NDBT_Context* ctx, NDBT_Step* step){ if (newTab.createTableInDb(pNdb) != 0){ ndbout << newTab.getName() << " could not be created" << ", fragmentType = "<<fragTtype <<endl; + ndbout << pNdb->getDictionary()->getNdbError() << endl; return NDBT_FAILED; } @@ -564,13 +564,17 @@ int runTestFragmentTypes(NDBT_Context* ctx, NDBT_Step* step){ result = NDBT_FAILED; goto drop_the_tab; } - +/** + This test does not work since fragmentation is + decided by the kernel, hence the fragementation + attribute on the column will differ + if (newTab.equal(*pTab3) == false){ ndbout << "It was not equal" << endl; result = NDBT_FAILED; goto drop_the_tab; } - +*/ do { HugoTransactions hugoTrans(*pTab3); @@ -1005,10 +1009,10 @@ int runGetPrimaryKey(NDBT_Context* ctx, NDBT_Step* step){ struct ErrorCodes { int error_id; bool crash;}; ErrorCodes NF_codes[] = { - {6003, true}, - {6004, true}, + {6003, true} + ,{6004, true} //,6005, true, - {7173, false} + //{7173, false} }; int @@ -1027,17 +1031,6 @@ runNF1(NDBT_Context* ctx, NDBT_Step* step){ int result = NDBT_OK; - /** - * Need to run LCP at high rate otherwise - * packed replicas become "to many" - */ - int val = DumpStateOrd::DihMinTimeBetweenLCP; - if(restarter.dumpStateAllNodes(&val, 1) != 0){ - do { CHECK(0); } while(0); - g_err << "Failed to set LCP to min value" << endl; - return NDBT_FAILED; - } - const int loops = ctx->getNumLoops(); for (int l = 0; l < loops && result == NDBT_OK ; l++){ const int sz = sizeof(NF_codes)/sizeof(NF_codes[0]); @@ -1060,7 +1053,7 @@ runNF1(NDBT_Context* ctx, NDBT_Step* step){ CHECK2(dict->createTable(* pTab) == 0, "failed to create table"); - + if (crash) { CHECK2(restarter.waitNodesNoStart(&nodeId, 1) == 0, "waitNodesNoStart failed"); @@ -1084,9 +1077,6 @@ runNF1(NDBT_Context* ctx, NDBT_Step* step){ CHECK2(restarter.waitClusterStarted() == 0, "waitClusterStarted failed"); } - - CHECK2(restarter.dumpStateOneNode(nodeId, &val, 1) == 0, - "Failed to set LCP to min value"); } } } @@ -1583,21 +1573,26 @@ TESTCASE("CreateTableWhenDbIsFull", INITIALIZER(runFillTable); INITIALIZER(runCreateTableWhenDbIsFull); INITIALIZER(runDropTableWhenDbIsFull); - FINALIZER(runClearTable); + FINALIZER(runDropTheTable); } TESTCASE("FragmentTypeSingle", "Create the table with fragment type Single\n"){ - TC_PROPERTY("FragmentType", 1); + TC_PROPERTY("FragmentType", NdbDictionary::Table::FragSingle); + INITIALIZER(runTestFragmentTypes); +} +TESTCASE("FragmentTypeAllSmall", + "Create the table with fragment type AllSmall\n"){ + TC_PROPERTY("FragmentType", NdbDictionary::Table::FragAllSmall); INITIALIZER(runTestFragmentTypes); } -TESTCASE("FragmentTypeAll", - "Create the table with fragment type All\n"){ - TC_PROPERTY("FragmentType", 2); +TESTCASE("FragmentTypeAllMedium", + "Create the table with fragment type AllMedium\n"){ + TC_PROPERTY("FragmentType", NdbDictionary::Table::FragAllMedium); INITIALIZER(runTestFragmentTypes); } TESTCASE("FragmentTypeAllLarge", "Create the table with fragment type AllLarge\n"){ - TC_PROPERTY("FragmentType", 3); + TC_PROPERTY("FragmentType", NdbDictionary::Table::FragAllLarge); INITIALIZER(runTestFragmentTypes); } TESTCASE("TemporaryTables", @@ -1609,7 +1604,7 @@ TESTCASE("CreateMaxTables", "Create tables until db says that it can't create any more\n"){ TC_PROPERTY("tables", 1000); INITIALIZER(runCreateMaxTables); - FINALIZER(runDropMaxTables); + INITIALIZER(runDropMaxTables); } TESTCASE("PkSizes", "Create tables with all different primary key sizes.\n"\ diff --git a/ndb/test/ndbapi/testIndex.cpp b/ndb/test/ndbapi/testIndex.cpp index d359f83257f..5785db232c4 100644 --- a/ndb/test/ndbapi/testIndex.cpp +++ b/ndb/test/ndbapi/testIndex.cpp @@ -1145,20 +1145,18 @@ runUniqueNullTransactions(NDBT_Context* ctx, NDBT_Step* step){ pTrans = pNdb->startTransaction(); NdbScanOperation * sOp; NdbOperation * uOp; - NdbResultSet * rs; int eof; if(!pTrans) goto done; sOp = pTrans->getNdbScanOperation(pTab->getName()); if(!sOp) goto done; - rs = sOp->readTuples(NdbScanOperation::LM_Exclusive); - if(!rs) goto done; + if(sOp->readTuples(NdbScanOperation::LM_Exclusive)) goto done; if(pTrans->execute(NoCommit) == -1) goto done; - while((eof = rs->nextResult(true)) == 0){ + while((eof = sOp->nextResult(true)) == 0){ do { - NdbOperation * uOp = rs->updateTuple(); + NdbOperation * uOp = sOp->updateCurrentTuple(); if(uOp == 0) goto done; uOp->setValue(colId, 0); - } while((eof = rs->nextResult(false)) == 0); + } while((eof = sOp->nextResult(false)) == 0); eof = pTrans->execute(Commit); if(eof == -1) goto done; } @@ -1279,7 +1277,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); + TC_PROPERTY("PauseThreads", 2); INITIALIZER(runClearTable); INITIALIZER(createRandomIndex); INITIALIZER(runLoadTable); @@ -1294,6 +1292,7 @@ TESTCASE("NFNR1_O", "Test that indexes are correctly maintained during node fail and node restart"){ TC_PROPERTY("OrderedIndex", 1); TC_PROPERTY("LoggedIndexes", (unsigned)0); + TC_PROPERTY("PauseThreads", 2); INITIALIZER(runClearTable); INITIALIZER(createRandomIndex); INITIALIZER(runLoadTable); @@ -1307,6 +1306,7 @@ TESTCASE("NFNR1_O", TESTCASE("NFNR2", "Test that indexes are correctly maintained during node fail and node restart"){ TC_PROPERTY("LoggedIndexes", (unsigned)0); + TC_PROPERTY("PauseThreads", 2); INITIALIZER(runClearTable); INITIALIZER(createRandomIndex); INITIALIZER(createPkIndex); @@ -1323,6 +1323,7 @@ TESTCASE("NFNR2_O", "Test that indexes are correctly maintained during node fail and node restart"){ TC_PROPERTY("OrderedIndex", 1); TC_PROPERTY("LoggedIndexes", (unsigned)0); + TC_PROPERTY("PauseThreads", 1); INITIALIZER(runClearTable); INITIALIZER(createRandomIndex); INITIALIZER(createPkIndex); @@ -1338,6 +1339,7 @@ TESTCASE("NFNR2_O", TESTCASE("NFNR3", "Test that indexes are correctly maintained during node fail and node restart"){ TC_PROPERTY("LoggedIndexes", (unsigned)0); + TC_PROPERTY("PauseThreads", 2); INITIALIZER(runClearTable); INITIALIZER(createRandomIndex); INITIALIZER(createPkIndex); @@ -1353,6 +1355,7 @@ TESTCASE("NFNR3_O", "Test that indexes are correctly maintained during node fail and node restart"){ TC_PROPERTY("OrderedIndex", 1); TC_PROPERTY("LoggedIndexes", (unsigned)0); + TC_PROPERTY("PauseThreads", 2); INITIALIZER(runClearTable); INITIALIZER(createRandomIndex); INITIALIZER(createPkIndex); @@ -1367,6 +1370,7 @@ TESTCASE("NFNR3_O", TESTCASE("NFNR4", "Test that indexes are correctly maintained during node fail and node restart"){ TC_PROPERTY("LoggedIndexes", (unsigned)0); + TC_PROPERTY("PauseThreads", 4); INITIALIZER(runClearTable); INITIALIZER(createRandomIndex); INITIALIZER(createPkIndex); @@ -1385,6 +1389,7 @@ TESTCASE("NFNR4_O", "Test that indexes are correctly maintained during node fail and node restart"){ TC_PROPERTY("OrderedIndex", 1); TC_PROPERTY("LoggedIndexes", (unsigned)0); + TC_PROPERTY("PauseThreads", 4); INITIALIZER(runClearTable); INITIALIZER(createRandomIndex); INITIALIZER(createPkIndex); diff --git a/ndb/test/ndbapi/testLcp.cpp b/ndb/test/ndbapi/testLcp.cpp index d11692db761..8bfc7ccf9b9 100644 --- a/ndb/test/ndbapi/testLcp.cpp +++ b/ndb/test/ndbapi/testLcp.cpp @@ -30,6 +30,7 @@ static CASE g_ops[] = const size_t OP_COUNT = (sizeof(g_ops)/sizeof(g_ops[0])); static Ndb* g_ndb = 0; +static Ndb_cluster_connection *g_cluster_connection= 0; static CASE* g_cases; static HugoOperations* g_hugo_ops; @@ -122,6 +123,7 @@ main(int argc, char ** argv){ static int init_ndb(int argc, char** argv) { + ndb_init(); return 0; } @@ -132,7 +134,13 @@ static int parse_args(int argc, char** argv) static int connect_ndb() { - g_ndb = new Ndb("TEST_DB"); + g_cluster_connection = new Ndb_cluster_connection(); + if(g_cluster_connection->connect(12, 5, 1) != 0) + { + return 1; + } + + g_ndb = new Ndb(g_cluster_connection, "TEST_DB"); g_ndb->init(); if(g_ndb->waitUntilReady(30) == 0){ int args[] = { DumpStateOrd::DihMaxTimeBetweenLCP }; @@ -144,8 +152,10 @@ static int connect_ndb() static int disconnect_ndb() { delete g_ndb; + delete g_cluster_connection; g_ndb = 0; g_table = 0; + g_cluster_connection= 0; return 0; } diff --git a/ndb/test/ndbapi/testNdbApi.cpp b/ndb/test/ndbapi/testNdbApi.cpp index 3a06269f8dc..f456d852898 100644 --- a/ndb/test/ndbapi/testNdbApi.cpp +++ b/ndb/test/ndbapi/testNdbApi.cpp @@ -56,7 +56,7 @@ int runTestMaxNdb(NDBT_Context* ctx, NDBT_Step* step){ int init = 0; do { - Ndb* pNdb = new Ndb("TEST_DB"); + Ndb* pNdb = new Ndb(&ctx->m_cluster_connection, "TEST_DB"); if (pNdb == NULL){ ndbout << "pNdb == NULL" << endl; errors++; @@ -108,7 +108,7 @@ int runTestMaxTransaction(NDBT_Context* ctx, NDBT_Step* step){ int oldi = 0; int result = NDBT_OK; - Ndb* pNdb = new Ndb("TEST_DB"); + Ndb* pNdb = new Ndb(&ctx->m_cluster_connection, "TEST_DB"); if (pNdb == NULL){ ndbout << "pNdb == NULL" << endl; return NDBT_FAILED; @@ -119,6 +119,9 @@ int runTestMaxTransaction(NDBT_Context* ctx, NDBT_Step* step){ return NDBT_FAILED; } + const NdbDictionary::Table* pTab = ctx->getTab(); + if (pTab == 0) abort(); + while (l < loops && result == NDBT_OK){ int errors = 0; int maxErrors = 5; @@ -131,39 +134,25 @@ int runTestMaxTransaction(NDBT_Context* ctx, NDBT_Step* step){ NdbConnection* pCon; - int type = i%4; + int type = i%2; switch (type){ case 0: pCon = pNdb->startTransaction(); break; case 1: - pCon = pNdb->startTransaction(2, - "DATA", - 4); - break; - case 2: - ndbout_c("startTransactionDGroup not supported"); - abort(); - /* - pCon = pNdb->startTransactionDGroup(1, - "TEST", - 0); - */ - break; - case 3: - ndbout_c("startTransactionDGroup not supported"); - abort(); - /* - pCon = pNdb->startTransactionDGroup(2, - "TEST", - 1); - */ - break; - + { + BaseString key; + key.appfmt("DATA-%d", i); + ndbout_c("%s", key.c_str()); + pCon = pNdb->startTransaction(pTab, + key.c_str(), + key.length()); + } + break; default: abort(); } - + if (pCon == NULL){ ERR(pNdb->getNdbError()); errors++; @@ -209,7 +198,7 @@ int runTestMaxOperations(NDBT_Context* ctx, NDBT_Step* step){ int maxOpsLimit = 1; const NdbDictionary::Table* pTab = ctx->getTab(); - Ndb* pNdb = new Ndb("TEST_DB"); + Ndb* pNdb = new Ndb(&ctx->m_cluster_connection, "TEST_DB"); if (pNdb == NULL){ ndbout << "pNdb == NULL" << endl; return NDBT_FAILED; @@ -281,7 +270,7 @@ int runTestGetValue(NDBT_Context* ctx, NDBT_Step* step){ int result = NDBT_OK; const NdbDictionary::Table* pTab = ctx->getTab(); - Ndb* pNdb = new Ndb("TEST_DB"); + Ndb* pNdb = new Ndb(&ctx->m_cluster_connection, "TEST_DB"); if (pNdb == NULL){ ndbout << "pNdb == NULL" << endl; return NDBT_FAILED; @@ -381,7 +370,7 @@ int runTestEqual(NDBT_Context* ctx, NDBT_Step* step){ int result = NDBT_OK; const NdbDictionary::Table* pTab = ctx->getTab(); - Ndb* pNdb = new Ndb("TEST_DB"); + Ndb* pNdb = new Ndb(&ctx->m_cluster_connection, "TEST_DB"); if (pNdb == NULL){ ndbout << "pNdb == NULL" << endl; return NDBT_FAILED; @@ -502,7 +491,7 @@ int runTestDeleteNdb(NDBT_Context* ctx, NDBT_Step* step){ // Create 5 ndb objects for( int i = 0; i < 5; i++){ - Ndb* pNdb = new Ndb("TEST_DB"); + Ndb* pNdb = new Ndb(&ctx->m_cluster_connection, "TEST_DB"); if (pNdb == NULL){ ndbout << "pNdb == NULL" << endl; result = NDBT_FAILED; @@ -583,7 +572,7 @@ int runLoadTable(NDBT_Context* ctx, NDBT_Step* step){ int runTestWaitUntilReady(NDBT_Context* ctx, NDBT_Step* step){ - Ndb* pNdb = new Ndb("TEST_DB"); + Ndb* pNdb = new Ndb(&ctx->m_cluster_connection, "TEST_DB"); // Forget about calling pNdb->init(); @@ -604,7 +593,7 @@ int runTestWaitUntilReady(NDBT_Context* ctx, NDBT_Step* step){ int runGetNdbOperationNoTab(NDBT_Context* ctx, NDBT_Step* step){ - Ndb* pNdb = new Ndb("TEST_DB"); + Ndb* pNdb = new Ndb(&ctx->m_cluster_connection, "TEST_DB"); if (pNdb == NULL){ ndbout << "pNdb == NULL" << endl; return NDBT_FAILED; @@ -645,7 +634,7 @@ int runMissingOperation(NDBT_Context* ctx, NDBT_Step* step){ const NdbDictionary::Table* pTab = ctx->getTab(); - Ndb* pNdb = new Ndb("TEST_DB"); + Ndb* pNdb = new Ndb(&ctx->m_cluster_connection, "TEST_DB"); if (pNdb == NULL){ ndbout << "pNdb == NULL" << endl; return NDBT_FAILED; @@ -695,7 +684,7 @@ int runMissingOperation(NDBT_Context* ctx, NDBT_Step* step){ int runGetValueInUpdate(NDBT_Context* ctx, NDBT_Step* step){ const NdbDictionary::Table* pTab = ctx->getTab(); - Ndb* pNdb = new Ndb("TEST_DB"); + Ndb* pNdb = new Ndb(&ctx->m_cluster_connection, "TEST_DB"); if (pNdb == NULL){ ndbout << "pNdb == NULL" << endl; return NDBT_FAILED; @@ -761,7 +750,7 @@ int runUpdateWithoutValues(NDBT_Context* ctx, NDBT_Step* step){ HugoOperations hugoOps(*pTab); - Ndb* pNdb = new Ndb("TEST_DB"); + Ndb* pNdb = new Ndb(&ctx->m_cluster_connection, "TEST_DB"); if (pNdb == NULL){ ndbout << "pNdb == NULL" << endl; return NDBT_FAILED; @@ -807,13 +796,13 @@ int runUpdateWithoutValues(NDBT_Context* ctx, NDBT_Step* step){ // Dont' call any setValues - // Execute should not work + // Execute should work int check = pCon->execute(Commit); if (check == 0){ ndbout << "execute worked" << endl; - result = NDBT_FAILED; } else { ERR(pCon->getNdbError()); + result = NDBT_FAILED; } pNdb->closeTransaction(pCon); @@ -827,7 +816,7 @@ int runUpdateWithoutKeys(NDBT_Context* ctx, NDBT_Step* step){ const NdbDictionary::Table* pTab = ctx->getTab(); - Ndb* pNdb = new Ndb("TEST_DB"); + Ndb* pNdb = new Ndb(&ctx->m_cluster_connection, "TEST_DB"); if (pNdb == NULL){ ndbout << "pNdb == NULL" << endl; return NDBT_FAILED; @@ -953,8 +942,7 @@ int runReadWithoutGetValue(NDBT_Context* ctx, NDBT_Step* step){ return NDBT_FAILED; } - NdbResultSet *rs; - if ((rs = pOp->readTuples((NdbOperation::LockMode)lm)) == 0){ + if ((pOp->readTuples((NdbOperation::LockMode)lm)) != 0){ pNdb->closeTransaction(pCon); ERR(pOp->getNdbError()); return NDBT_FAILED; @@ -973,7 +961,7 @@ int runReadWithoutGetValue(NDBT_Context* ctx, NDBT_Step* step){ } int res; - while((res = rs->nextResult()) == 0); + while((res = pOp->nextResult()) == 0); pNdb->closeTransaction(pCon); if(res != 1) @@ -988,7 +976,7 @@ int runCheckGetNdbErrorOperation(NDBT_Context* ctx, NDBT_Step* step){ int result = NDBT_OK; const NdbDictionary::Table* pTab = ctx->getTab(); - Ndb* pNdb = new Ndb("TEST_DB"); + Ndb* pNdb = new Ndb(&ctx->m_cluster_connection, "TEST_DB"); if (pNdb == NULL){ ndbout << "pNdb == NULL" << endl; return NDBT_FAILED; @@ -1049,7 +1037,7 @@ int runCheckGetNdbErrorOperation(NDBT_Context* ctx, NDBT_Step* step){ return result; } -#define C2(x) { int _x= (x); if(_x == 0) return NDBT_FAILED; } +#define C2(x) { int _x= (x); if(_x == 0){ ndbout << "line: " << __LINE__ << endl; return NDBT_FAILED;} } int runBug_11133(NDBT_Context* ctx, NDBT_Step* step){ int result = NDBT_OK; @@ -1058,7 +1046,6 @@ int runBug_11133(NDBT_Context* ctx, NDBT_Step* step){ HugoOperations hugoOps(*pTab); Ndb* pNdb = GETNDB(step); - C2(hugoOps.startTransaction(pNdb) == 0); C2(hugoOps.pkInsertRecord(pNdb, 0, 1) == 0); C2(hugoOps.execute_NoCommit(pNdb) == 0); @@ -1101,7 +1088,7 @@ int runBug_11133(NDBT_Context* ctx, NDBT_Step* step){ C2(hugoOps.execute_Commit(pNdb) == 0); C2(hugoOps.closeTransaction(pNdb) == 0); - Ndb ndb2("TEST_DB"); + Ndb ndb2(&ctx->m_cluster_connection, "TEST_DB"); C2(ndb2.init() == 0); C2(ndb2.waitUntilReady() == 0); HugoOperations hugoOps2(*pTab); @@ -1110,8 +1097,8 @@ int runBug_11133(NDBT_Context* ctx, NDBT_Step* step){ C2(hugoOps.pkInsertRecord(pNdb, 0, 1) == 0); C2(hugoOps.execute_NoCommit(pNdb) == 0); C2(hugoOps2.startTransaction(&ndb2) == 0); - C2(hugoOps2.pkWriteRecord(&ndb2, 0, 1) == 0); - C2(hugoOps2.execute_async(&ndb2, NoCommit) == 0); + C2(hugoOps2.pkWritePartialRecord(&ndb2, 0) == 0); + C2(hugoOps2.execute_async(&ndb2, NdbTransaction::NoCommit) == 0); C2(hugoOps.execute_Commit(pNdb) == 0); C2(hugoOps2.wait_async(&ndb2) == 0); C2(hugoOps.closeTransaction(pNdb) == 0); @@ -1122,15 +1109,133 @@ int runBug_11133(NDBT_Context* ctx, NDBT_Step* step){ C2(hugoOps.execute_NoCommit(pNdb) == 0); C2(hugoOps2.startTransaction(&ndb2) == 0); C2(hugoOps2.pkWriteRecord(&ndb2, 0, 1) == 0); - C2(hugoOps2.execute_async(&ndb2, NoCommit) == 0); + C2(hugoOps2.execute_async(&ndb2, NdbTransaction::NoCommit) == 0); C2(hugoOps.execute_Commit(pNdb) == 0); C2(hugoOps2.wait_async(&ndb2) == 0); + C2(hugoOps2.execute_Commit(pNdb) == 0); C2(hugoOps.closeTransaction(pNdb) == 0); C2(hugoOps2.closeTransaction(&ndb2) == 0); + C2(hugoOps.startTransaction(pNdb) == 0); + C2(hugoOps.pkUpdateRecord(pNdb, 0, 1) == 0); + C2(hugoOps.execute_NoCommit(pNdb) == 0); + C2(hugoOps2.startTransaction(&ndb2) == 0); + C2(hugoOps2.pkWritePartialRecord(&ndb2, 0) == 0); + C2(hugoOps2.execute_async(&ndb2, NdbTransaction::NoCommit) == 0); + C2(hugoOps.execute_Commit(pNdb) == 0); + C2(hugoOps2.wait_async(&ndb2) == 0); + C2(hugoOps.closeTransaction(pNdb) == 0); + C2(hugoOps2.closeTransaction(&ndb2) == 0); + + C2(hugoOps.startTransaction(pNdb) == 0); + C2(hugoOps.pkDeleteRecord(pNdb, 0, 1) == 0); + C2(hugoOps.execute_NoCommit(pNdb) == 0); + C2(hugoOps2.startTransaction(&ndb2) == 0); + C2(hugoOps2.pkWritePartialRecord(&ndb2, 0) == 0); + C2(hugoOps2.execute_async(&ndb2, NdbTransaction::NoCommit) == 0); + C2(hugoOps.execute_Commit(pNdb) == 0); + C2(hugoOps2.wait_async(&ndb2) != 0); + C2(hugoOps.closeTransaction(pNdb) == 0); + C2(hugoOps2.closeTransaction(&ndb2) == 0); + + return result; +} + +int runScan_4006(NDBT_Context* ctx, NDBT_Step* step){ + int result = NDBT_OK; + const Uint32 max= 5; + const NdbDictionary::Table* pTab = ctx->getTab(); + + Ndb* pNdb = new Ndb(&ctx->m_cluster_connection, "TEST_DB"); + if (pNdb == NULL){ + ndbout << "pNdb == NULL" << endl; + return NDBT_FAILED; + } + if (pNdb->init(max)){ + ERR(pNdb->getNdbError()); + delete pNdb; + return NDBT_FAILED; + } + + NdbConnection* pCon = pNdb->startTransaction(); + if (pCon == NULL){ + pNdb->closeTransaction(pCon); + delete pNdb; + return NDBT_FAILED; + } + + Uint32 i; + Vector<NdbScanOperation*> scans; + for(i = 0; i<10*max; i++) + { + NdbScanOperation* pOp = pCon->getNdbScanOperation(pTab->getName()); + if (pOp == NULL){ + ERR(pCon->getNdbError()); + pNdb->closeTransaction(pCon); + delete pNdb; + return NDBT_FAILED; + } + + if (pOp->readTuples() != 0){ + pNdb->closeTransaction(pCon); + ERR(pOp->getNdbError()); + delete pNdb; + return NDBT_FAILED; + } + scans.push_back(pOp); + } + + // Dont' call any equal or setValues + + // Execute should not work + int check = pCon->execute(NoCommit); + if (check == 0){ + ndbout << "execute worked" << endl; + } else { + ERR(pCon->getNdbError()); + } + + for(i= 0; i<scans.size(); i++) + { + NdbScanOperation* pOp= scans[i]; + while((check= pOp->nextResult()) == 0); + if(check != 1) + { + ERR(pOp->getNdbError()); + pNdb->closeTransaction(pCon); + delete pNdb; + return NDBT_FAILED; + } + } + + pNdb->closeTransaction(pCon); + + Vector<NdbConnection*> cons; + for(i= 0; i<10*max; i++) + { + pCon= pNdb->startTransaction(); + if(pCon) + cons.push_back(pCon); + else + break; + } + + for(i= 0; i<cons.size(); i++) + { + cons[i]->close(); + } + + if(cons.size() != max) + { + result= NDBT_FAILED; + } + + delete pNdb; + return result; } +template class Vector<NdbScanOperation*>; NDBT_TESTSUITE(testNdbApi); @@ -1212,6 +1317,12 @@ TESTCASE("Bug_11133", INITIALIZER(runBug_11133); FINALIZER(runClearTable); } +TESTCASE("Scan_4006", + "Check that getNdbScanOperation does not get 4006\n"){ + INITIALIZER(runLoadTable); + INITIALIZER(runScan_4006); + FINALIZER(runClearTable); +} NDBT_TESTSUITE_END(testNdbApi); int main(int argc, const char** argv){ diff --git a/ndb/test/ndbapi/testNodeRestart.cpp b/ndb/test/ndbapi/testNodeRestart.cpp index 9c25d715d07..6ef3da2d760 100644 --- a/ndb/test/ndbapi/testNodeRestart.cpp +++ b/ndb/test/ndbapi/testNodeRestart.cpp @@ -311,7 +311,7 @@ int runDirtyRead(NDBT_Context* ctx, NDBT_Step* step){ int id = i % restarter.getNumDbNodes(); int nodeId = restarter.getDbNodeId(id); ndbout << "Restart node " << nodeId << endl; - restarter.insertErrorInAllNodes(5041); + restarter.insertErrorInNode(nodeId, 5041); restarter.insertErrorInAllNodes(8048 + (i & 1)); for(int j = 0; j<records; j++){ diff --git a/ndb/test/ndbapi/testOIBasic.cpp b/ndb/test/ndbapi/testOIBasic.cpp index 9f8da850ff4..942ee2ec966 100644 --- a/ndb/test/ndbapi/testOIBasic.cpp +++ b/ndb/test/ndbapi/testOIBasic.cpp @@ -28,7 +28,10 @@ #include <NdbCondition.h> #include <NdbThread.h> #include <NdbTick.h> +#include <NdbSleep.h> #include <my_sys.h> +#include <NdbSqlUtil.hpp> +#include <ndb_version.h> // options @@ -37,6 +40,7 @@ struct Opt { unsigned m_batch; const char* m_bound; const char* m_case; + bool m_collsp; bool m_core; const char* m_csname; CHARSET_INFO* m_cs; @@ -52,20 +56,20 @@ struct Opt { unsigned m_pctnull; unsigned m_rows; unsigned m_samples; - unsigned m_scanbat; unsigned m_scanpar; unsigned m_scanstop; - unsigned m_seed; + int m_seed; unsigned m_subloop; const char* m_table; unsigned m_threads; - int m_v; + int m_v; // int for lint Opt() : m_batch(32), m_bound("01234"), m_case(0), + m_collsp(false), m_core(false), - m_csname("latin1_bin"), + m_csname("random"), m_cs(0), m_die(0), m_dups(false), @@ -79,13 +83,12 @@ struct Opt { m_pctnull(10), m_rows(1000), m_samples(0), - m_scanbat(0), m_scanpar(0), m_scanstop(0), - m_seed(0), + m_seed(-1), m_subloop(4), m_table(0), - m_threads(10), + m_threads(4), m_v(1) { } }; @@ -104,23 +107,23 @@ printhelp() << " -batch N pk operations in batch [" << d.m_batch << "]" << endl << " -bound xyz use only these bound types 0-4 [" << d.m_bound << "]" << endl << " -case abc only given test cases (letters a-z)" << endl + << " -collsp use strnncollsp instead of strnxfrm" << endl << " -core core dump on error [" << d.m_core << "]" << endl - << " -csname S charset (collation) of non-pk char column [" << d.m_csname << "]" << endl + << " -csname S charset or collation [" << d.m_csname << "]" << endl << " -die nnn exit immediately on NDB error code nnn" << 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 + << " -index xyz only given index numbers (digits 0-9)" << endl << " -loop N loop count full suite 0=forever [" << d.m_loop << "]" << endl << " -nologging create tables in no-logging mode" << endl << " -noverify skip index verifications" << endl << " -pctnull N pct NULL values in nullable column [" << d.m_pctnull << "]" << endl << " -rows N rows per thread [" << d.m_rows << "]" << endl << " -samples N samples for some timings (0=all) [" << d.m_samples << "]" << endl - << " -scanbat N scan batch per fragment (ignored by ndb api) [" << d.m_scanbat << "]" << endl << " -scanpar N scan parallelism [" << d.m_scanpar << "]" << endl - << " -seed N srandom seed 0=loop number[" << d.m_seed << "]" << endl + << " -seed N srandom seed 0=loop number -1=random [" << d.m_seed << "]" << endl << " -subloop N subtest loop count [" << d.m_subloop << "]" << endl - << " -table xyz only given table numbers (digits 1-9)" << endl + << " -table xyz only given table numbers (digits 0-9)" << endl << " -threads N number of threads [" << d.m_threads << "]" << endl << " -vN verbosity [" << d.m_v << "]" << endl << " -h or -help print this help text" << endl @@ -135,9 +138,84 @@ 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; +static const char* hexstr = "0123456789abcdef"; + +// random ints + +static unsigned +urandom(unsigned n) +{ + if (n == 0) + return 0; + unsigned i = random() % n; + return i; +} + +static int +irandom(unsigned n) +{ + if (n == 0) + return 0; + int i = random() % n; + if (random() & 0x1) + i = -i; + return i; +} + +static bool +randompct(unsigned pct) +{ + if (pct == 0) + return false; + if (pct >= 100) + return true; + return urandom(100) < pct; +} + +static unsigned +random_coprime(unsigned n) +{ + unsigned prime[] = { 101, 211, 307, 401, 503, 601, 701, 809, 907 }; + unsigned count = sizeof(prime) / sizeof(prime[0]); + if (n == 0) + return 0; + while (1) { + unsigned i = urandom(count); + if (n % prime[i] != 0) + return prime[i]; + } +} + +// random re-sequence of 0...(n-1) + +struct Rsq { + Rsq(unsigned n); + unsigned next(); +private: + unsigned m_n; + unsigned m_i; + unsigned m_start; + unsigned m_prime; +}; + +Rsq::Rsq(unsigned n) +{ + m_n = n; + m_i = 0; + m_start = urandom(n); + m_prime = random_coprime(n); +} + +unsigned +Rsq::next() +{ + assert(m_n != 0); + return (m_start + m_i++ * m_prime) % m_n; +} + // log and error macros -static NdbMutex *ndbout_mutex= NULL; +static NdbMutex *ndbout_mutex = NULL; static unsigned getthrno(); @@ -198,7 +276,7 @@ getthrstr() return -1; \ } while (0) -// method parameters base class +// method parameters class Thr; class Con; @@ -222,6 +300,8 @@ struct Par : public Opt { // value calculation unsigned m_range; unsigned m_pctrange; + unsigned m_pctbrange; + int m_bdir; // choice of key bool m_randomkey; // do verify after read @@ -230,6 +310,11 @@ struct Par : public Opt { bool m_deadlock; // abort percentabge unsigned m_abortpct; + NdbOperation::LockMode m_lockmode; + // scan options + bool m_tupscan; + bool m_ordered; + bool m_descending; // timer location Par(const Opt& opt) : Opt(opt), @@ -242,24 +327,30 @@ struct Par : public Opt { m_slno(0), m_totrows(m_threads * m_rows), m_range(m_rows), - m_pctrange(0), + m_pctrange(40), + m_pctbrange(80), + m_bdir(0), m_randomkey(false), m_verify(false), m_deadlock(false), - m_abortpct(0) { + m_abortpct(0), + m_lockmode(NdbOperation::LM_Read), + m_tupscan(false), + m_ordered(false), + m_descending(false) { } }; static bool -usetable(unsigned i) +usetable(Par par, unsigned i) { - return g_opt.m_table == 0 || strchr(g_opt.m_table, '1' + i) != 0; + return par.m_table == 0 || strchr(par.m_table, '0' + i) != 0; } static bool -useindex(unsigned i) +useindex(Par par, unsigned i) { - return g_opt.m_index == 0 || strchr(g_opt.m_index, '1' + i) != 0; + return par.m_index == 0 || strchr(par.m_index, '0' + i) != 0; } static unsigned @@ -385,38 +476,285 @@ Lst::reset() m_cnt = 0; } +// character sets + +static const unsigned maxcsnumber = 512; +static const unsigned maxcharcount = 32; +static const unsigned maxcharsize = 4; +static const unsigned maxxmulsize = 8; + +// single mb char +struct Chr { + unsigned char m_bytes[maxcharsize]; + unsigned char m_xbytes[maxxmulsize * maxcharsize]; + unsigned m_size; + Chr(); +}; + +Chr::Chr() +{ + memset(m_bytes, 0, sizeof(m_bytes)); + memset(m_xbytes, 0, sizeof(m_xbytes)); + m_size = 0; +} + +// charset and random valid chars to use +struct Chs { + CHARSET_INFO* m_cs; + unsigned m_xmul; + Chr* m_chr; + Chs(CHARSET_INFO* cs); + ~Chs(); +}; + +static NdbOut& +operator<<(NdbOut& out, const Chs& chs); + +Chs::Chs(CHARSET_INFO* cs) : + m_cs(cs) +{ + m_xmul = m_cs->strxfrm_multiply; + if (m_xmul == 0) + m_xmul = 1; + assert(m_xmul <= maxxmulsize); + m_chr = new Chr [maxcharcount]; + unsigned i = 0; + unsigned miss1 = 0; + unsigned miss2 = 0; + unsigned miss3 = 0; + unsigned miss4 = 0; + while (i < maxcharcount) { + unsigned char* bytes = m_chr[i].m_bytes; + unsigned char* xbytes = m_chr[i].m_xbytes; + unsigned& size = m_chr[i].m_size; + bool ok; + size = m_cs->mbminlen + urandom(m_cs->mbmaxlen - m_cs->mbminlen + 1); + assert(m_cs->mbminlen <= size && size <= m_cs->mbmaxlen); + // prefer longer chars + if (size == m_cs->mbminlen && m_cs->mbminlen < m_cs->mbmaxlen && urandom(5) != 0) + continue; + for (unsigned j = 0; j < size; j++) { + bytes[j] = urandom(256); + } + int not_used; + // check wellformed + const char* sbytes = (const char*)bytes; + if ((*cs->cset->well_formed_len)(cs, sbytes, sbytes + size, 1, ¬_used) != size) { + miss1++; + continue; + } + // check no proper prefix wellformed + ok = true; + for (unsigned j = 1; j < size; j++) { + if ((*cs->cset->well_formed_len)(cs, sbytes, sbytes + j, 1, ¬_used) == j) { + ok = false; + break; + } + } + if (! ok) { + miss2++; + continue; + } + // normalize + memset(xbytes, 0, sizeof(xbytes)); + // currently returns buffer size always + int xlen = (*cs->coll->strnxfrm)(cs, xbytes, m_xmul * size, bytes, size); + // check we got something + ok = false; + for (unsigned j = 0; j < xlen; j++) { + if (xbytes[j] != 0) { + ok = true; + break; + } + } + if (! ok) { + miss3++; + continue; + } + // check for duplicate (before normalize) + ok = true; + for (unsigned j = 0; j < i; j++) { + const Chr& chr = m_chr[j]; + if (chr.m_size == size && memcmp(chr.m_bytes, bytes, size) == 0) { + ok = false; + break; + } + } + if (! ok) { + miss4++; + continue; + } + i++; + } + bool disorder = true; + unsigned bubbles = 0; + while (disorder) { + disorder = false; + for (unsigned i = 1; i < maxcharcount; i++) { + unsigned len = sizeof(m_chr[i].m_xbytes); + if (memcmp(m_chr[i-1].m_xbytes, m_chr[i].m_xbytes, len) > 0) { + Chr chr = m_chr[i]; + m_chr[i] = m_chr[i-1]; + m_chr[i-1] = chr; + disorder = true; + bubbles++; + } + } + } + LL3("inited charset " << *this << " miss=" << miss1 << "," << miss2 << "," << miss3 << "," << miss4 << " bubbles=" << bubbles); +} + +Chs::~Chs() +{ + delete [] m_chr; +} + +static NdbOut& +operator<<(NdbOut& out, const Chs& chs) +{ + CHARSET_INFO* cs = chs.m_cs; + out << cs->name << "[" << cs->mbminlen << "-" << cs->mbmaxlen << "," << chs.m_xmul << "]"; + return out; +} + +static Chs* cslist[maxcsnumber]; + +static void +resetcslist() +{ + for (unsigned i = 0; i < maxcsnumber; i++) { + delete cslist[i]; + cslist[i] = 0; + } +} + +static Chs* +getcs(Par par) +{ + CHARSET_INFO* cs; + if (par.m_cs != 0) { + cs = par.m_cs; + } else { + while (1) { + unsigned n = urandom(maxcsnumber); + cs = get_charset(n, MYF(0)); + if (cs != 0) { + // prefer complex charsets + if (cs->mbmaxlen != 1 || urandom(5) == 0) + break; + } + } + } + if (cslist[cs->number] == 0) + cslist[cs->number] = new Chs(cs); + return cslist[cs->number]; +} + // tables and indexes // Col - table column struct Col { + enum Type { + Unsigned = NdbDictionary::Column::Unsigned, + Char = NdbDictionary::Column::Char, + Varchar = NdbDictionary::Column::Varchar, + Longvarchar = NdbDictionary::Column::Longvarchar + }; + const class Tab& m_tab; unsigned m_num; const char* m_name; bool m_pk; - NdbDictionary::Column::Type m_type; + Type m_type; unsigned m_length; + unsigned m_bytelength; // multiplied by char width + unsigned m_attrsize; // base type size + unsigned m_headsize; // length bytes + unsigned m_bytesize; // full value size bool m_nullable; - void verify(const void* addr) const; + const Chs* m_chs; + Col(const class Tab& tab, unsigned num, const char* name, bool pk, Type type, unsigned length, bool nullable, const Chs* chs); + ~Col(); + bool equal(const Col& col2) const; + void wellformed(const void* addr) const; }; +Col::Col(const class Tab& tab, unsigned num, const char* name, bool pk, Type type, unsigned length, bool nullable, const Chs* chs) : + m_tab(tab), + m_num(num), + m_name(strcpy(new char [strlen(name) + 1], name)), + m_pk(pk), + m_type(type), + m_length(length), + m_bytelength(length * (chs == 0 ? 1 : chs->m_cs->mbmaxlen)), + m_attrsize( + type == Unsigned ? sizeof(Uint32) : + type == Char ? sizeof(char) : + type == Varchar ? sizeof(char) : + type == Longvarchar ? sizeof(char) : ~0), + m_headsize( + type == Unsigned ? 0 : + type == Char ? 0 : + type == Varchar ? 1 : + type == Longvarchar ? 2 : ~0), + m_bytesize(m_headsize + m_attrsize * m_bytelength), + m_nullable(nullable), + m_chs(chs) +{ + // fix long varchar + if (type == Varchar && m_bytelength > 255) { + m_type = Longvarchar; + m_headsize += 1; + m_bytesize += 1; + } +} + +Col::~Col() +{ + delete [] m_name; +} + +bool +Col::equal(const Col& col2) const +{ + return m_type == col2.m_type && m_length == col2.m_length && m_chs == col2.m_chs; +} + void -Col::verify(const void* addr) const +Col::wellformed(const void* addr) const { switch (m_type) { - case NdbDictionary::Column::Unsigned: + case Col::Unsigned: break; - case NdbDictionary::Column::Varchar: + case Col::Char: { - const unsigned char* p = (const unsigned char*)addr; - unsigned n = (p[0] << 8) | p[1]; - assert(n <= m_length); - unsigned i; - for (i = 0; i < n; i++) { - assert(p[2 + i] != 0); - } - for (i = n; i < m_length; i++) { - assert(p[2 + i] == 0); - } + CHARSET_INFO* cs = m_chs->m_cs; + const char* src = (const char*)addr; + unsigned len = m_bytelength; + int not_used; + assert((*cs->cset->well_formed_len)(cs, src, src + len, 0xffff, ¬_used) == len); + } + break; + case Col::Varchar: + { + CHARSET_INFO* cs = m_chs->m_cs; + const unsigned char* src = (const unsigned char*)addr; + const char* ssrc = (const char*)src; + unsigned len = src[0]; + int not_used; + assert(len <= m_bytelength); + assert((*cs->cset->well_formed_len)(cs, ssrc + 1, ssrc + 1 + len, 0xffff, ¬_used) == len); + } + break; + case Col::Longvarchar: + { + CHARSET_INFO* cs = m_chs->m_cs; + const unsigned char* src = (const unsigned char*)addr; + const char* ssrc = (const char*)src; + unsigned len = src[0] + (src[1] << 8); + int not_used; + assert(len <= m_bytelength); + assert((*cs->cset->well_formed_len)(cs, ssrc + 2, ssrc + 2 + len, 0xffff, ¬_used) == len); } break; default: @@ -428,14 +766,28 @@ Col::verify(const void* addr) const static NdbOut& operator<<(NdbOut& out, const Col& col) { - out << "col " << col.m_num; - out << " " << col.m_name; + out << "col[" << col.m_num << "] " << col.m_name; switch (col.m_type) { - case NdbDictionary::Column::Unsigned: + case Col::Unsigned: out << " unsigned"; break; - case NdbDictionary::Column::Varchar: - out << " varchar(" << col.m_length << ")"; + case Col::Char: + { + CHARSET_INFO* cs = col.m_chs->m_cs; + out << " char(" << col.m_length << "*" << cs->mbmaxlen << ";" << cs->name << ")"; + } + break; + case Col::Varchar: + { + CHARSET_INFO* cs = col.m_chs->m_cs; + out << " varchar(" << col.m_length << "*" << cs->mbmaxlen << ";" << cs->name << ")"; + } + break; + case Col::Longvarchar: + { + CHARSET_INFO* cs = col.m_chs->m_cs; + out << " longvarchar(" << col.m_length << "*" << cs->mbmaxlen << ";" << cs->name << ")"; + } break; default: out << "type" << (int)col.m_type; @@ -450,25 +802,84 @@ operator<<(NdbOut& out, const Col& col) // ICol - index column struct ICol { + const class ITab& m_itab; unsigned m_num; - struct Col m_col; + const Col& m_col; + ICol(const class ITab& itab, unsigned num, const Col& col); + ~ICol(); }; +ICol::ICol(const class ITab& itab, unsigned num, const Col& col) : + m_itab(itab), + m_num(num), + m_col(col) +{ +} + +ICol::~ICol() +{ +} + +static NdbOut& +operator<<(NdbOut& out, const ICol& icol) +{ + out << "icol[" << icol.m_num << "] " << icol.m_col; + return out; +} + // ITab - index struct ITab { + enum Type { + OrderedIndex = NdbDictionary::Index::OrderedIndex, + UniqueHashIndex = NdbDictionary::Index::UniqueHashIndex + }; + const class Tab& m_tab; const char* m_name; + Type m_type; unsigned m_icols; - const ICol* m_icol; + const ICol** m_icol; + unsigned m_colmask; + ITab(const class Tab& tab, const char* name, Type type, unsigned icols); + ~ITab(); + void icoladd(unsigned k, const ICol* icolptr); }; +ITab::ITab(const class Tab& tab, const char* name, Type type, unsigned icols) : + m_tab(tab), + m_name(strcpy(new char [strlen(name) + 1], name)), + m_type(type), + m_icols(icols), + m_icol(new const ICol* [icols + 1]), + m_colmask(0) +{ + for (unsigned k = 0; k <= m_icols; k++) + m_icol[k] = 0; +} + +ITab::~ITab() +{ + delete [] m_name; + for (unsigned i = 0; i < m_icols; i++) + delete m_icol[i]; + delete [] m_icol; +} + +void +ITab::icoladd(unsigned k, const ICol* icolptr) +{ + assert(k == icolptr->m_num && k < m_icols && m_icol[k] == 0); + m_icol[k] = icolptr; + m_colmask |= (1 << icolptr->m_col.m_num); +} + static NdbOut& operator<<(NdbOut& out, const ITab& itab) { - out << "itab " << itab.m_name << " " << itab.m_icols; + out << "itab " << itab.m_name << " icols=" << itab.m_icols; for (unsigned k = 0; k < itab.m_icols; k++) { - out << endl; - out << "icol " << k << " " << itab.m_icol[k].m_col; + const ICol& icol = *itab.m_icol[k]; + out << endl << icol; } return out; } @@ -478,200 +889,298 @@ operator<<(NdbOut& out, const ITab& itab) struct Tab { const char* m_name; unsigned m_cols; - const Col* m_col; + const Col** m_col; unsigned m_itabs; - const ITab* m_itab; + const ITab** m_itab; + // pk must contain an Unsigned column + unsigned m_keycol; + void coladd(unsigned k, Col* colptr); + void itabadd(unsigned j, ITab* itab); + Tab(const char* name, unsigned cols, unsigned itabs, unsigned keycol); + ~Tab(); }; +Tab::Tab(const char* name, unsigned cols, unsigned itabs, unsigned keycol) : + m_name(strcpy(new char [strlen(name) + 1], name)), + m_cols(cols), + m_col(new const Col* [cols + 1]), + m_itabs(itabs), + m_itab(new const ITab* [itabs + 1]), + m_keycol(keycol) +{ + for (unsigned k = 0; k <= cols; k++) + m_col[k] = 0; + for (unsigned j = 0; j <= itabs; j++) + m_itab[j] = 0; +} + +Tab::~Tab() +{ + delete [] m_name; + for (unsigned i = 0; i < m_cols; i++) + delete m_col[i]; + delete [] m_col; + for (unsigned i = 0; i < m_itabs; i++) + delete m_itab[i]; + delete [] m_itab; +} + +void +Tab::coladd(unsigned k, Col* colptr) +{ + assert(k == colptr->m_num && k < m_cols && m_col[k] == 0); + m_col[k] = colptr; +} + +void +Tab::itabadd(unsigned j, ITab* itabptr) +{ + assert(j < m_itabs && m_itab[j] == 0); + m_itab[j] = itabptr; +} + static NdbOut& operator<<(NdbOut& out, const Tab& tab) { - out << "tab " << tab.m_name << " " << tab.m_cols; + out << "tab " << tab.m_name << " cols=" << tab.m_cols; for (unsigned k = 0; k < tab.m_cols; k++) { - out << endl; - out << tab.m_col[k]; + const Col& col = *tab.m_col[k]; + out << endl << col; } for (unsigned i = 0; i < tab.m_itabs; i++) { - if (! useindex(i)) + if (tab.m_itab[i] == 0) continue; - out << endl; - out << tab.m_itab[i]; + const ITab& itab = *tab.m_itab[i]; + out << endl << itab; } return out; } -// tt1 + tt1x1 tt1x2 tt1x3 tt1x4 tt1x5 - -static const Col -tt1col[] = { - { 0, "A", 1, NdbDictionary::Column::Unsigned, 1, 0 }, - { 1, "B", 0, NdbDictionary::Column::Unsigned, 1, 1 }, - { 2, "C", 0, NdbDictionary::Column::Unsigned, 1, 1 }, - { 3, "D", 0, NdbDictionary::Column::Unsigned, 1, 1 }, - { 4, "E", 0, NdbDictionary::Column::Unsigned, 1, 1 } -}; +// make table structs -static const ICol -tt1x1col[] = { - { 0, tt1col[0] } -}; - -static const ICol -tt1x2col[] = { - { 0, tt1col[1] } -}; - -static const ICol -tt1x3col[] = { - { 0, tt1col[1] }, - { 1, tt1col[2] } -}; - -static const ICol -tt1x4col[] = { - { 0, tt1col[3] }, - { 1, tt1col[2] }, - { 2, tt1col[1] } -}; - -static const ICol -tt1x5col[] = { - { 0, tt1col[1] }, - { 1, tt1col[4] }, - { 2, tt1col[2] }, - { 3, tt1col[3] } -}; - -static const ITab -tt1x1 = { - "TT1X1", 1, tt1x1col -}; - -static const ITab -tt1x2 = { - "TT1X2", 1, tt1x2col -}; - -static const ITab -tt1x3 = { - "TT1X3", 2, tt1x3col -}; +static const Tab** tablist = 0; +static unsigned tabcount = 0; -static const ITab -tt1x4 = { - "TT1X4", 3, tt1x4col -}; - -static const ITab -tt1x5 = { - "TT1X5", 4, tt1x5col -}; - -static const ITab -tt1itab[] = { - tt1x1, - tt1x2, - tt1x3, - tt1x4, - tt1x5 -}; - -static const Tab -tt1 = { - "TT1", 5, tt1col, 5, tt1itab -}; - -// tt2 + tt2x1 tt2x2 tt2x3 tt2x4 tt2x5 - -static const Col -tt2col[] = { - { 0, "A", 1, NdbDictionary::Column::Unsigned, 1, 0 }, - { 1, "B", 0, NdbDictionary::Column::Unsigned, 1, 1 }, - { 2, "C", 0, NdbDictionary::Column::Varchar, 20, 1 }, - { 3, "D", 0, NdbDictionary::Column::Varchar, 5, 1 }, - { 4, "E", 0, NdbDictionary::Column::Varchar, 5, 1 } -}; - -static const ICol -tt2x1col[] = { - { 0, tt2col[0] } -}; - -static const ICol -tt2x2col[] = { - { 0, tt2col[1] }, - { 1, tt2col[2] } -}; - -static const ICol -tt2x3col[] = { - { 0, tt2col[2] }, - { 1, tt2col[1] } -}; - -static const ICol -tt2x4col[] = { - { 0, tt2col[3] }, - { 1, tt2col[4] } -}; - -static const ICol -tt2x5col[] = { - { 0, tt2col[4] }, - { 1, tt2col[3] }, - { 2, tt2col[2] }, - { 3, tt2col[1] } -}; - -static const ITab -tt2x1 = { - "TT2X1", 1, tt2x1col -}; - -static const ITab -tt2x2 = { - "TT2X2", 2, tt2x2col -}; - -static const ITab -tt2x3 = { - "TT2X3", 2, tt2x3col -}; - -static const ITab -tt2x4 = { - "TT2X4", 2, tt2x4col -}; - -static const ITab -tt2x5 = { - "TT2X5", 4, tt2x5col -}; - -static const ITab -tt2itab[] = { - tt2x1, - tt2x2, - tt2x3, - tt2x4, - tt2x5 -}; - -static const Tab -tt2 = { - "TT2", 5, tt2col, 5, tt2itab -}; - -// all tables - -static const Tab -tablist[] = { - tt1, - tt2 -}; +static void +verifytables() +{ + for (unsigned j = 0; j < tabcount; j++) { + const Tab* t = tablist[j]; + if (t == 0) + continue; + assert(t->m_cols != 0 && t->m_col != 0); + for (unsigned k = 0; k < t->m_cols; k++) { + const Col* c = t->m_col[k]; + assert(c != 0 && c->m_num == k); + assert(! (c->m_pk && c->m_nullable)); + } + assert(t->m_col[t->m_cols] == 0); + { + assert(t->m_keycol < t->m_cols); + const Col* c = t->m_col[t->m_keycol]; + assert(c->m_pk && c->m_type == Col::Unsigned); + } + assert(t->m_itabs != 0 && t->m_itab != 0); + for (unsigned i = 0; i < t->m_itabs; i++) { + const ITab* x = t->m_itab[i]; + if (x == 0) + continue; + assert(x != 0 && x->m_icols != 0 && x->m_icol != 0); + for (unsigned k = 0; k < x->m_icols; k++) { + const ICol* c = x->m_icol[k]; + assert(c != 0 && c->m_num == k && c->m_col.m_num < t->m_cols); + if (x->m_type == ITab::UniqueHashIndex) { + assert(! c->m_col.m_nullable); + } + } + } + assert(t->m_itab[t->m_itabs] == 0); + } +} -static const unsigned -tabcount = sizeof(tablist) / sizeof(tablist[0]); +static void +makebuiltintables(Par par) +{ + LL2("makebuiltintables"); + resetcslist(); + tabcount = 3; + if (tablist == 0) { + tablist = new const Tab* [tabcount]; + for (unsigned j = 0; j < tabcount; j++) { + tablist[j] = 0; + } + } else { + for (unsigned j = 0; j < tabcount; j++) { + delete tablist[j]; + tablist[j] = 0; + } + } + // ti0 - basic + if (usetable(par, 0)) { + Tab* t = new Tab("ti0", 5, 7, 0); + // name - pk - type - length - nullable - cs + t->coladd(0, new Col(*t, 0, "a", 1, Col::Unsigned, 1, 0, 0)); + t->coladd(1, new Col(*t, 1, "b", 0, Col::Unsigned, 1, 1, 0)); + t->coladd(2, new Col(*t, 2, "c", 0, Col::Unsigned, 1, 0, 0)); + t->coladd(3, new Col(*t, 3, "d", 0, Col::Unsigned, 1, 1, 0)); + t->coladd(4, new Col(*t, 4, "e", 0, Col::Unsigned, 1, 0, 0)); + if (useindex(par, 0)) { + // a + ITab* x = new ITab(*t, "ti0x0", ITab::OrderedIndex, 1); + x->icoladd(0, new ICol(*x, 0, *t->m_col[0])); + t->itabadd(0, x); + } + if (useindex(par, 1)) { + // b + ITab* x = new ITab(*t, "ti0x1", ITab::OrderedIndex, 1); + x->icoladd(0, new ICol(*x, 0, *t->m_col[1])); + t->itabadd(1, x); + } + if (useindex(par, 2)) { + // b, c + ITab* x = new ITab(*t, "ti0x2", ITab::OrderedIndex, 2); + x->icoladd(0, new ICol(*x, 0, *t->m_col[1])); + x->icoladd(1, new ICol(*x, 1, *t->m_col[2])); + t->itabadd(2, x); + } + if (useindex(par, 3)) { + // b, e, c, d + ITab* x = new ITab(*t, "ti0x3", ITab::OrderedIndex, 4); + x->icoladd(0, new ICol(*x, 0, *t->m_col[1])); + x->icoladd(1, new ICol(*x, 1, *t->m_col[4])); + x->icoladd(2, new ICol(*x, 2, *t->m_col[2])); + x->icoladd(3, new ICol(*x, 3, *t->m_col[3])); + t->itabadd(3, x); + } + if (useindex(par, 4)) { + // a, c + ITab* x = new ITab(*t, "ti0z4", ITab::UniqueHashIndex, 2); + x->icoladd(0, new ICol(*x, 0, *t->m_col[0])); + x->icoladd(1, new ICol(*x, 1, *t->m_col[2])); + t->itabadd(4, x); + } + if (useindex(par, 5)) { + // a, e + ITab* x = new ITab(*t, "ti0z5", ITab::UniqueHashIndex, 2); + x->icoladd(0, new ICol(*x, 0, *t->m_col[0])); + x->icoladd(1, new ICol(*x, 1, *t->m_col[4])); + t->itabadd(5, x); + } + tablist[0] = t; + } + // ti1 - simple char fields + if (usetable(par, 1)) { + Tab* t = new Tab("ti1", 5, 7, 1); + // name - pk - type - length - nullable - cs + t->coladd(0, new Col(*t, 0, "a", 0, Col::Unsigned, 1, 0, 0)); + t->coladd(1, new Col(*t, 1, "b", 1, Col::Unsigned, 1, 0, 0)); + t->coladd(2, new Col(*t, 2, "c", 0, Col::Varchar, 20, 0, getcs(par))); + t->coladd(3, new Col(*t, 3, "d", 0, Col::Char, 5, 0, getcs(par))); + t->coladd(4, new Col(*t, 4, "e", 0, Col::Longvarchar, 5, 1, getcs(par))); + if (useindex(par, 0)) { + // b + ITab* x = new ITab(*t, "ti1x0", ITab::OrderedIndex, 1); + x->icoladd(0, new ICol(*x, 0, *t->m_col[1])); + t->itabadd(0, x); + } + if (useindex(par, 1)) { + // c, a + ITab* x = new ITab(*t, "ti1x1", ITab::OrderedIndex, 2); + x->icoladd(0, new ICol(*x, 0, *t->m_col[2])); + x->icoladd(1, new ICol(*x, 1, *t->m_col[0])); + t->itabadd(1, x); + } + if (useindex(par, 2)) { + // d + ITab* x = new ITab(*t, "ti1x2", ITab::OrderedIndex, 1); + x->icoladd(0, new ICol(*x, 0, *t->m_col[3])); + t->itabadd(2, x); + } + if (useindex(par, 3)) { + // e, d, c, b + ITab* x = new ITab(*t, "ti1x3", ITab::OrderedIndex, 4); + x->icoladd(0, new ICol(*x, 0, *t->m_col[4])); + x->icoladd(1, new ICol(*x, 1, *t->m_col[3])); + x->icoladd(2, new ICol(*x, 2, *t->m_col[2])); + x->icoladd(3, new ICol(*x, 3, *t->m_col[1])); + t->itabadd(3, x); + } + if (useindex(par, 4)) { + // a, b + ITab* x = new ITab(*t, "ti1z4", ITab::UniqueHashIndex, 2); + x->icoladd(0, new ICol(*x, 0, *t->m_col[0])); + x->icoladd(1, new ICol(*x, 1, *t->m_col[1])); + t->itabadd(4, x); + } + if (useindex(par, 5)) { + // b, c, d + ITab* x = new ITab(*t, "ti1z5", ITab::UniqueHashIndex, 3); + x->icoladd(0, new ICol(*x, 0, *t->m_col[1])); + x->icoladd(1, new ICol(*x, 1, *t->m_col[2])); + x->icoladd(2, new ICol(*x, 2, *t->m_col[3])); + t->itabadd(5, x); + } + tablist[1] = t; + } + // ti2 - complex char fields + if (usetable(par, 2)) { + Tab* t = new Tab("ti2", 5, 7, 2); + // name - pk - type - length - nullable - cs + t->coladd(0, new Col(*t, 0, "a", 1, Col::Char, 31, 0, getcs(par))); + t->coladd(1, new Col(*t, 1, "b", 0, Col::Char, 4, 1, getcs(par))); + t->coladd(2, new Col(*t, 2, "c", 1, Col::Unsigned, 1, 0, 0)); + t->coladd(3, new Col(*t, 3, "d", 1, Col::Varchar, 128, 0, getcs(par))); + t->coladd(4, new Col(*t, 4, "e", 0, Col::Varchar, 7, 0, getcs(par))); + if (useindex(par, 0)) { + // a, c, d + ITab* x = new ITab(*t, "ti2x0", ITab::OrderedIndex, 3); + x->icoladd(0, new ICol(*x, 0, *t->m_col[0])); + x->icoladd(1, new ICol(*x, 1, *t->m_col[2])); + x->icoladd(2, new ICol(*x, 2, *t->m_col[3])); + t->itabadd(0, x); + } + if (useindex(par, 1)) { + // e, d, c, b, a + ITab* x = new ITab(*t, "ti2x1", ITab::OrderedIndex, 5); + x->icoladd(0, new ICol(*x, 0, *t->m_col[4])); + x->icoladd(1, new ICol(*x, 1, *t->m_col[3])); + x->icoladd(2, new ICol(*x, 2, *t->m_col[2])); + x->icoladd(3, new ICol(*x, 3, *t->m_col[1])); + x->icoladd(4, new ICol(*x, 4, *t->m_col[0])); + t->itabadd(1, x); + } + if (useindex(par, 2)) { + // d + ITab* x = new ITab(*t, "ti2x2", ITab::OrderedIndex, 1); + x->icoladd(0, new ICol(*x, 0, *t->m_col[3])); + t->itabadd(2, x); + } + if (useindex(par, 3)) { + // b + ITab* x = new ITab(*t, "ti2x3", ITab::OrderedIndex, 1); + x->icoladd(0, new ICol(*x, 0, *t->m_col[1])); + t->itabadd(3, x); + } + if (useindex(par, 4)) { + // a, c + ITab* x = new ITab(*t, "ti2z4", ITab::UniqueHashIndex, 2); + x->icoladd(0, new ICol(*x, 0, *t->m_col[0])); + x->icoladd(1, new ICol(*x, 1, *t->m_col[2])); + t->itabadd(4, x); + } + if (useindex(par, 5)) { + // a, c, d, e + ITab* x = new ITab(*t, "ti2z5", ITab::UniqueHashIndex, 4); + x->icoladd(0, new ICol(*x, 0, *t->m_col[0])); + x->icoladd(1, new ICol(*x, 1, *t->m_col[2])); + x->icoladd(2, new ICol(*x, 2, *t->m_col[3])); + x->icoladd(3, new ICol(*x, 3, *t->m_col[4])); + t->itabadd(5, x); + } + tablist[2] = t; + } + verifytables(); +} // connections @@ -682,16 +1191,18 @@ struct Con { NdbDictionary::Dictionary* m_dic; NdbConnection* m_tx; NdbOperation* m_op; + NdbIndexOperation* m_indexop; NdbScanOperation* m_scanop; NdbIndexScanOperation* m_indexscanop; - NdbResultSet* m_resultset; + NdbScanFilter* m_scanfilter; enum ScanMode { ScanNo = 0, Committed, Latest, Exclusive }; ScanMode m_scanmode; enum ErrType { ErrNone = 0, ErrDeadlock, ErrNospace, ErrOther }; ErrType m_errtype; Con() : - m_ndb(0), m_dic(0), m_tx(0), m_op(0), - m_scanop(0), m_indexscanop(0), m_resultset(0), m_scanmode(ScanNo), m_errtype(ErrNone) {} + m_ndb(0), m_dic(0), m_tx(0), m_op(0), m_indexop(0), + m_scanop(0), m_indexscanop(0), m_scanfilter(0), + m_scanmode(ScanNo), m_errtype(ErrNone) {} ~Con() { if (m_tx != 0) closeTransaction(); @@ -701,16 +1212,23 @@ struct Con { void disconnect(); int startTransaction(); int getNdbOperation(const Tab& tab); + int getNdbIndexOperation1(const ITab& itab, const Tab& tab); + int getNdbIndexOperation(const ITab& itab, const Tab& tab); int getNdbScanOperation(const Tab& tab); - int getNdbScanOperation(const ITab& itab, const Tab& tab); + int getNdbIndexScanOperation1(const ITab& itab, const Tab& tab); + int getNdbIndexScanOperation(const ITab& itab, const Tab& tab); + int getNdbScanFilter(); 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 beginFilter(int group); + int endFilter(); + int setFilter(int num, int cond, const void* value, unsigned len); int execute(ExecType t); int execute(ExecType t, bool& deadlock, bool& nospace); - int openScanRead(unsigned scanbat, unsigned scanpar); - int openScanExclusive(unsigned scanbat, unsigned scanpar); + int readTuples(Par par); + int readIndexTuples(Par par); int executeScan(); int nextScanResult(bool fetchAllowed); int nextScanResult(bool fetchAllowed, bool& deadlock); @@ -765,6 +1283,28 @@ Con::getNdbOperation(const Tab& tab) } int +Con::getNdbIndexOperation1(const ITab& itab, const Tab& tab) +{ + assert(m_tx != 0); + CHKCON((m_op = m_indexop = m_tx->getNdbIndexOperation(itab.m_name, tab.m_name)) != 0, *this); + return 0; +} + +int +Con::getNdbIndexOperation(const ITab& itab, const Tab& tab) +{ + assert(m_tx != 0); + unsigned tries = 0; + while (1) { + if (getNdbIndexOperation1(itab, tab) == 0) + break; + CHK(++tries < 10); + NdbSleep_MilliSleep(100); + } + return 0; +} + +int Con::getNdbScanOperation(const Tab& tab) { assert(m_tx != 0); @@ -773,7 +1313,7 @@ Con::getNdbScanOperation(const Tab& tab) } int -Con::getNdbScanOperation(const ITab& itab, const Tab& tab) +Con::getNdbIndexScanOperation1(const ITab& itab, const Tab& tab) { assert(m_tx != 0); CHKCON((m_op = m_scanop = m_indexscanop = m_tx->getNdbIndexScanOperation(itab.m_name, tab.m_name)) != 0, *this); @@ -781,6 +1321,29 @@ Con::getNdbScanOperation(const ITab& itab, const Tab& tab) } int +Con::getNdbIndexScanOperation(const ITab& itab, const Tab& tab) +{ + assert(m_tx != 0); + unsigned tries = 0; + while (1) { + if (getNdbIndexScanOperation1(itab, tab) == 0) + break; + CHK(++tries < 10); + NdbSleep_MilliSleep(100); + } + return 0; +} + +int +Con::getNdbScanFilter() +{ + assert(m_tx != 0 && m_scanop != 0); + delete m_scanfilter; + m_scanfilter = new NdbScanFilter(m_scanop); + return 0; +} + +int Con::equal(int num, const char* addr) { assert(m_tx != 0 && m_op != 0); @@ -807,12 +1370,36 @@ Con::setValue(int num, const char* addr) int Con::setBound(int num, int type, const void* value) { - assert(m_tx != 0 && m_op != 0); + assert(m_tx != 0 && m_indexscanop != 0); CHKCON(m_indexscanop->setBound(num, type, value) == 0, *this); return 0; } int +Con::beginFilter(int group) +{ + assert(m_tx != 0 && m_scanfilter != 0); + CHKCON(m_scanfilter->begin((NdbScanFilter::Group)group) == 0, *this); + return 0; +} + +int +Con::endFilter() +{ + assert(m_tx != 0 && m_scanfilter != 0); + CHKCON(m_scanfilter->end() == 0, *this); + return 0; +} + +int +Con::setFilter(int num, int cond, const void* value, unsigned len) +{ + assert(m_tx != 0 && m_scanfilter != 0); + CHKCON(m_scanfilter->cmp((NdbScanFilter::BinaryCondition)cond, num, value, len) == 0, *this); + return 0; +} + +int Con::execute(ExecType t) { assert(m_tx != 0); @@ -841,20 +1428,21 @@ Con::execute(ExecType t, bool& deadlock, bool& nospace) } int -Con::openScanRead(unsigned scanbat, unsigned scanpar) +Con::readTuples(Par par) { - assert(m_tx != 0 && m_op != 0); - NdbOperation::LockMode lm = NdbOperation::LM_Read; - CHKCON((m_resultset = m_scanop->readTuples(lm, scanbat, scanpar)) != 0, *this); + assert(m_tx != 0 && m_scanop != 0); + int scan_flags = 0; + if (par.m_tupscan) + scan_flags |= NdbScanOperation::SF_TupScan; + CHKCON(m_scanop->readTuples(par.m_lockmode, scan_flags, par.m_scanpar) == 0, *this); return 0; } int -Con::openScanExclusive(unsigned scanbat, unsigned scanpar) +Con::readIndexTuples(Par par) { - assert(m_tx != 0 && m_op != 0); - NdbOperation::LockMode lm = NdbOperation::LM_Exclusive; - CHKCON((m_resultset = m_scanop->readTuples(lm, scanbat, scanpar)) != 0, *this); + assert(m_tx != 0 && m_indexscanop != 0); + CHKCON(m_indexscanop->readTuples(par.m_lockmode, 0, par.m_scanpar, par.m_ordered, par.m_descending) == 0, *this); return 0; } @@ -869,8 +1457,8 @@ int Con::nextScanResult(bool fetchAllowed) { int ret; - assert(m_resultset != 0); - CHKCON((ret = m_resultset->nextResult(fetchAllowed)) != -1, *this); + assert(m_scanop != 0); + CHKCON((ret = m_scanop->nextResult(fetchAllowed)) != -1, *this); assert(ret == 0 || ret == 1 || (! fetchAllowed && ret == 2)); return ret; } @@ -895,7 +1483,7 @@ int Con::updateScanTuple(Con& con2) { assert(con2.m_tx != 0); - CHKCON((con2.m_op = m_resultset->updateTuple(con2.m_tx)) != 0, *this); + CHKCON((con2.m_op = m_scanop->updateCurrentTuple(con2.m_tx)) != 0, *this); return 0; } @@ -903,16 +1491,16 @@ int Con::deleteScanTuple(Con& con2) { assert(con2.m_tx != 0); - CHKCON(m_resultset->deleteTuple(con2.m_tx) == 0, *this); + CHKCON(m_scanop->deleteCurrentTuple(con2.m_tx) == 0, *this); return 0; } void Con::closeScan() { - assert(m_resultset != 0); - m_resultset->close(); - m_scanop = 0, m_indexscanop = 0, m_resultset = 0; + assert(m_scanop != 0); + m_scanop->close(); + m_scanop = 0, m_indexscanop = 0; } @@ -922,7 +1510,7 @@ Con::closeTransaction() assert(m_ndb != 0 && m_tx != 0); m_ndb->closeTransaction(m_tx); m_tx = 0, m_op = 0; - m_scanop = 0, m_indexscanop = 0, m_resultset = 0; + m_scanop = 0, m_indexscanop = 0; } void @@ -945,7 +1533,8 @@ Con::printerror(NdbOut& out) if ((code = m_tx->getNdbError().code) != 0) { LL0(++any << " con: error " << m_tx->getNdbError()); die += (code == g_opt.m_die); - if (code == 266 || code == 274 || code == 296 || code == 297 || code == 499) + // 631 is new, occurs only on 4 db nodes, needs to be checked out + if (code == 266 || code == 274 || code == 296 || code == 297 || code == 499 || code == 631) m_errtype = ErrDeadlock; if (code == 826 || code == 827 || code == 902) m_errtype = ErrNospace; @@ -983,9 +1572,9 @@ invalidateindex(Par par) Con& con = par.con(); const Tab& tab = par.tab(); for (unsigned i = 0; i < tab.m_itabs; i++) { - if (! useindex(i)) + if (tab.m_itab[i] == 0) continue; - const ITab& itab = tab.m_itab[i]; + const ITab& itab = *tab.m_itab[i]; invalidateindex(par, itab); } return 0; @@ -1033,16 +1622,14 @@ createtable(Par par) t.setLogging(false); } for (unsigned k = 0; k < tab.m_cols; k++) { - const Col& col = tab.m_col[k]; + const Col& col = *tab.m_col[k]; NdbDictionary::Column c(col.m_name); - c.setType(col.m_type); - c.setLength(col.m_length); + c.setType((NdbDictionary::Column::Type)col.m_type); + c.setLength(col.m_bytelength); // for char NDB API uses length in bytes c.setPrimaryKey(col.m_pk); c.setNullable(col.m_nullable); - if (c.getCharset()) { // test if char type - if (! col.m_pk) - c.setCharset(par.m_cs); - } + if (col.m_chs != 0) + c.setCharset(col.m_chs->m_cs); t.addColumn(c); } con.m_dic = con.m_ndb->getDictionary(); @@ -1073,9 +1660,9 @@ dropindex(Par par) { const Tab& tab = par.tab(); for (unsigned i = 0; i < tab.m_itabs; i++) { - if (! useindex(i)) + if (tab.m_itab[i] == 0) continue; - const ITab& itab = tab.m_itab[i]; + const ITab& itab = *tab.m_itab[i]; CHK(dropindex(par, itab) == 0); } return 0; @@ -1090,10 +1677,13 @@ createindex(Par par, const ITab& itab) LL4(itab); NdbDictionary::Index x(itab.m_name); x.setTable(tab.m_name); - x.setType(NdbDictionary::Index::OrderedIndex); - x.setLogging(false); + x.setType((NdbDictionary::Index::Type)itab.m_type); + if (par.m_nologging || itab.m_type == ITab::OrderedIndex) { + x.setLogging(false); + } for (unsigned k = 0; k < itab.m_icols; k++) { - const Col& col = itab.m_icol[k].m_col; + const ICol& icol = *itab.m_icol[k]; + const Col& col = icol.m_col; x.addColumnName(col.m_name); } con.m_dic = con.m_ndb->getDictionary(); @@ -1107,9 +1697,9 @@ createindex(Par par) { const Tab& tab = par.tab(); for (unsigned i = 0; i < tab.m_itabs; i++) { - if (! useindex(i)) + if (tab.m_itab[i] == 0) continue; - const ITab& itab = tab.m_itab[i]; + const ITab& itab = *tab.m_itab[i]; CHK(createindex(par, itab) == 0); } return 0; @@ -1117,43 +1707,15 @@ createindex(Par par) // data sets -static unsigned -urandom(unsigned n) -{ - if (n == 0) - return 0; - unsigned i = random() % n; - return i; -} - -static int -irandom(unsigned n) -{ - if (n == 0) - return 0; - int i = random() % n; - if (random() & 0x1) - i = -i; - return i; -} - -static bool -randompct(unsigned pct) -{ - if (pct == 0) - return false; - if (pct >= 100) - return true; - return urandom(100) < pct; -} - // Val - typed column value struct Val { const Col& m_col; union { Uint32 m_uint32; - char* m_varchar; + unsigned char* m_char; + unsigned char* m_varchar; + unsigned char* m_longvarchar; }; Val(const Col& col); ~Val(); @@ -1161,10 +1723,17 @@ struct Val { void copy(const void* addr); const void* dataaddr() const; bool m_null; + int equal(Par par) const; + int equal(Par par, const ICol& icol) const; int setval(Par par) const; void calc(Par par, unsigned i); - int verify(const Val& val2) const; - int cmp(const Val& val2) const; + void calckey(Par par, unsigned i); + void calckeychars(Par par, unsigned i, unsigned& n, unsigned char* buf); + void calcnokey(Par par); + void calcnokeychars(Par par, unsigned& n, unsigned char* buf); + int verify(Par par, const Val& val2) const; + int cmp(Par par, const Val& val2) const; + int cmpchars(Par par, const unsigned char* buf1, unsigned len1, const unsigned char* buf2, unsigned len2) const; private: Val& operator=(const Val& val2); }; @@ -1176,10 +1745,16 @@ Val::Val(const Col& col) : m_col(col) { switch (col.m_type) { - case NdbDictionary::Column::Unsigned: + case Col::Unsigned: break; - case NdbDictionary::Column::Varchar: - m_varchar = new char [2 + col.m_length]; + case Col::Char: + m_char = new unsigned char [col.m_bytelength]; + break; + case Col::Varchar: + m_varchar = new unsigned char [1 + col.m_bytelength]; + break; + case Col::Longvarchar: + m_longvarchar = new unsigned char [2 + col.m_bytelength]; break; default: assert(false); @@ -1191,11 +1766,17 @@ Val::~Val() { const Col& col = m_col; switch (col.m_type) { - case NdbDictionary::Column::Unsigned: + case Col::Unsigned: break; - case NdbDictionary::Column::Varchar: + case Col::Char: + delete [] m_char; + break; + case Col::Varchar: delete [] m_varchar; break; + case Col::Longvarchar: + delete [] m_longvarchar; + break; default: assert(false); break; @@ -1220,11 +1801,17 @@ Val::copy(const void* addr) { const Col& col = m_col; switch (col.m_type) { - case NdbDictionary::Column::Unsigned: + case Col::Unsigned: m_uint32 = *(const Uint32*)addr; break; - case NdbDictionary::Column::Varchar: - memcpy(m_varchar, addr, 2 + col.m_length); + case Col::Char: + memcpy(m_char, addr, col.m_bytelength); + break; + case Col::Varchar: + memcpy(m_varchar, addr, 1 + col.m_bytelength); + break; + case Col::Longvarchar: + memcpy(m_longvarchar, addr, 2 + col.m_bytelength); break; default: assert(false); @@ -1238,10 +1825,14 @@ Val::dataaddr() const { const Col& col = m_col; switch (col.m_type) { - case NdbDictionary::Column::Unsigned: + case Col::Unsigned: return &m_uint32; - case NdbDictionary::Column::Varchar: + case Col::Char: + return m_char; + case Col::Varchar: return m_varchar; + case Col::Longvarchar: + return m_longvarchar; default: break; } @@ -1250,18 +1841,37 @@ Val::dataaddr() const } int -Val::setval(Par par) const +Val::equal(Par par) const { Con& con = par.con(); const Col& col = m_col; + assert(col.m_pk && ! m_null); const char* addr = (const char*)dataaddr(); - if (m_null) - addr = 0; - if (col.m_pk) - CHK(con.equal(col.m_num, addr) == 0); - else - CHK(con.setValue(col.m_num, addr) == 0); - LL5("setval [" << m_col << "] " << *this); + LL5("equal [" << col << "] " << *this); + CHK(con.equal(col.m_num, addr) == 0); + return 0; +} + +int +Val::equal(Par par, const ICol& icol) const +{ + Con& con = par.con(); + assert(! m_null); + const char* addr = (const char*)dataaddr(); + LL5("equal [" << icol << "] " << *this); + CHK(con.equal(icol.m_num, addr) == 0); + return 0; +} + +int +Val::setval(Par par) const +{ + Con& con = par.con(); + const Col& col = m_col; + assert(! col.m_pk); + const char* addr = ! m_null ? (const char*)dataaddr() : 0; + LL5("setval [" << col << "] " << *this); + CHK(con.setValue(col.m_num, addr) == 0); return 0; } @@ -1269,58 +1879,170 @@ void Val::calc(Par par, unsigned i) { const Col& col = m_col; + col.m_pk ? calckey(par, i) : calcnokey(par); + if (! m_null) + col.wellformed(dataaddr()); +} + +void +Val::calckey(Par par, unsigned i) +{ + const Col& col = m_col; m_null = false; - if (col.m_pk) { + switch (col.m_type) { + case Col::Unsigned: m_uint32 = i; - return; + break; + case Col::Char: + { + const Chs* chs = col.m_chs; + CHARSET_INFO* cs = chs->m_cs; + unsigned n = 0; + calckeychars(par, i, n, m_char); + // extend by appropriate space + (*cs->cset->fill)(cs, (char*)&m_char[n], col.m_bytelength - n, 0x20); + } + break; + case Col::Varchar: + { + unsigned n = 0; + calckeychars(par, i, n, m_varchar + 1); + // set length and pad with nulls + m_varchar[0] = n; + memset(&m_varchar[1 + n], 0, col.m_bytelength - n); + } + break; + case Col::Longvarchar: + { + unsigned n = 0; + calckeychars(par, i, n, m_longvarchar + 2); + // set length and pad with nulls + m_longvarchar[0] = (n & 0xff); + m_longvarchar[1] = (n >> 8); + memset(&m_longvarchar[2 + n], 0, col.m_bytelength - n); + } + break; + default: + assert(false); + break; } +} + +void +Val::calckeychars(Par par, unsigned i, unsigned& n, unsigned char* buf) +{ + const Col& col = m_col; + const Chs* chs = col.m_chs; + CHARSET_INFO* cs = chs->m_cs; + n = 0; + unsigned len = 0; + while (len < col.m_length) { + if (i % (1 + n) == 0) { + break; + } + const Chr& chr = chs->m_chr[i % maxcharcount]; + assert(n + chr.m_size <= col.m_bytelength); + memcpy(buf + n, chr.m_bytes, chr.m_size); + n += chr.m_size; + len++; + } +} + +void +Val::calcnokey(Par par) +{ + const Col& col = m_col; + m_null = false; if (col.m_nullable && urandom(100) < par.m_pctnull) { m_null = true; return; } - unsigned v = par.m_range + irandom((par.m_pctrange * par.m_range) / 100); + int r = irandom((par.m_pctrange * par.m_range) / 100); + if (par.m_bdir != 0 && urandom(10) != 0) { + if (r < 0 && par.m_bdir > 0 || r > 0 && par.m_bdir < 0) + r = -r; + } + unsigned v = par.m_range + r; switch (col.m_type) { - case NdbDictionary::Column::Unsigned: + case Col::Unsigned: m_uint32 = v; break; - case NdbDictionary::Column::Varchar: + case Col::Char: { + const Chs* chs = col.m_chs; + CHARSET_INFO* cs = chs->m_cs; unsigned n = 0; - while (n < col.m_length) { - if (urandom(1 + col.m_length) == 0) { - // nice distribution on lengths - break; - } - m_varchar[2 + n++] = 'a' + urandom((par.m_pctrange * 10) / 100); - } - m_varchar[0] = (n >> 8); - m_varchar[1] = (n & 0xff); - while (n < col.m_length) { - m_varchar[2 + n++] = 0; - } + calcnokeychars(par, n, m_char); + // extend by appropriate space + (*cs->cset->fill)(cs, (char*)&m_char[n], col.m_bytelength - n, 0x20); + } + break; + case Col::Varchar: + { + unsigned n = 0; + calcnokeychars(par, n, m_varchar + 1); + // set length and pad with nulls + m_varchar[0] = n; + memset(&m_varchar[1 + n], 0, col.m_bytelength - n); + } + break; + case Col::Longvarchar: + { + unsigned n = 0; + calcnokeychars(par, n, m_longvarchar + 2); + // set length and pad with nulls + m_longvarchar[0] = (n & 0xff); + m_longvarchar[1] = (n >> 8); + memset(&m_longvarchar[2 + n], 0, col.m_bytelength - n); } break; default: assert(false); break; } - // verify format - col.verify(dataaddr()); +} + +void +Val::calcnokeychars(Par par, unsigned& n, unsigned char* buf) +{ + const Col& col = m_col; + const Chs* chs = col.m_chs; + CHARSET_INFO* cs = chs->m_cs; + n = 0; + unsigned len = 0; + while (len < col.m_length) { + if (urandom(1 + col.m_bytelength) == 0) { + break; + } + unsigned half = maxcharcount / 2; + int r = irandom((par.m_pctrange * half) / 100); + if (par.m_bdir != 0 && urandom(10) != 0) { + if (r < 0 && par.m_bdir > 0 || r > 0 && par.m_bdir < 0) + r = -r; + } + unsigned i = half + r; + assert(i < maxcharcount); + const Chr& chr = chs->m_chr[i]; + assert(n + chr.m_size <= col.m_bytelength); + memcpy(buf + n, chr.m_bytes, chr.m_size); + n += chr.m_size; + len++; + } } int -Val::verify(const Val& val2) const +Val::verify(Par par, const Val& val2) const { - CHK(cmp(val2) == 0); + CHK(cmp(par, val2) == 0); return 0; } int -Val::cmp(const Val& val2) const +Val::cmp(Par par, const Val& val2) const { const Col& col = m_col; const Col& col2 = val2.m_col; - assert(col.m_type == col2.m_type && col.m_length == col2.m_length); + assert(col.equal(col2)); if (m_null || val2.m_null) { if (! m_null) return +1; @@ -1329,18 +2051,39 @@ Val::cmp(const Val& val2) const return 0; } // verify data formats - col.verify(dataaddr()); - col.verify(val2.dataaddr()); + col.wellformed(dataaddr()); + col.wellformed(val2.dataaddr()); // compare switch (col.m_type) { - case NdbDictionary::Column::Unsigned: - if (m_uint32 < val2.m_uint32) - return -1; - if (m_uint32 > val2.m_uint32) - return +1; - return 0; - case NdbDictionary::Column::Varchar: - return memcmp(&m_varchar[2], &val2.m_varchar[2], col.m_length); + case Col::Unsigned: + { + if (m_uint32 < val2.m_uint32) + return -1; + if (m_uint32 > val2.m_uint32) + return +1; + return 0; + } + break; + case Col::Char: + { + unsigned len = col.m_bytelength; + return cmpchars(par, m_char, len, val2.m_char, len); + } + break; + case Col::Varchar: + { + unsigned len1 = m_varchar[0]; + unsigned len2 = val2.m_varchar[0]; + return cmpchars(par, m_varchar + 1, len1, val2.m_varchar + 1, len2); + } + break; + case Col::Longvarchar: + { + unsigned len1 = m_longvarchar[0] + (m_longvarchar[1] << 8); + unsigned len2 = val2.m_longvarchar[0] + (val2.m_longvarchar[1] << 8); + return cmpchars(par, m_longvarchar + 2, len1, val2.m_longvarchar + 2, len2); + } + break; default: break; } @@ -1348,6 +2091,56 @@ Val::cmp(const Val& val2) const return 0; } +int +Val::cmpchars(Par par, const unsigned char* buf1, unsigned len1, const unsigned char* buf2, unsigned len2) const +{ + const Col& col = m_col; + const Chs* chs = col.m_chs; + CHARSET_INFO* cs = chs->m_cs; + int k; + if (! par.m_collsp) { + unsigned char x1[maxxmulsize * 8000]; + unsigned char x2[maxxmulsize * 8000]; + // make strxfrm pad both to same length + unsigned len = maxxmulsize * col.m_bytelength; + int n1 = NdbSqlUtil::strnxfrm_bug7284(cs, x1, chs->m_xmul * len, buf1, len1); + int n2 = NdbSqlUtil::strnxfrm_bug7284(cs, x2, chs->m_xmul * len, buf2, len2); + assert(n1 != -1 && n1 == n2); + k = memcmp(x1, x2, n1); + } else { + k = (*cs->coll->strnncollsp)(cs, buf1, len1, buf2, len2, false); + } + return k < 0 ? -1 : k > 0 ? +1 : 0; +} + +static void +printstring(NdbOut& out, const unsigned char* str, unsigned len, bool showlen) +{ + char buf[4 * 8000]; + char *p = buf; + *p++ = '['; + if (showlen) { + sprintf(p, "%u:", len); + p += strlen(p); + } + for (unsigned i = 0; i < len; i++) { + unsigned char c = str[i]; + if (c == '\\') { + *p++ = '\\'; + *p++ = c; + } else if (0x20 <= c && c < 0x7e) { + *p++ = c; + } else { + *p++ = '\\'; + *p++ = hexstr[c >> 4]; + *p++ = hexstr[c & 15]; + } + } + *p++ = ']'; + *p = 0; + out << buf; +} + static NdbOut& operator<<(NdbOut& out, const Val& val) { @@ -1357,16 +2150,25 @@ operator<<(NdbOut& out, const Val& val) return out; } switch (col.m_type) { - case NdbDictionary::Column::Unsigned: + case Col::Unsigned: out << val.m_uint32; break; - case NdbDictionary::Column::Varchar: + case Col::Char: + { + unsigned len = col.m_bytelength; + printstring(out, val.m_char, len, false); + } + break; + case Col::Varchar: { - char buf[8000]; - unsigned n = (val.m_varchar[0] << 8) | val.m_varchar[1]; - assert(n <= col.m_length); - sprintf(buf, "'%.*s'[%d]", n, &val.m_varchar[2], n); - out << buf; + unsigned len = val.m_varchar[0]; + printstring(out, val.m_varchar + 1, len, true); + } + break; + case Col::Longvarchar: + { + unsigned len = val.m_longvarchar[0] + (val.m_longvarchar[1] << 8); + printstring(out, val.m_longvarchar + 2, len, true); } break; default: @@ -1383,19 +2185,25 @@ struct Row { const Tab& m_tab; Val** m_val; bool m_exist; - enum Op { NoOp = 0, ReadOp, InsOp, UpdOp, DelOp }; + enum Op { NoOp = 0, ReadOp = 1, InsOp = 2, UpdOp = 4, DelOp = 8, AnyOp = 15 }; Op m_pending; + Row* m_dbrow; // copy of db row before update Row(const Tab& tab); ~Row(); void copy(const Row& row2); - void calc(Par par, unsigned i); - int verify(const Row& row2) const; + void calc(Par par, unsigned i, unsigned mask = 0); + const Row& dbrow() const; + int verify(Par par, const Row& row2) const; int insrow(Par par); int updrow(Par par); + int updrow(Par par, const ITab& itab); int delrow(Par par); + int delrow(Par par, const ITab& itab); int selrow(Par par); + int selrow(Par par, const ITab& itab); int setrow(Par par); - int cmp(const Row& row2) const; + int cmp(Par par, const Row& row2) const; + int cmp(Par par, const Row& row2, const ITab& itab) const; private: Row& operator=(const Row& row2); }; @@ -1405,11 +2213,12 @@ Row::Row(const Tab& tab) : { m_val = new Val* [tab.m_cols]; for (unsigned k = 0; k < tab.m_cols; k++) { - const Col& col = tab.m_col[k]; + const Col& col = *tab.m_col[k]; m_val[k] = new Val(col); } m_exist = false; m_pending = NoOp; + m_dbrow = 0; } Row::~Row() @@ -1419,6 +2228,7 @@ Row::~Row() delete m_val[k]; } delete [] m_val; + delete m_dbrow; } void @@ -1431,27 +2241,49 @@ Row::copy(const Row& row2) const Val& val2 = *row2.m_val[k]; val.copy(val2); } + m_exist = row2.m_exist; + m_pending = row2.m_pending; + if (row2.m_dbrow == 0) { + m_dbrow = 0; + } else { + assert(row2.m_dbrow->m_dbrow == 0); + if (m_dbrow == 0) + m_dbrow = new Row(tab); + m_dbrow->copy(*row2.m_dbrow); + } } void -Row::calc(Par par, unsigned i) +Row::calc(Par par, unsigned i, unsigned mask) { const Tab& tab = m_tab; for (unsigned k = 0; k < tab.m_cols; k++) { - Val& val = *m_val[k]; - val.calc(par, i); + if (! (mask & (1 << k))) { + Val& val = *m_val[k]; + val.calc(par, i); + } } } +const Row& +Row::dbrow() const +{ + if (m_dbrow == 0) + return *this; + assert(m_pending == Row::UpdOp || m_pending == Row::DelOp); + return *m_dbrow; +} + int -Row::verify(const Row& row2) const +Row::verify(Par par, const Row& row2) const { const Tab& tab = m_tab; - assert(&tab == &row2.m_tab && m_exist && row2.m_exist); + const Row& row1 = *this; + assert(&row1.m_tab == &row2.m_tab && row1.m_exist && row2.m_exist); for (unsigned k = 0; k < tab.m_cols; k++) { - const Val& val = *m_val[k]; + const Val& val1 = *row1.m_val[k]; const Val& val2 = *row2.m_val[k]; - CHK(val.verify(val2) == 0); + CHK(val1.verify(par, val2) == 0); } return 0; } @@ -1464,9 +2296,21 @@ Row::insrow(Par par) assert(! m_exist); CHK(con.getNdbOperation(tab) == 0); CHKCON(con.m_op->insertTuple() == 0, con); + Rsq rsq1(tab.m_cols); for (unsigned k = 0; k < tab.m_cols; k++) { - const Val& val = *m_val[k]; - CHK(val.setval(par) == 0); + unsigned k2 = rsq1.next(); + const Val& val = *m_val[k2]; + const Col& col = val.m_col; + if (col.m_pk) + CHK(val.equal(par) == 0); + } + Rsq rsq2(tab.m_cols); + for (unsigned k = 0; k < tab.m_cols; k++) { + unsigned k2 = rsq2.next(); + const Val& val = *m_val[k2]; + const Col& col = val.m_col; + if (! col.m_pk) + CHK(val.setval(par) == 0); } m_pending = InsOp; return 0; @@ -1480,9 +2324,51 @@ Row::updrow(Par par) assert(m_exist); CHK(con.getNdbOperation(tab) == 0); CHKCON(con.m_op->updateTuple() == 0, con); + Rsq rsq1(tab.m_cols); for (unsigned k = 0; k < tab.m_cols; k++) { - const Val& val = *m_val[k]; - CHK(val.setval(par) == 0); + unsigned k2 = rsq1.next(); + const Val& val = *m_val[k2]; + const Col& col = val.m_col; + if (col.m_pk) + CHK(val.equal(par) == 0); + } + Rsq rsq2(tab.m_cols); + for (unsigned k = 0; k < tab.m_cols; k++) { + unsigned k2 = rsq2.next(); + const Val& val = *m_val[k2]; + const Col& col = val.m_col; + if (! col.m_pk) + CHK(val.setval(par) == 0); + } + m_pending = UpdOp; + return 0; +} + +int +Row::updrow(Par par, const ITab& itab) +{ + Con& con = par.con(); + const Tab& tab = m_tab; + assert(itab.m_type == ITab::UniqueHashIndex && &itab.m_tab == &tab); + assert(m_exist); + CHK(con.getNdbIndexOperation(itab, tab) == 0); + CHKCON(con.m_op->updateTuple() == 0, con); + Rsq rsq1(itab.m_icols); + for (unsigned k = 0; k < itab.m_icols; k++) { + unsigned k2 = rsq1.next(); + const ICol& icol = *itab.m_icol[k2]; + const Col& col = icol.m_col; + unsigned m = col.m_num; + const Val& val = *m_val[m]; + CHK(val.equal(par, icol) == 0); + } + Rsq rsq2(tab.m_cols); + for (unsigned k = 0; k < tab.m_cols; k++) { + unsigned k2 = rsq2.next(); + const Val& val = *m_val[k2]; + const Col& col = val.m_col; + if (! col.m_pk) + CHK(val.setval(par) == 0); } m_pending = UpdOp; return 0; @@ -1496,11 +2382,35 @@ Row::delrow(Par par) assert(m_exist); CHK(con.getNdbOperation(m_tab) == 0); CHKCON(con.m_op->deleteTuple() == 0, con); + Rsq rsq1(tab.m_cols); for (unsigned k = 0; k < tab.m_cols; k++) { - const Val& val = *m_val[k]; + unsigned k2 = rsq1.next(); + const Val& val = *m_val[k2]; const Col& col = val.m_col; if (col.m_pk) - CHK(val.setval(par) == 0); + CHK(val.equal(par) == 0); + } + m_pending = DelOp; + return 0; +} + +int +Row::delrow(Par par, const ITab& itab) +{ + Con& con = par.con(); + const Tab& tab = m_tab; + assert(itab.m_type == ITab::UniqueHashIndex && &itab.m_tab == &tab); + assert(m_exist); + CHK(con.getNdbIndexOperation(itab, tab) == 0); + CHKCON(con.m_op->deleteTuple() == 0, con); + Rsq rsq1(itab.m_icols); + for (unsigned k = 0; k < itab.m_icols; k++) { + unsigned k2 = rsq1.next(); + const ICol& icol = *itab.m_icol[k2]; + const Col& col = icol.m_col; + unsigned m = col.m_num; + const Val& val = *m_val[m]; + CHK(val.equal(par, icol) == 0); } m_pending = DelOp; return 0; @@ -1513,11 +2423,33 @@ Row::selrow(Par par) const Tab& tab = m_tab; CHK(con.getNdbOperation(m_tab) == 0); CHKCON(con.m_op->readTuple() == 0, con); + Rsq rsq1(tab.m_cols); for (unsigned k = 0; k < tab.m_cols; k++) { - const Val& val = *m_val[k]; + unsigned k2 = rsq1.next(); + const Val& val = *m_val[k2]; const Col& col = val.m_col; if (col.m_pk) - CHK(val.setval(par) == 0); + CHK(val.equal(par) == 0); + } + return 0; +} + +int +Row::selrow(Par par, const ITab& itab) +{ + Con& con = par.con(); + const Tab& tab = m_tab; + assert(itab.m_type == ITab::UniqueHashIndex && &itab.m_tab == &tab); + CHK(con.getNdbIndexOperation(itab, tab) == 0); + CHKCON(con.m_op->readTuple() == 0, con); + Rsq rsq1(itab.m_icols); + for (unsigned k = 0; k < itab.m_icols; k++) { + unsigned k2 = rsq1.next(); + const ICol& icol = *itab.m_icol[k2]; + const Col& col = icol.m_col; + unsigned m = col.m_num; + const Val& val = *m_val[m]; + CHK(val.equal(par, icol) == 0); } return 0; } @@ -1527,8 +2459,10 @@ Row::setrow(Par par) { Con& con = par.con(); const Tab& tab = m_tab; + Rsq rsq1(tab.m_cols); for (unsigned k = 0; k < tab.m_cols; k++) { - const Val& val = *m_val[k]; + unsigned k2 = rsq1.next(); + const Val& val = *m_val[k2]; const Col& col = val.m_col; if (! col.m_pk) CHK(val.setval(par) == 0); @@ -1538,7 +2472,7 @@ Row::setrow(Par par) } int -Row::cmp(const Row& row2) const +Row::cmp(Par par, const Row& row2) const { const Tab& tab = m_tab; assert(&tab == &row2.m_tab); @@ -1546,13 +2480,47 @@ Row::cmp(const Row& row2) const for (unsigned k = 0; k < tab.m_cols; k++) { const Val& val = *m_val[k]; const Val& val2 = *row2.m_val[k]; - if ((c = val.cmp(val2)) != 0) + if ((c = val.cmp(par, val2)) != 0) + break; + } + return c; +} + +int +Row::cmp(Par par, const Row& row2, const ITab& itab) const +{ + const Tab& tab = m_tab; + int c = 0; + for (unsigned i = 0; i < itab.m_icols; i++) { + const ICol& icol = *itab.m_icol[i]; + const Col& col = icol.m_col; + unsigned k = col.m_num; + assert(k < tab.m_cols); + const Val& val = *m_val[k]; + const Val& val2 = *row2.m_val[k]; + if ((c = val.cmp(par, val2)) != 0) break; } return c; } static NdbOut& +operator<<(NdbOut& out, const Row::Op op) +{ + if (op == Row::NoOp) + out << "NoOp"; + else if (op == Row::InsOp) + out << "InsOp"; + else if (op == Row::UpdOp) + out << "UpdOp"; + else if (op == Row::DelOp) + out << "DelOp"; + else + out << op; + return out; +} + +static NdbOut& operator<<(NdbOut& out, const Row& row) { const Tab& tab = row.m_tab; @@ -1561,10 +2529,21 @@ operator<<(NdbOut& out, const Row& row) out << " "; out << *row.m_val[i]; } - out << " [exist=" << row.m_exist; + out << " exist=" << row.m_exist; if (row.m_pending) out << " pending=" << row.m_pending; - out << "]"; + if (row.m_dbrow != 0) + out << " [dbrow=" << *row.m_dbrow << "]"; + return out; +} + +static NdbOut& +operator<<(NdbOut& out, const Row* rowptr) +{ + if (rowptr == 0) + out << "null"; + else + out << *rowptr; return out; } @@ -1574,38 +2553,47 @@ struct Set { const Tab& m_tab; unsigned m_rows; Row** m_row; - Row** m_saverow; + unsigned* m_rowkey; // maps row number (from 0) in scan to tuple key Row* m_keyrow; NdbRecAttr** m_rec; Set(const Tab& tab, unsigned rows); ~Set(); void reset(); unsigned count() const; - // row methods + // old and new values bool exist(unsigned i) const; - Row::Op pending(unsigned i) const; + void dbsave(unsigned i); + void calc(Par par, unsigned i, unsigned mask = 0); + bool pending(unsigned i, unsigned mask) const; void notpending(unsigned i, ExecType et = Commit); void notpending(const Lst& lst, ExecType et = Commit); - void calc(Par par, unsigned i); + void dbdiscard(unsigned i); + void dbdiscard(const Lst& lst); + const Row& dbrow(unsigned i) const; + // operations int insrow(Par par, unsigned i); int updrow(Par par, unsigned i); + int updrow(Par par, const ITab& itab, unsigned i); int delrow(Par par, unsigned i); - int selrow(Par par, unsigned i); + int delrow(Par par, const ITab& itab, unsigned i); + int selrow(Par par, const Row& keyrow); + int selrow(Par par, const ITab& itab, const Row& keyrow); + // set and get + void setkey(Par par, const Row& keyrow); + void setkey(Par par, const ITab& itab, const Row& keyrow); int setrow(Par par, unsigned i); int getval(Par par); int getkey(Par par, unsigned* i); - int putval(unsigned i, bool force); - // set methods - int verify(const Set& set2) const; - void savepoint(); - void commit(); - void rollback(); + int putval(unsigned i, bool force, unsigned n = ~0); + // verify + int verify(Par par, const Set& set2) const; + int verifyorder(Par par, const ITab& itab, bool descending) const; // protect structure NdbMutex* m_mutex; - void lock() { + void lock() const { NdbMutex_Lock(m_mutex); } - void unlock() { + void unlock() const { NdbMutex_Unlock(m_mutex); } private: @@ -1621,7 +2609,11 @@ Set::Set(const Tab& tab, unsigned rows) : // allocate on need to save space m_row[i] = 0; } - m_saverow = 0; + m_rowkey = new unsigned [m_rows]; + for (unsigned n = 0; n < m_rows; n++) { + // initialize to null + m_rowkey[n] = ~0; + } m_keyrow = new Row(tab); m_rec = new NdbRecAttr* [tab.m_cols]; for (unsigned k = 0; k < tab.m_cols; k++) { @@ -1635,11 +2627,9 @@ Set::~Set() { for (unsigned i = 0; i < m_rows; i++) { delete m_row[i]; - if (m_saverow != 0) - delete m_saverow[i]; } delete [] m_row; - delete [] m_saverow; + delete [] m_rowkey; delete m_keyrow; delete [] m_rec; NdbMutex_Destroy(m_mutex); @@ -1670,6 +2660,8 @@ Set::count() const return count; } +// old and new values + bool Set::exist(unsigned i) const { @@ -1679,27 +2671,97 @@ Set::exist(unsigned i) const return m_row[i]->m_exist; } -Row::Op -Set::pending(unsigned i) const +void +Set::dbsave(unsigned i) { - assert(i < m_rows); - if (m_row[i] == 0) // not allocated => not pending - return Row::NoOp; - return m_row[i]->m_pending; + const Tab& tab = m_tab; + assert(i < m_rows && m_row[i] != 0); + Row& row = *m_row[i]; + LL5("dbsave " << i << ": " << row); + assert(row.m_exist && ! row.m_pending && row.m_dbrow == 0); + // could swap pointers but making copy is safer + Row* rowptr = new Row(tab); + rowptr->copy(row); + row.m_dbrow = rowptr; } void -Set::calc(Par par, unsigned i) +Set::calc(Par par, unsigned i, unsigned mask) { const Tab& tab = m_tab; if (m_row[i] == 0) m_row[i] = new Row(tab); Row& row = *m_row[i]; - // value generation parameters - par.m_pctrange = 40; - row.calc(par, i); + row.calc(par, i, mask); +} + +bool +Set::pending(unsigned i, unsigned mask) const +{ + assert(i < m_rows); + if (m_row[i] == 0) // not allocated => not pending + return Row::NoOp; + return m_row[i]->m_pending & mask; +} + +void +Set::notpending(unsigned i, ExecType et) +{ + assert(m_row[i] != 0); + Row& row = *m_row[i]; + if (et == Commit) { + if (row.m_pending == Row::InsOp) + row.m_exist = true; + if (row.m_pending == Row::DelOp) + row.m_exist = false; + } else { + if (row.m_pending == Row::InsOp) + row.m_exist = false; + if (row.m_pending == Row::DelOp) + row.m_exist = true; + } + row.m_pending = Row::NoOp; +} + +void +Set::notpending(const Lst& lst, ExecType et) +{ + for (unsigned j = 0; j < lst.m_cnt; j++) { + unsigned i = lst.m_arr[j]; + notpending(i, et); + } +} + +void +Set::dbdiscard(unsigned i) +{ + assert(m_row[i] != 0); + Row& row = *m_row[i]; + LL5("dbdiscard " << i << ": " << row); + assert(row.m_dbrow != 0); + delete row.m_dbrow; + row.m_dbrow = 0; } +const Row& +Set::dbrow(unsigned i) const +{ + assert(m_row[i] != 0); + Row& row = *m_row[i]; + return row.dbrow(); +} + +void +Set::dbdiscard(const Lst& lst) +{ + for (unsigned j = 0; j < lst.m_cnt; j++) { + unsigned i = lst.m_arr[j]; + dbdiscard(i); + } +} + +// operations + int Set::insrow(Par par, unsigned i) { @@ -1719,6 +2781,15 @@ Set::updrow(Par par, unsigned i) } int +Set::updrow(Par par, const ITab& itab, unsigned i) +{ + assert(m_row[i] != 0); + Row& row = *m_row[i]; + CHK(row.updrow(par, itab) == 0); + return 0; +} + +int Set::delrow(Par par, unsigned i) { assert(m_row[i] != 0); @@ -1728,16 +2799,68 @@ Set::delrow(Par par, unsigned i) } int -Set::selrow(Par par, unsigned i) +Set::delrow(Par par, const ITab& itab, unsigned i) +{ + assert(m_row[i] != 0); + Row& row = *m_row[i]; + CHK(row.delrow(par, itab) == 0); + return 0; +} + +int +Set::selrow(Par par, const Row& keyrow) { Con& con = par.con(); - m_keyrow->calc(par, i); + const Tab& tab = par.tab(); + setkey(par, keyrow); + LL5("selrow " << tab.m_name << ": keyrow: " << keyrow); CHK(m_keyrow->selrow(par) == 0); CHK(getval(par) == 0); return 0; } int +Set::selrow(Par par, const ITab& itab, const Row& keyrow) +{ + Con& con = par.con(); + setkey(par, itab, keyrow); + LL5("selrow " << itab.m_name << ": keyrow: " << keyrow); + CHK(m_keyrow->selrow(par, itab) == 0); + CHK(getval(par) == 0); + return 0; +} + +// set and get + +void +Set::setkey(Par par, const Row& keyrow) +{ + const Tab& tab = m_tab; + for (unsigned k = 0; k < tab.m_cols; k++) { + const Col& col = *tab.m_col[k]; + if (col.m_pk) { + Val& val1 = *m_keyrow->m_val[k]; + const Val& val2 = *keyrow.dbrow().m_val[k]; + val1.copy(val2); + } + } +} + +void +Set::setkey(Par par, const ITab& itab, const Row& keyrow) +{ + const Tab& tab = m_tab; + for (unsigned k = 0; k < itab.m_icols; k++) { + const ICol& icol = *itab.m_icol[k]; + const Col& col = icol.m_col; + unsigned m = col.m_num; + Val& val1 = *m_keyrow->m_val[m]; + const Val& val2 = *keyrow.dbrow().m_val[m]; + val1.copy(val2); + } +} + +int Set::setrow(Par par, unsigned i) { Con& con = par.con(); @@ -1751,8 +2874,10 @@ Set::getval(Par par) { Con& con = par.con(); const Tab& tab = m_tab; + Rsq rsq1(tab.m_cols); for (unsigned k = 0; k < tab.m_cols; k++) { - CHK(con.getValue(k, m_rec[k]) == 0); + unsigned k2 = rsq1.next(); + CHK(con.getValue(k2, m_rec[k2]) == 0); } return 0; } @@ -1760,16 +2885,18 @@ Set::getval(Par par) int Set::getkey(Par par, unsigned* i) { - assert(m_rec[0] != 0); - const char* aRef0 = m_rec[0]->aRef(); - Uint32 key = *(const Uint32*)aRef0; + const Tab& tab = m_tab; + unsigned k = tab.m_keycol; + assert(m_rec[k] != 0); + const char* aRef = m_rec[k]->aRef(); + Uint32 key = *(const Uint32*)aRef; CHK(key < m_rows); *i = key; return 0; } int -Set::putval(unsigned i, bool force) +Set::putval(unsigned i, bool force, unsigned n) { const Tab& tab = m_tab; if (m_row[i] == 0) @@ -1790,82 +2917,53 @@ Set::putval(unsigned i, bool force) } if (! row.m_exist) row.m_exist = true; + if (n != ~0) + m_rowkey[n] = i; return 0; } -void -Set::notpending(unsigned i, ExecType et) -{ - assert(m_row[i] != 0); - Row& row = *m_row[i]; - if (et == Commit) { - if (row.m_pending == Row::InsOp) - row.m_exist = true; - if (row.m_pending == Row::DelOp) - row.m_exist = false; - } else { - if (row.m_pending == Row::InsOp) - row.m_exist = false; - if (row.m_pending == Row::DelOp) - row.m_exist = true; - } - row.m_pending = Row::NoOp; -} - -void -Set::notpending(const Lst& lst, ExecType et) -{ - for (unsigned j = 0; j < lst.m_cnt; j++) { - unsigned i = lst.m_arr[j]; - notpending(i, et); - } -} - int -Set::verify(const Set& set2) const +Set::verify(Par par, const Set& set2) const { - const Tab& tab = m_tab; - assert(&tab == &set2.m_tab && m_rows == set2.m_rows); + assert(&m_tab == &set2.m_tab && m_rows == set2.m_rows); + LL4("verify set1 count=" << count() << " vs set2 count=" << set2.count()); for (unsigned i = 0; i < m_rows; i++) { - CHK(exist(i) == set2.exist(i)); - if (! exist(i)) - continue; - Row& row = *m_row[i]; - Row& row2 = *set2.m_row[i]; - CHK(row.verify(row2) == 0); + bool ok = true; + if (exist(i) != set2.exist(i)) { + ok = false; + } else if (exist(i)) { + if (dbrow(i).verify(par, set2.dbrow(i)) != 0) + ok = false; + } + if (! ok) { + LL1("verify failed: key=" << i << " row1=" << m_row[i] << " row2=" << set2.m_row[i]); + CHK(0 == 1); + } } return 0; } -void -Set::savepoint() +int +Set::verifyorder(Par par, const ITab& itab, bool descending) const { const Tab& tab = m_tab; - assert(m_saverow == 0); - m_saverow = new Row* [m_rows]; - for (unsigned i = 0; i < m_rows; i++) { - if (m_row[i] == 0) - m_saverow[i] = 0; - else { - m_saverow[i] = new Row(tab); - m_saverow[i]->copy(*m_row[i]); - } + for (unsigned n = 0; n < m_rows; n++) { + unsigned i2 = m_rowkey[n]; + if (i2 == ~0) + break; + if (n == 0) + continue; + unsigned i1 = m_rowkey[n - 1]; + assert(i1 < m_rows && i2 < m_rows); + const Row& row1 = *m_row[i1]; + const Row& row2 = *m_row[i2]; + assert(row1.m_exist && row2.m_exist); + if (! descending) + CHK(row1.cmp(par, row2, itab) <= 0); + else + CHK(row1.cmp(par, row2, itab) >= 0); } -} - -void -Set::commit() -{ - delete [] m_saverow; - m_saverow = 0; -} - -void -Set::rollback() -{ - assert(m_saverow != 0); - m_row = m_saverow; - m_saverow = 0; + return 0; } static NdbOut& @@ -1887,6 +2985,7 @@ struct BVal : public Val { int m_type; BVal(const ICol& icol); int setbnd(Par par) const; + int setflt(Par par) const; }; BVal::BVal(const ICol& icol) : @@ -1906,16 +3005,37 @@ BVal::setbnd(Par par) const return 0; } +int +BVal::setflt(Par par) const +{ + static unsigned index_bound_to_filter_bound[5] = { + NdbScanFilter::COND_GE, + NdbScanFilter::COND_GT, + NdbScanFilter::COND_LE, + NdbScanFilter::COND_LT, + NdbScanFilter::COND_EQ + }; + Con& con = par.con(); + assert(g_compare_null || ! m_null); + const char* addr = ! m_null ? (const char*)dataaddr() : 0; + const ICol& icol = m_icol; + const Col& col = icol.m_col; + unsigned length = col.m_bytesize; + unsigned cond = index_bound_to_filter_bound[m_type]; + CHK(con.setFilter(col.m_num, cond, addr, length) == 0); + return 0; +} + static NdbOut& operator<<(NdbOut& out, const BVal& bval) { const ICol& icol = bval.m_icol; const Col& col = icol.m_col; const Val& val = bval; - out << "type " << bval.m_type; - out << " icol " << icol.m_num; - out << " col " << col.m_name << "(" << col.m_num << ")"; - out << " value " << val; + out << "type=" << bval.m_type; + out << " icol=" << icol.m_num; + out << " col=" << col.m_num << "," << col.m_name; + out << " value=" << val; return out; } @@ -1933,7 +3053,8 @@ struct BSet { void calc(Par par); void calcpk(Par par, unsigned i); int setbnd(Par par) const; - void filter(const Set& set, Set& set2) const; + int setflt(Par par) const; + void filter(Par par, const Set& set, Set& set2) const; }; BSet::BSet(const Tab& tab, const ITab& itab, unsigned rows) : @@ -1967,12 +3088,15 @@ void BSet::calc(Par par) { const ITab& itab = m_itab; + par.m_pctrange = par.m_pctbrange; reset(); for (unsigned k = 0; k < itab.m_icols; k++) { - const ICol& icol = itab.m_icol[k]; + const ICol& icol = *itab.m_icol[k]; const Col& col = icol.m_col; for (unsigned i = 0; i <= 1; i++) { - if (urandom(10) == 0) + if (m_bvals == 0 && urandom(100) == 0) + return; + if (m_bvals != 0 && urandom(3) == 0) return; assert(m_bvals < m_alloc); BVal& bval = *new BVal(icol); @@ -1991,17 +3115,19 @@ BSet::calc(Par par) bval.m_type = 4; if (k + 1 < itab.m_icols) bval.m_type = 4; - // value generation parammeters if (! g_compare_null) par.m_pctnull = 0; - par.m_pctrange = 50; // bit higher + if (bval.m_type == 0 || bval.m_type == 1) + par.m_bdir = -1; + if (bval.m_type == 2 || bval.m_type == 3) + par.m_bdir = +1; do { - bval.calc(par, 0); + bval.calcnokey(par); if (i == 1) { assert(m_bvals >= 2); const BVal& bv1 = *m_bval[m_bvals - 2]; const BVal& bv2 = *m_bval[m_bvals - 1]; - if (bv1.cmp(bv2) > 0 && urandom(100) != 0) + if (bv1.cmp(par, bv2) > 0 && urandom(100) != 0) continue; } } while (0); @@ -2018,7 +3144,7 @@ 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 ICol& icol = *itab.m_icol[k]; const Col& col = icol.m_col; assert(col.m_pk); assert(m_bvals < m_alloc); @@ -2033,26 +3159,48 @@ int BSet::setbnd(Par par) const { if (m_bvals != 0) { - unsigned p1 = urandom(m_bvals); - unsigned p2 = 10009; // prime - // random order + Rsq rsq1(m_bvals); for (unsigned j = 0; j < m_bvals; j++) { - unsigned k = p1 + p2 * j; - const BVal& bval = *m_bval[k % m_bvals]; + unsigned j2 = rsq1.next(); + const BVal& bval = *m_bval[j2]; CHK(bval.setbnd(par) == 0); } // duplicate if (urandom(5) == 0) { - unsigned k = urandom(m_bvals); - const BVal& bval = *m_bval[k]; + unsigned j3 = urandom(m_bvals); + const BVal& bval = *m_bval[j3]; CHK(bval.setbnd(par) == 0); } } return 0; } +int +BSet::setflt(Par par) const +{ + Con& con = par.con(); + CHK(con.getNdbScanFilter() == 0); + CHK(con.beginFilter(NdbScanFilter::AND) == 0); + if (m_bvals != 0) { + Rsq rsq1(m_bvals); + for (unsigned j = 0; j < m_bvals; j++) { + unsigned j2 = rsq1.next(); + const BVal& bval = *m_bval[j2]; + CHK(bval.setflt(par) == 0); + } + // duplicate + if (urandom(5) == 0) { + unsigned j3 = urandom(m_bvals); + const BVal& bval = *m_bval[j3]; + CHK(bval.setflt(par) == 0); + } + } + CHK(con.endFilter() == 0); + return 0; +} + void -BSet::filter(const Set& set, Set& set2) const +BSet::filter(Par par, const Set& set, Set& set2) const { const Tab& tab = m_tab; const ITab& itab = m_itab; @@ -2061,11 +3209,13 @@ BSet::filter(const Set& set, Set& set2) const for (unsigned i = 0; i < set.m_rows; i++) { if (! set.exist(i)) continue; - const Row& row = *set.m_row[i]; + set.lock(); + const Row& row = set.dbrow(i); + set.unlock(); 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 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) { @@ -2082,7 +3232,8 @@ BSet::filter(const Set& set, Set& set2) const const ICol& icol = bval.m_icol; const Col& col = icol.m_col; const Val& val = *row.m_val[col.m_num]; - int ret = bval.cmp(val); + int ret = bval.cmp(par, val); + LL5("cmp: ret=" << ret << " " << bval << " vs " << val); if (bval.m_type == 0) ok2 = (ret <= 0); else if (bval.m_type == 1) @@ -2106,7 +3257,6 @@ BSet::filter(const Set& set, Set& set2) const Row& row2 = *set2.m_row[i]; assert(! row2.m_exist); row2.copy(row); - row2.m_exist = true; } } @@ -2115,9 +3265,8 @@ operator<<(NdbOut& out, const BSet& bset) { out << "bounds=" << bset.m_bvals; for (unsigned j = 0; j < bset.m_bvals; j++) { - out << endl; const BVal& bval = *bset.m_bval[j]; - out << "bound " << j << ": " << bval; + out << " [bound " << j << ": " << bval << "]"; } return out; } @@ -2128,15 +3277,16 @@ static int pkinsert(Par par) { Con& con = par.con(); + const Tab& tab = par.tab(); Set& set = par.set(); - LL3("pkinsert"); + LL3("pkinsert " << tab.m_name); CHK(con.startTransaction() == 0); Lst lst; for (unsigned j = 0; j < par.m_rows; j++) { unsigned j2 = ! par.m_randomkey ? j : urandom(par.m_rows); unsigned i = thrrow(par, j2); set.lock(); - if (set.exist(i) || set.pending(i)) { + if (set.exist(i) || set.pending(i, Row::AnyOp)) { set.unlock(); continue; } @@ -2152,7 +3302,7 @@ pkinsert(Par par) CHK(con.execute(et, deadlock, nospace) == 0); con.closeTransaction(); if (deadlock) { - LL1("pkinsert: stop on deadlock"); + LL1("pkinsert: stop on deadlock [at 1]"); return 0; } if (nospace) { @@ -2173,7 +3323,7 @@ pkinsert(Par par) CHK(con.execute(et, deadlock, nospace) == 0); con.closeTransaction(); if (deadlock) { - LL1("pkinsert: stop on deadlock"); + LL1("pkinsert: stop on deadlock [at 2]"); return 0; } if (nospace) { @@ -2187,14 +3337,15 @@ pkinsert(Par par) } con.closeTransaction(); return 0; -}; +} static int pkupdate(Par par) { Con& con = par.con(); + const Tab& tab = par.tab(); Set& set = par.set(); - LL3("pkupdate"); + LL3("pkupdate " << tab.m_name); CHK(con.startTransaction() == 0); Lst lst; bool deadlock = false; @@ -2203,10 +3354,11 @@ pkupdate(Par par) unsigned j2 = ! par.m_randomkey ? j : urandom(par.m_rows); unsigned i = thrrow(par, j2); set.lock(); - if (! set.exist(i) || set.pending(i)) { + if (! set.exist(i) || set.pending(i, Row::AnyOp)) { set.unlock(); continue; } + set.dbsave(i); set.calc(par, i); CHK(set.updrow(par, i) == 0); set.unlock(); @@ -2218,16 +3370,17 @@ pkupdate(Par par) ExecType et = randompct(par.m_abortpct) ? Rollback : Commit; CHK(con.execute(et, deadlock, nospace) == 0); if (deadlock) { - LL1("pkupdate: stop on deadlock"); + LL1("pkupdate: stop on deadlock [at 1]"); break; } if (nospace) { - LL1("pkupdate: cnt=" << j << " stop on nospace"); + LL1("pkupdate: cnt=" << j << " stop on nospace [at 1]"); break; } con.closeTransaction(); set.lock(); set.notpending(lst, et); + set.dbdiscard(lst); set.unlock(); lst.reset(); CHK(con.startTransaction() == 0); @@ -2239,25 +3392,27 @@ pkupdate(Par par) ExecType et = randompct(par.m_abortpct) ? Rollback : Commit; CHK(con.execute(et, deadlock, nospace) == 0); if (deadlock) { - LL1("pkupdate: stop on deadlock"); + LL1("pkupdate: stop on deadlock [at 2]"); } else if (nospace) { - LL1("pkupdate: end: stop on nospace"); + LL1("pkupdate: end: stop on nospace [at 2]"); } else { set.lock(); set.notpending(lst, et); + set.dbdiscard(lst); set.unlock(); } } con.closeTransaction(); return 0; -}; +} static int pkdelete(Par par) { Con& con = par.con(); + const Tab& tab = par.tab(); Set& set = par.set(); - LL3("pkdelete"); + LL3("pkdelete " << tab.m_name); CHK(con.startTransaction() == 0); Lst lst; bool deadlock = false; @@ -2266,7 +3421,7 @@ pkdelete(Par par) unsigned j2 = ! par.m_randomkey ? j : urandom(par.m_rows); unsigned i = thrrow(par, j2); set.lock(); - if (! set.exist(i) || set.pending(i)) { + if (! set.exist(i) || set.pending(i, Row::AnyOp)) { set.unlock(); continue; } @@ -2280,7 +3435,7 @@ pkdelete(Par par) ExecType et = randompct(par.m_abortpct) ? Rollback : Commit; CHK(con.execute(et, deadlock, nospace) == 0); if (deadlock) { - LL1("pkdelete: stop on deadlock"); + LL1("pkdelete: stop on deadlock [at 1]"); break; } con.closeTransaction(); @@ -2297,7 +3452,7 @@ pkdelete(Par par) ExecType et = randompct(par.m_abortpct) ? Rollback : Commit; CHK(con.execute(et, deadlock, nospace) == 0); if (deadlock) { - LL1("pkdelete: stop on deadlock"); + LL1("pkdelete: stop on deadlock [at 2]"); } else { set.lock(); set.notpending(lst, et); @@ -2306,7 +3461,7 @@ pkdelete(Par par) } con.closeTransaction(); return 0; -}; +} static int pkread(Par par) @@ -2314,19 +3469,19 @@ pkread(Par par) Con& con = par.con(); const Tab& tab = par.tab(); Set& set = par.set(); - LL3((par.m_verify ? "pkverify " : "pkread ") << tab.m_name); + LL3("pkread " << tab.m_name << " verify=" << par.m_verify); // expected const Set& set1 = set; Set set2(tab, set.m_rows); for (unsigned i = 0; i < set.m_rows; i++) { set.lock(); - if (! set.exist(i) || set.pending(i)) { + if (! set.exist(i)) { set.unlock(); continue; } set.unlock(); CHK(con.startTransaction() == 0); - CHK(set2.selrow(par, i) == 0); + CHK(set2.selrow(par, *set1.m_row[i]) == 0); CHK(con.execute(Commit) == 0); unsigned i2 = (unsigned)-1; CHK(set2.getkey(par, &i2) == 0 && i == i2); @@ -2335,7 +3490,7 @@ pkread(Par par) con.closeTransaction(); } if (par.m_verify) - CHK(set1.verify(set2) == 0); + CHK(set1.verify(par, set2) == 0); return 0; } @@ -2364,6 +3519,148 @@ pkreadfast(Par par, unsigned count) return 0; } +// hash index operations + +static int +hashindexupdate(Par par, const ITab& itab) +{ + Con& con = par.con(); + Set& set = par.set(); + LL3("hashindexupdate " << itab.m_name); + CHK(con.startTransaction() == 0); + Lst lst; + bool deadlock = false; + bool nospace = false; + for (unsigned j = 0; j < par.m_rows; j++) { + unsigned j2 = ! par.m_randomkey ? j : urandom(par.m_rows); + unsigned i = thrrow(par, j2); + set.lock(); + if (! set.exist(i) || set.pending(i, Row::AnyOp)) { + set.unlock(); + continue; + } + set.dbsave(i); + // index key columns are not re-calculated + set.calc(par, i, itab.m_colmask); + CHK(set.updrow(par, itab, i) == 0); + set.unlock(); + LL4("hashindexupdate " << i << ": " << *set.m_row[i]); + lst.push(i); + if (lst.cnt() == par.m_batch) { + deadlock = par.m_deadlock; + CHK(con.execute(Commit, deadlock, nospace) == 0); + if (deadlock) { + LL1("hashindexupdate: stop on deadlock [at 1]"); + break; + } + con.closeTransaction(); + set.lock(); + set.notpending(lst); + set.dbdiscard(lst); + set.unlock(); + lst.reset(); + CHK(con.startTransaction() == 0); + } + } + if (! deadlock && lst.cnt() != 0) { + deadlock = par.m_deadlock; + CHK(con.execute(Commit, deadlock, nospace) == 0); + if (deadlock) { + LL1("hashindexupdate: stop on deadlock [at 2]"); + } else { + set.lock(); + set.notpending(lst); + set.dbdiscard(lst); + set.unlock(); + } + } + con.closeTransaction(); + return 0; +} + +static int +hashindexdelete(Par par, const ITab& itab) +{ + Con& con = par.con(); + Set& set = par.set(); + LL3("hashindexdelete " << itab.m_name); + CHK(con.startTransaction() == 0); + Lst lst; + bool deadlock = false; + bool nospace = false; + for (unsigned j = 0; j < par.m_rows; j++) { + unsigned j2 = ! par.m_randomkey ? j : urandom(par.m_rows); + unsigned i = thrrow(par, j2); + set.lock(); + if (! set.exist(i) || set.pending(i, Row::AnyOp)) { + set.unlock(); + continue; + } + CHK(set.delrow(par, itab, i) == 0); + set.unlock(); + LL4("hashindexdelete " << i << ": " << *set.m_row[i]); + lst.push(i); + if (lst.cnt() == par.m_batch) { + deadlock = par.m_deadlock; + CHK(con.execute(Commit, deadlock, nospace) == 0); + if (deadlock) { + LL1("hashindexdelete: stop on deadlock [at 1]"); + break; + } + con.closeTransaction(); + set.lock(); + set.notpending(lst); + set.unlock(); + lst.reset(); + CHK(con.startTransaction() == 0); + } + } + if (! deadlock && lst.cnt() != 0) { + deadlock = par.m_deadlock; + CHK(con.execute(Commit, deadlock, nospace) == 0); + if (deadlock) { + LL1("hashindexdelete: stop on deadlock [at 2]"); + } else { + set.lock(); + set.notpending(lst); + set.unlock(); + } + } + con.closeTransaction(); + return 0; +} + +static int +hashindexread(Par par, const ITab& itab) +{ + Con& con = par.con(); + const Tab& tab = par.tab(); + Set& set = par.set(); + LL3("hashindexread " << itab.m_name << " verify=" << par.m_verify); + // expected + const Set& set1 = set; + Set set2(tab, set.m_rows); + for (unsigned i = 0; i < set.m_rows; i++) { + set.lock(); + if (! set.exist(i)) { + set.unlock(); + continue; + } + set.unlock(); + CHK(con.startTransaction() == 0); + CHK(set2.selrow(par, itab, *set1.m_row[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.count() << ": " << *set2.m_row[i]); + con.closeTransaction(); + } + if (par.m_verify) + CHK(set1.verify(par, set2) == 0); + return 0; +} + // scan read static int @@ -2374,26 +3671,35 @@ scanreadtable(Par par) const Set& set = par.set(); // expected const Set& set1 = set; - LL3((par.m_verify ? "scanverify " : "scanread ") << tab.m_name); + LL3("scanread " << tab.m_name << " lockmode=" << par.m_lockmode << " tupscan=" << par.m_tupscan << " expect=" << set1.count() << " verify=" << par.m_verify); Set set2(tab, set.m_rows); CHK(con.startTransaction() == 0); CHK(con.getNdbScanOperation(tab) == 0); - CHK(con.openScanRead(par.m_scanbat, par.m_scanpar) == 0); + CHK(con.readTuples(par) == 0); set2.getval(par); CHK(con.executeScan() == 0); + unsigned n = 0; + bool deadlock = false; while (1) { int ret; - CHK((ret = con.nextScanResult(true)) == 0 || ret == 1); + deadlock = par.m_deadlock; + CHK((ret = con.nextScanResult(true, deadlock)) == 0 || ret == 1); if (ret == 1) break; + if (deadlock) { + LL1("scanreadtable: stop on deadlock"); + break; + } unsigned i = (unsigned)-1; CHK(set2.getkey(par, &i) == 0); - CHK(set2.putval(i, false) == 0); - LL4("row " << set2.count() << ": " << *set2.m_row[i]); + CHK(set2.putval(i, false, n) == 0); + LL4("row " << n << ": " << *set2.m_row[i]); + n++; } con.closeTransaction(); if (par.m_verify) - CHK(set1.verify(set2) == 0); + CHK(set1.verify(par, set2) == 0); + LL3("scanread " << tab.m_name << " done rows=" << n); return 0; } @@ -2406,7 +3712,7 @@ scanreadtablefast(Par par, unsigned countcheck) LL3("scanfast " << tab.m_name); CHK(con.startTransaction() == 0); CHK(con.getNdbScanOperation(tab) == 0); - CHK(con.openScanRead(par.m_scanbat, par.m_scanpar) == 0); + CHK(con.readTuples(par) == 0); // get 1st column NdbRecAttr* rec; CHK(con.getValue((Uint32)0, rec) == 0); @@ -2425,37 +3731,60 @@ scanreadtablefast(Par par, unsigned countcheck) } static int -scanreadindex(Par par, const ITab& itab, const BSet& bset) +scanreadindex(Par par, const ITab& itab, BSet& bset, bool calc) { Con& con = par.con(); const Tab& tab = par.tab(); const Set& set = par.set(); - // expected Set set1(tab, set.m_rows); - bset.filter(set, set1); - LL3((par.m_verify ? "scanverify " : "scanread ") << itab.m_name << " bounds=" << bset.m_bvals); - LL4(bset); + if (calc) { + while (true) { + bset.calc(par); + bset.filter(par, set, set1); + unsigned n = set1.count(); + // prefer proper subset + if (0 < n && n < set.m_rows) + break; + if (urandom(3) == 0) + break; + set1.reset(); + } + } else { + bset.filter(par, set, set1); + } + LL3("scanread " << itab.m_name << " " << bset << " lockmode=" << par.m_lockmode << " expect=" << set1.count() << " verify=" << par.m_verify << " ordered=" << par.m_ordered << " descending=" << par.m_descending); Set set2(tab, set.m_rows); CHK(con.startTransaction() == 0); - CHK(con.getNdbScanOperation(itab, tab) == 0); - CHK(con.openScanRead(par.m_scanbat, par.m_scanpar) == 0); + CHK(con.getNdbIndexScanOperation(itab, tab) == 0); + CHK(con.readIndexTuples(par) == 0); CHK(bset.setbnd(par) == 0); set2.getval(par); CHK(con.executeScan() == 0); + unsigned n = 0; + bool deadlock = false; while (1) { int ret; - CHK((ret = con.nextScanResult(true)) == 0 || ret == 1); + deadlock = par.m_deadlock; + CHK((ret = con.nextScanResult(true, deadlock)) == 0 || ret == 1); if (ret == 1) break; + if (deadlock) { + LL1("scanreadindex: stop on deadlock"); + 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.count() << ": " << *set2.m_row[i]); + CHK(set2.putval(i, par.m_dups, n) == 0); + LL4("key " << i << " row " << n << ": " << *set2.m_row[i]); + n++; } con.closeTransaction(); - if (par.m_verify) - CHK(set1.verify(set2) == 0); + if (par.m_verify) { + CHK(set1.verify(par, set2) == 0); + if (par.m_ordered) + CHK(set2.verifyorder(par, itab, par.m_descending) == 0); + } + LL3("scanread " << itab.m_name << " done rows=" << n); return 0; } @@ -2465,11 +3794,11 @@ scanreadindexfast(Par par, const ITab& itab, const BSet& bset, unsigned countche Con& con = par.con(); const Tab& tab = par.tab(); const Set& set = par.set(); - LL3("scanfast " << itab.m_name << " bounds=" << bset.m_bvals); + LL3("scanfast " << itab.m_name << " " << bset); LL4(bset); CHK(con.startTransaction() == 0); - CHK(con.getNdbScanOperation(itab, tab) == 0); - CHK(con.openScanRead(par.m_scanbat, par.m_scanpar) == 0); + CHK(con.getNdbIndexScanOperation(itab, tab) == 0); + CHK(con.readIndexTuples(par) == 0); CHK(bset.setbnd(par) == 0); // get 1st column NdbRecAttr* rec; @@ -2489,13 +3818,71 @@ scanreadindexfast(Par par, const ITab& itab, const BSet& bset, unsigned countche } static int +scanreadfilter(Par par, const ITab& itab, BSet& bset, bool calc) +{ + Con& con = par.con(); + const Tab& tab = par.tab(); + const Set& set = par.set(); + Set set1(tab, set.m_rows); + if (calc) { + while (true) { + bset.calc(par); + bset.filter(par, set, set1); + unsigned n = set1.count(); + // prefer proper subset + if (0 < n && n < set.m_rows) + break; + if (urandom(3) == 0) + break; + set1.reset(); + } + } else { + bset.filter(par, set, set1); + } + LL3("scanfilter " << itab.m_name << " " << bset << " lockmode=" << par.m_lockmode << " expect=" << set1.count() << " verify=" << par.m_verify); + Set set2(tab, set.m_rows); + CHK(con.startTransaction() == 0); + CHK(con.getNdbScanOperation(tab) == 0); + CHK(con.readTuples(par) == 0); + CHK(bset.setflt(par) == 0); + set2.getval(par); + CHK(con.executeScan() == 0); + unsigned n = 0; + bool deadlock = false; + while (1) { + int ret; + deadlock = par.m_deadlock; + CHK((ret = con.nextScanResult(true, deadlock)) == 0 || ret == 1); + if (ret == 1) + break; + if (deadlock) { + LL1("scanfilter: stop on deadlock"); + break; + } + unsigned i = (unsigned)-1; + CHK(set2.getkey(par, &i) == 0); + CHK(set2.putval(i, par.m_dups, n) == 0); + LL4("key " << i << " row " << n << ": " << *set2.m_row[i]); + n++; + } + con.closeTransaction(); + if (par.m_verify) { + CHK(set1.verify(par, set2) == 0); + } + LL3("scanfilter " << itab.m_name << " done rows=" << n); + return 0; +} + +static int scanreadindex(Par par, const ITab& itab) { const Tab& tab = par.tab(); for (unsigned i = 0; i < par.m_subsubloop; i++) { - BSet bset(tab, itab, par.m_rows); - bset.calc(par); - CHK(scanreadindex(par, itab, bset) == 0); + if (itab.m_type == ITab::OrderedIndex) { + BSet bset(tab, itab, par.m_rows); + CHK(scanreadfilter(par, itab, bset, true) == 0); + CHK(scanreadindex(par, itab, bset, true) == 0); + } } return 0; } @@ -2505,10 +3892,14 @@ scanreadindex(Par par) { const Tab& tab = par.tab(); for (unsigned i = 0; i < tab.m_itabs; i++) { - if (! useindex(i)) + if (tab.m_itab[i] == 0) continue; - const ITab& itab = tab.m_itab[i]; - CHK(scanreadindex(par, itab) == 0); + const ITab& itab = *tab.m_itab[i]; + if (itab.m_type == ITab::OrderedIndex) { + CHK(scanreadindex(par, itab) == 0); + } else { + CHK(hashindexread(par, itab) == 0); + } } return 0; } @@ -2516,8 +3907,7 @@ scanreadindex(Par par) static int scanreadall(Par par) { - if (par.m_no < 11) - CHK(scanreadtable(par) == 0); + CHK(scanreadtable(par) == 0); CHK(scanreadindex(par) == 0); return 0; } @@ -2537,7 +3927,7 @@ static int timescanpkindex(Par par) { const Tab& tab = par.tab(); - const ITab& itab = tab.m_itab[0]; // 1st index is on PK + 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); @@ -2561,7 +3951,7 @@ static int timepkreadindex(Par par) { const Tab& tab = par.tab(); - const ITab& itab = tab.m_itab[0]; // 1st index is on PK + 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) @@ -2586,9 +3976,10 @@ scanupdatetable(Par par) Set& set = par.set(); LL3("scan update " << tab.m_name); Set set2(tab, set.m_rows); + par.m_lockmode = NdbOperation::LM_Exclusive; CHK(con.startTransaction() == 0); CHK(con.getNdbScanOperation(tab) == 0); - CHK(con.openScanExclusive(par.m_scanbat, par.m_scanpar) == 0); + CHK(con.readTuples(par) == 0); set2.getval(par); CHK(con.executeScan() == 0); unsigned count = 0; @@ -2598,6 +3989,7 @@ scanupdatetable(Par par) CHK(con2.startTransaction() == 0); Lst lst; bool deadlock = false; + bool nospace = false; while (1) { int ret; deadlock = par.m_deadlock; @@ -2605,7 +3997,7 @@ scanupdatetable(Par par) if (ret == 1) break; if (deadlock) { - LL1("scanupdatetable: stop on deadlock"); + LL1("scanupdatetable: stop on deadlock [at 1]"); break; } if (par.m_scanstop != 0 && urandom(par.m_scanstop) == 0) { @@ -2617,13 +4009,14 @@ scanupdatetable(Par par) CHK(set2.getkey(par, &i) == 0); const Row& row = *set.m_row[i]; set.lock(); - if (! set.exist(i) || set.pending(i)) { + if (! set.exist(i) || set.pending(i, Row::AnyOp)) { 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.dbsave(i); set.calc(par, i); CHKTRY(set.setrow(par2, i) == 0, set.unlock()); LL4("scan update " << tab.m_name << ": " << row); @@ -2631,10 +4024,16 @@ scanupdatetable(Par par) } set.unlock(); if (lst.cnt() == par.m_batch) { - CHK(con2.execute(Commit) == 0); + deadlock = par.m_deadlock; + CHK(con2.execute(Commit, deadlock, nospace) == 0); + if (deadlock) { + LL1("scanupdatetable: stop on deadlock [at 2]"); + goto out; + } con2.closeTransaction(); set.lock(); set.notpending(lst); + set.dbdiscard(lst); set.unlock(); count += lst.cnt(); lst.reset(); @@ -2642,10 +4041,16 @@ scanupdatetable(Par par) } CHK((ret = con.nextScanResult(false)) == 0 || ret == 1 || ret == 2); if (ret == 2 && lst.cnt() != 0) { - CHK(con2.execute(Commit) == 0); + deadlock = par.m_deadlock; + CHK(con2.execute(Commit, deadlock, nospace) == 0); + if (deadlock) { + LL1("scanupdatetable: stop on deadlock [at 3]"); + goto out; + } con2.closeTransaction(); set.lock(); set.notpending(lst); + set.dbdiscard(lst); set.unlock(); count += lst.cnt(); lst.reset(); @@ -2655,6 +4060,7 @@ scanupdatetable(Par par) if (ret == 1) break; } +out: con2.closeTransaction(); LL3("scan update " << tab.m_name << " rows updated=" << count); con.closeTransaction(); @@ -2669,9 +4075,10 @@ scanupdateindex(Par par, const ITab& itab, const BSet& bset) Set& set = par.set(); LL3("scan update " << itab.m_name); Set set2(tab, set.m_rows); + par.m_lockmode = NdbOperation::LM_Exclusive; CHK(con.startTransaction() == 0); - CHK(con.getNdbScanOperation(itab, tab) == 0); - CHK(con.openScanExclusive(par.m_scanbat, par.m_scanpar) == 0); + CHK(con.getNdbIndexScanOperation(itab, tab) == 0); + CHK(con.readTuples(par) == 0); CHK(bset.setbnd(par) == 0); set2.getval(par); CHK(con.executeScan() == 0); @@ -2682,6 +4089,7 @@ scanupdateindex(Par par, const ITab& itab, const BSet& bset) CHK(con2.startTransaction() == 0); Lst lst; bool deadlock = false; + bool nospace = false; while (1) { int ret; deadlock = par.m_deadlock; @@ -2689,7 +4097,7 @@ scanupdateindex(Par par, const ITab& itab, const BSet& bset) if (ret == 1) break; if (deadlock) { - LL1("scanupdateindex: stop on deadlock"); + LL1("scanupdateindex: stop on deadlock [at 1]"); break; } if (par.m_scanstop != 0 && urandom(par.m_scanstop) == 0) { @@ -2701,13 +4109,14 @@ scanupdateindex(Par par, const ITab& itab, const BSet& bset) CHK(set2.getkey(par, &i) == 0); const Row& row = *set.m_row[i]; set.lock(); - if (! set.exist(i) || set.pending(i)) { + if (! set.exist(i) || set.pending(i, Row::AnyOp)) { 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.dbsave(i); set.calc(par, i); CHKTRY(set.setrow(par2, i) == 0, set.unlock()); LL4("scan update " << itab.m_name << ": " << row); @@ -2715,10 +4124,16 @@ scanupdateindex(Par par, const ITab& itab, const BSet& bset) } set.unlock(); if (lst.cnt() == par.m_batch) { - CHK(con2.execute(Commit) == 0); + deadlock = par.m_deadlock; + CHK(con2.execute(Commit, deadlock, nospace) == 0); + if (deadlock) { + LL1("scanupdateindex: stop on deadlock [at 2]"); + goto out; + } con2.closeTransaction(); set.lock(); set.notpending(lst); + set.dbdiscard(lst); set.unlock(); count += lst.cnt(); lst.reset(); @@ -2726,10 +4141,16 @@ scanupdateindex(Par par, const ITab& itab, const BSet& bset) } CHK((ret = con.nextScanResult(false)) == 0 || ret == 1 || ret == 2); if (ret == 2 && lst.cnt() != 0) { - CHK(con2.execute(Commit) == 0); + deadlock = par.m_deadlock; + CHK(con2.execute(Commit, deadlock, nospace) == 0); + if (deadlock) { + LL1("scanupdateindex: stop on deadlock [at 3]"); + goto out; + } con2.closeTransaction(); set.lock(); set.notpending(lst); + set.dbdiscard(lst); set.unlock(); count += lst.cnt(); lst.reset(); @@ -2737,6 +4158,7 @@ scanupdateindex(Par par, const ITab& itab, const BSet& bset) } } while (ret == 0); } +out: con2.closeTransaction(); LL3("scan update " << itab.m_name << " rows updated=" << count); con.closeTransaction(); @@ -2748,9 +4170,13 @@ scanupdateindex(Par par, const ITab& itab) { const Tab& tab = par.tab(); for (unsigned i = 0; i < par.m_subsubloop; i++) { - BSet bset(tab, itab, par.m_rows); - bset.calc(par); - CHK(scanupdateindex(par, itab, bset) == 0); + if (itab.m_type == ITab::OrderedIndex) { + BSet bset(tab, itab, par.m_rows); + bset.calc(par); + CHK(scanupdateindex(par, itab, bset) == 0); + } else { + CHK(hashindexupdate(par, itab) == 0); + } } return 0; } @@ -2760,9 +4186,9 @@ scanupdateindex(Par par) { const Tab& tab = par.tab(); for (unsigned i = 0; i < tab.m_itabs; i++) { - if (! useindex(i)) + if (tab.m_itab[i] == 0) continue; - const ITab& itab = tab.m_itab[i]; + const ITab& itab = *tab.m_itab[i]; CHK(scanupdateindex(par, itab) == 0); } return 0; @@ -2788,6 +4214,7 @@ readverify(Par par) LL2("skip verify in this version"); // implement in 5.0 version par.m_verify = false; } + par.m_lockmode = NdbOperation::LM_CommittedRead; CHK(pkread(par) == 0); CHK(scanreadall(par) == 0); return 0; @@ -2799,43 +4226,106 @@ readverifyfull(Par par) if (par.m_noverify) return 0; par.m_verify = true; - if (par.m_no == 0) + if (par.m_abortpct != 0) { + LL2("skip verify in this version"); // implement in 5.0 version + par.m_verify = false; + } + par.m_lockmode = NdbOperation::LM_CommittedRead; + const Tab& tab = par.tab(); + if (par.m_no == 0) { + // thread 0 scans table CHK(scanreadtable(par) == 0); - else { - const Tab& tab = par.tab(); - unsigned i = par.m_no; - if (i <= tab.m_itabs && useindex(i)) { - const ITab& itab = tab.m_itab[i - 1]; + // once more via tup scan + par.m_tupscan = true; + if (NDB_VERSION < MAKE_VERSION(5, 1, 0)) //TODO + CHK(scanreadtable(par) == 0); + } + // each thread scans different indexes + for (unsigned i = 0; i < tab.m_itabs; i++) { + if (i % par.m_threads != par.m_no) + continue; + if (tab.m_itab[i] == 0) + continue; + const ITab& itab = *tab.m_itab[i]; + if (itab.m_type == ITab::OrderedIndex) { BSet bset(tab, itab, par.m_rows); - CHK(scanreadindex(par, itab, bset) == 0); + CHK(scanreadindex(par, itab, bset, false) == 0); + } else { + CHK(hashindexread(par, itab) == 0); } } return 0; } static int +readverifyindex(Par par) +{ + if (par.m_noverify) + return 0; + par.m_verify = true; + par.m_lockmode = NdbOperation::LM_CommittedRead; + unsigned sel = urandom(10); + if (sel < 9) { + par.m_ordered = true; + par.m_descending = (sel < 5); + } + CHK(scanreadindex(par) == 0); + return 0; +} + +static int pkops(Par par) { + const Tab& tab = par.tab(); par.m_randomkey = true; for (unsigned i = 0; i < par.m_subsubloop; i++) { + unsigned j = 0; + while (j < tab.m_itabs) { + if (tab.m_itab[j] != 0) { + const ITab& itab = *tab.m_itab[j]; + if (itab.m_type == ITab::UniqueHashIndex && urandom(5) == 0) + break; + } + j++; + } unsigned sel = urandom(10); if (par.m_slno % 2 == 0) { // favor insert if (sel < 8) { CHK(pkinsert(par) == 0); } else if (sel < 9) { - CHK(pkupdate(par) == 0); + if (j == tab.m_itabs) + CHK(pkupdate(par) == 0); + else { + const ITab& itab = *tab.m_itab[j]; + CHK(hashindexupdate(par, itab) == 0); + } } else { - CHK(pkdelete(par) == 0); + if (j == tab.m_itabs) + CHK(pkdelete(par) == 0); + else { + const ITab& itab = *tab.m_itab[j]; + CHK(hashindexdelete(par, itab) == 0); + } } } else { // favor delete if (sel < 1) { CHK(pkinsert(par) == 0); } else if (sel < 2) { - CHK(pkupdate(par) == 0); + if (j == tab.m_itabs) + CHK(pkupdate(par) == 0); + else { + const ITab& itab = *tab.m_itab[j]; + CHK(hashindexupdate(par, itab) == 0); + } } else { - CHK(pkdelete(par) == 0); + if (j == tab.m_itabs) + CHK(pkdelete(par) == 0); + else { + const ITab& itab = *tab.m_itab[j]; + CHK(hashindexdelete(par, itab) == 0); + } } } } @@ -2846,6 +4336,7 @@ static int pkupdatescanread(Par par) { par.m_dups = true; + par.m_deadlock = true; unsigned sel = urandom(10); if (sel < 5) { CHK(pkupdate(par) == 0); @@ -2854,6 +4345,10 @@ pkupdatescanread(Par par) CHK(scanreadtable(par) == 0); } else { par.m_verify = false; + if (sel < 8) { + par.m_ordered = true; + par.m_descending = (sel < 7); + } CHK(scanreadindex(par) == 0); } return 0; @@ -2873,6 +4368,10 @@ mixedoperations(Par par) } else if (sel < 6) { CHK(scanupdatetable(par) == 0); } else { + if (sel < 8) { + par.m_ordered = true; + par.m_descending = (sel < 7); + } CHK(scanupdateindex(par) == 0); } return 0; @@ -3134,6 +4633,24 @@ tbuild(Par par) } static int +tindexscan(Par par) +{ + RUNSTEP(par, droptable, ST); + RUNSTEP(par, createtable, ST); + RUNSTEP(par, invalidatetable, MT); + RUNSTEP(par, createindex, ST); + RUNSTEP(par, invalidateindex, MT); + RUNSTEP(par, pkinsert, MT); + RUNSTEP(par, readverifyfull, MT); + for (par.m_slno = 0; par.m_slno < par.m_subloop; par.m_slno++) { + LL4("subloop " << par.m_slno); + RUNSTEP(par, readverifyindex, MT); + } + return 0; +} + + +static int tpkops(Par par) { RUNSTEP(par, droptable, ST); @@ -3266,6 +4783,10 @@ ttimemaint(Par par) static int ttimescan(Par par) { + if (par.tab().m_itab[0] == 0) { + LL1("ttimescan - no index 0, skipped"); + return 0; + } Tmr t1, t2; RUNSTEP(par, droptable, ST); RUNSTEP(par, createtable, ST); @@ -3288,6 +4809,10 @@ ttimescan(Par par) static int ttimepkread(Par par) { + if (par.tab().m_itab[0] == 0) { + LL1("ttimescan - no index 0, skipped"); + return 0; + } Tmr t1, t2; RUNSTEP(par, droptable, ST); RUNSTEP(par, createtable, ST); @@ -3328,7 +4853,7 @@ struct TCase { static const TCase tcaselist[] = { TCase("a", tbuild, "index build"), - // "b" in 5.0 + TCase("b", tindexscan, "index scans"), TCase("c", tpkops, "pk operations"), TCase("d", tpkopsread, "pk operations and scan reads"), TCase("e", tmixedops, "pk operations and scan operations"), @@ -3357,13 +4882,32 @@ printcases() static void printtables() { - ndbout << "tables and indexes (X1 is on table PK):" << endl; + Par par(g_opt); + makebuiltintables(par); + ndbout << "tables and indexes (x=ordered z=hash x0=on pk):" << endl; for (unsigned j = 0; j < tabcount; j++) { - const Tab& tab = tablist[j]; - ndbout << " " << tab.m_name; + if (tablist[j] == 0) + continue; + const Tab& tab = *tablist[j]; + const char* tname = tab.m_name; + ndbout << " " << tname; for (unsigned i = 0; i < tab.m_itabs; i++) { - const ITab& itab = tab.m_itab[i]; - ndbout << " " << itab.m_name; + if (tab.m_itab[i] == 0) + continue; + const ITab& itab = *tab.m_itab[i]; + const char* iname = itab.m_name; + if (strncmp(tname, iname, strlen(tname)) == 0) + iname += strlen(tname); + ndbout << " " << iname; + ndbout << "("; + for (unsigned k = 0; k < itab.m_icols; k++) { + if (k != 0) + ndbout << ","; + const ICol& icol = *itab.m_icol[k]; + const Col& col = icol.m_col; + ndbout << col.m_name; + } + ndbout << ")"; } ndbout << endl; } @@ -3373,15 +4917,29 @@ static int runtest(Par par) { LL1("start"); - if (par.m_seed != 0) + if (par.m_seed == -1) { + // good enough for daily run + unsigned short seed = (getpid() ^ time(0)); + LL1("random seed: " << seed); + srandom((unsigned)seed); + } else if (par.m_seed != 0) { + LL1("random seed: " << par.m_seed); srandom(par.m_seed); + } else { + LL1("random seed: loop number"); + } + // cs assert(par.m_csname != 0); - CHARSET_INFO* cs; - CHK((cs = get_charset_by_name(par.m_csname, MYF(0))) != 0 || (cs = get_charset_by_csname(par.m_csname, MY_CS_PRIMARY, MYF(0))) != 0); - par.m_cs = cs; + if (strcmp(par.m_csname, "random") != 0) { + CHARSET_INFO* cs; + CHK((cs = get_charset_by_name(par.m_csname, MYF(0))) != 0 || (cs = get_charset_by_csname(par.m_csname, MY_CS_PRIMARY, MYF(0))) != 0); + par.m_cs = cs; + } + // con Con con; CHK(con.connect() == 0); par.m_con = &con; + // threads g_thrlist = new Thr* [par.m_threads]; unsigned n; for (n = 0; n < par.m_threads; n++) { @@ -3400,16 +4958,18 @@ runtest(Par par) const TCase& tcase = tcaselist[i]; if (par.m_case != 0 && strchr(par.m_case, tcase.m_name[0]) == 0) continue; + makebuiltintables(par); LL1("case " << tcase.m_name << " - " << tcase.m_desc); for (unsigned j = 0; j < tabcount; j++) { - if (! usetable(j)) + if (tablist[j] == 0) continue; - const Tab& tab = tablist[j]; + const Tab& tab = *tablist[j]; par.m_tab = &tab; - delete par.m_set; par.m_set = new Set(tab, par.m_totrows); LL1("table " << tab.m_name); CHK(tcase.m_func(par) == 0); + delete par.m_set; + par.m_set = 0; } } } @@ -3433,7 +4993,7 @@ NDB_COMMAND(testOIBasic, "testOIBasic", "testOIBasic", "testOIBasic", 65535) { ndb_init(); if (ndbout_mutex == NULL) - ndbout_mutex= NdbMutex_Create(); + ndbout_mutex = NdbMutex_Create(); while (++argv, --argc > 0) { const char* arg = argv[0]; if (*arg != '-') { @@ -3461,6 +5021,10 @@ NDB_COMMAND(testOIBasic, "testOIBasic", "testOIBasic", "testOIBasic", 65535) continue; } } + if (strcmp(arg, "-collsp") == 0) { + g_opt.m_collsp = true; + continue; + } if (strcmp(arg, "-core") == 0) { g_opt.m_core = true; continue; @@ -3539,12 +5103,6 @@ NDB_COMMAND(testOIBasic, "testOIBasic", "testOIBasic", "testOIBasic", 65535) continue; } } - if (strcmp(arg, "-scanbat") == 0) { - if (++argv, --argc > 0) { - g_opt.m_scanbat = atoi(argv[0]); - continue; - } - } if (strcmp(arg, "-scanpar") == 0) { if (++argv, --argc > 0) { g_opt.m_scanpar = atoi(argv[0]); @@ -3572,7 +5130,8 @@ NDB_COMMAND(testOIBasic, "testOIBasic", "testOIBasic", "testOIBasic", 65535) if (strcmp(arg, "-threads") == 0) { if (++argv, --argc > 0) { g_opt.m_threads = atoi(argv[0]); - continue; + if (1 <= g_opt.m_threads) + continue; } } if (strcmp(arg, "-v") == 0) { @@ -3589,7 +5148,7 @@ NDB_COMMAND(testOIBasic, "testOIBasic", "testOIBasic", "testOIBasic", 65535) printhelp(); goto wrongargs; } - ndbout << "testOIBasic: unknown option " << arg; + ndbout << "testOIBasic: bad or unknown option " << arg; goto usage; } { @@ -3600,7 +5159,6 @@ NDB_COMMAND(testOIBasic, "testOIBasic", "testOIBasic", "testOIBasic", 65535) delete g_ncc; g_ncc = 0; } - // always exit with NDBT code ok: return NDBT_ProgramExit(NDBT_OK); failed: diff --git a/ndb/test/ndbapi/testPartitioning.cpp b/ndb/test/ndbapi/testPartitioning.cpp new file mode 100644 index 00000000000..9d67c27354b --- /dev/null +++ b/ndb/test/ndbapi/testPartitioning.cpp @@ -0,0 +1,430 @@ +/* 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 <NDBT_Test.hpp> +#include <NDBT_ReturnCodes.h> +#include <HugoTransactions.hpp> +#include <UtilTransactions.hpp> +#include <NdbRestarter.hpp> + +#define GETNDB(ps) ((NDBT_NdbApiStep*)ps)->getNdb() + +static Uint32 max_dks = 0; + +static +int +run_drop_table(NDBT_Context* ctx, NDBT_Step* step) +{ + NdbDictionary::Dictionary* dict = GETNDB(step)->getDictionary(); + dict->dropTable(ctx->getTab()->getName()); + return 0; +} + +static +int +add_distribution_key(Ndb*, NdbDictionary::Table& tab, int when) +{ + switch(when){ + case 0: // Before + break; + case 1: // After + return 0; + default: + return 0; + } + + int keys = tab.getNoOfPrimaryKeys(); + int dks = (2 * keys + 2) / 3; dks = (dks > max_dks ? max_dks : dks); + int cnt = 0; + + for(unsigned i = 0; i<tab.getNoOfColumns(); i++) + if(tab.getColumn(i)->getPrimaryKey() && + tab.getColumn(i)->getCharset() != 0) + keys--; + + Uint32 max = NDB_MAX_NO_OF_ATTRIBUTES_IN_KEY - tab.getNoOfPrimaryKeys(); + + if(max_dks < max) + max = max_dks; + + if(keys <= 1 && max > 0) + { + dks = 1 + (rand() % max); + ndbout_c("%s pks: %d dks: %d", tab.getName(), keys, dks); + while(dks--) + { + NdbDictionary::Column col; + BaseString name; + name.assfmt("PK_DK_%d", dks); + col.setName(name.c_str()); + col.setType(NdbDictionary::Column::Unsigned); + col.setLength(1); + col.setNullable(false); + col.setPrimaryKey(true); + col.setDistributionKey(true); + tab.addColumn(col); + } + } + else + { + for(unsigned i = 0; i<tab.getNoOfColumns(); i++) + { + NdbDictionary::Column* col = tab.getColumn(i); + if(col->getPrimaryKey() && col->getCharset() == 0) + { + if(dks >= keys || (rand() % 100) > 50) + { + col->setDistributionKey(true); + dks--; + } + keys--; + } + } + } + ndbout << (NDBT_Table&)tab << endl; + + return 0; +} + +static int +run_create_table(NDBT_Context* ctx, NDBT_Step* step) +{ + max_dks = ctx->getProperty("distributionkey", (unsigned)0); + + if(NDBT_Tables::createTable(GETNDB(step), + ctx->getTab()->getName(), + false, false, + max_dks?add_distribution_key:0) == NDBT_OK) + { + return NDBT_OK; + } + + if(GETNDB(step)->getDictionary()->getNdbError().code == 745) + return NDBT_OK; + + return NDBT_FAILED; +} + +static int +run_create_pk_index(NDBT_Context* ctx, NDBT_Step* step){ + bool orderedIndex = ctx->getProperty("OrderedIndex", (unsigned)0); + + Ndb* pNdb = GETNDB(step); + const NdbDictionary::Table *pTab = + pNdb->getDictionary()->getTable(ctx->getTab()->getName()); + + if(!pTab) + return NDBT_OK; + + bool logged = ctx->getProperty("LoggedIndexes", orderedIndex ? 0 : 1); + + BaseString name; + name.assfmt("IND_%s_PK_%c", pTab->getName(), orderedIndex ? 'O' : 'U'); + + // Create index + if (orderedIndex) + ndbout << "Creating " << ((logged)?"logged ": "temporary ") << "ordered index " + << name.c_str() << " ("; + else + ndbout << "Creating " << ((logged)?"logged ": "temporary ") << "unique index " + << name.c_str() << " ("; + + NdbDictionary::Index pIdx(name.c_str()); + pIdx.setTable(pTab->getName()); + if (orderedIndex) + pIdx.setType(NdbDictionary::Index::OrderedIndex); + else + pIdx.setType(NdbDictionary::Index::UniqueHashIndex); + for (int c = 0; c< pTab->getNoOfColumns(); c++){ + const NdbDictionary::Column * col = pTab->getColumn(c); + if(col->getPrimaryKey()){ + pIdx.addIndexColumn(col->getName()); + ndbout << col->getName() <<" "; + } + } + + pIdx.setStoredIndex(logged); + ndbout << ") "; + if (pNdb->getDictionary()->createIndex(pIdx) != 0){ + ndbout << "FAILED!" << endl; + const NdbError err = pNdb->getDictionary()->getNdbError(); + ERR(err); + return NDBT_FAILED; + } + + ndbout << "OK!" << endl; + return NDBT_OK; +} + +static int run_create_pk_index_drop(NDBT_Context* ctx, NDBT_Step* step){ + bool orderedIndex = ctx->getProperty("OrderedIndex", (unsigned)0); + + Ndb* pNdb = GETNDB(step); + const NdbDictionary::Table *pTab = + pNdb->getDictionary()->getTable(ctx->getTab()->getName()); + + if(!pTab) + return NDBT_OK; + + BaseString name; + name.assfmt("IND_%s_PK_%c", pTab->getName(), orderedIndex ? 'O' : 'U'); + + ndbout << "Dropping index " << name.c_str() << " "; + if (pNdb->getDictionary()->dropIndex(name.c_str(), pTab->getName()) != 0){ + ndbout << "FAILED!" << endl; + ERR(pNdb->getDictionary()->getNdbError()); + return NDBT_FAILED; + } else { + ndbout << "OK!" << endl; + } + + return NDBT_OK; +} + +static int +run_tests(Ndb* p_ndb, HugoTransactions& hugoTrans, int records) +{ + if (hugoTrans.loadTable(p_ndb, records) != 0) + { + return NDBT_FAILED; + } + + if(hugoTrans.pkReadRecords(p_ndb, records) != 0) + { + return NDBT_FAILED; + } + + if(hugoTrans.pkUpdateRecords(p_ndb, records) != 0) + { + return NDBT_FAILED; + } + + if(hugoTrans.pkDelRecords(p_ndb, records) != 0) + { + return NDBT_FAILED; + } + + if (hugoTrans.loadTable(p_ndb, records) != 0) + { + return NDBT_FAILED; + } + + if(hugoTrans.scanUpdateRecords(p_ndb, records) != 0) + { + return NDBT_FAILED; + } + + Uint32 abort = 23; + for(Uint32 j = 0; j<5; j++){ + Uint32 parallelism = (j == 1 ? 1 : j * 3); + ndbout_c("parallelism: %d", parallelism); + if (hugoTrans.scanReadRecords(p_ndb, records, abort, parallelism, + NdbOperation::LM_Read) != 0) + { + return NDBT_FAILED; + } + if (hugoTrans.scanReadRecords(p_ndb, records, abort, parallelism, + NdbOperation::LM_Exclusive) != 0) + { + return NDBT_FAILED; + } + if (hugoTrans.scanReadRecords(p_ndb, records, abort, parallelism, + NdbOperation::LM_CommittedRead) != 0) + { + return NDBT_FAILED; + } + } + + if(hugoTrans.clearTable(p_ndb, records) != 0) + { + return NDBT_FAILED; + } + + return 0; +} + +static int +run_pk_dk(NDBT_Context* ctx, NDBT_Step* step) +{ + Ndb* p_ndb = GETNDB(step); + int records = ctx->getNumRecords(); + const NdbDictionary::Table *tab = + p_ndb->getDictionary()->getTable(ctx->getTab()->getName()); + + if(!tab) + return NDBT_OK; + + HugoTransactions hugoTrans(*tab); + + return run_tests(p_ndb, hugoTrans, records); +} + +int +run_index_dk(NDBT_Context* ctx, NDBT_Step* step) +{ + Ndb* p_ndb = GETNDB(step); + int records = ctx->getNumRecords(); + const NdbDictionary::Table *pTab = + p_ndb->getDictionary()->getTable(ctx->getTab()->getName()); + + if(!pTab) + return NDBT_OK; + + bool orderedIndex = ctx->getProperty("OrderedIndex", (unsigned)0); + + BaseString name; + name.assfmt("IND_%s_PK_%c", pTab->getName(), orderedIndex ? 'O' : 'U'); + + const NdbDictionary::Index * idx = + p_ndb->getDictionary()->getIndex(name.c_str(), pTab->getName()); + + if(!idx) + { + ndbout << "Failed to retreive index: " << name.c_str() << endl; + return NDBT_FAILED; + } + + HugoTransactions hugoTrans(*pTab, idx); + + return run_tests(p_ndb, hugoTrans, records); +} + +static int +run_startHint(NDBT_Context* ctx, NDBT_Step* step) +{ + Ndb* p_ndb = GETNDB(step); + int records = ctx->getNumRecords(); + const NdbDictionary::Table *tab = + p_ndb->getDictionary()->getTable(ctx->getTab()->getName()); + + if(!tab) + return NDBT_OK; + + HugoTransactions hugoTrans(*tab); + if (hugoTrans.loadTable(p_ndb, records) != 0) + { + return NDBT_FAILED; + } + + NdbRestarter restarter; + if(restarter.insertErrorInAllNodes(8050) != 0) + return NDBT_FAILED; + + HugoCalculator dummy(*tab); + int result = NDBT_OK; + for(int i = 0; i<records && result == NDBT_OK; i++) + { + char buffer[8000]; + char* start= buffer + (rand() & 7); + char* pos= start; + + for(int j = 0; j<tab->getNoOfColumns(); j++) + { + if(tab->getColumn(j)->getPartitionKey()) + { + ndbout_c(tab->getColumn(j)->getName()); + int sz = tab->getColumn(j)->getSizeInBytes(); + int aligned_size = 4 * ((sz + 3) >> 2); + memset(pos, 0, aligned_size); + dummy.calcValue(i, j, 0, pos, sz); + pos += aligned_size; + } + } + // Now we have the pk + NdbTransaction* pTrans= p_ndb->startTransaction(tab, start,(pos - start)); + HugoOperations ops(*tab); + ops.setTransaction(pTrans); + if(ops.pkReadRecord(p_ndb, i, 1) != NDBT_OK) + { + result = NDBT_FAILED; + break; + } + + if(ops.execute_Commit(p_ndb) != 0) + { + result = NDBT_FAILED; + break; + } + + ops.closeTransaction(p_ndb); + } + restarter.insertErrorInAllNodes(0); + return result; +} + + +NDBT_TESTSUITE(testPartitioning); +TESTCASE("pk_dk", + "Primary key operations with distribution key") +{ + TC_PROPERTY("distributionkey", ~0); + INITIALIZER(run_drop_table); + INITIALIZER(run_create_table); + INITIALIZER(run_pk_dk); + INITIALIZER(run_drop_table); +} +TESTCASE("hash_index_dk", + "Unique index operatations with distribution key") +{ + TC_PROPERTY("distributionkey", ~0); + TC_PROPERTY("OrderedIndex", (unsigned)0); + INITIALIZER(run_drop_table); + INITIALIZER(run_create_table); + INITIALIZER(run_create_pk_index); + INITIALIZER(run_index_dk); + INITIALIZER(run_create_pk_index_drop); + INITIALIZER(run_drop_table); +} +TESTCASE("ordered_index_dk", + "Ordered index operatations with distribution key") +{ + TC_PROPERTY("distributionkey", (unsigned)1); + TC_PROPERTY("OrderedIndex", (unsigned)1); + INITIALIZER(run_drop_table); + INITIALIZER(run_create_table); + INITIALIZER(run_create_pk_index); + INITIALIZER(run_index_dk); + INITIALIZER(run_create_pk_index_drop); + INITIALIZER(run_drop_table); +} +TESTCASE("startTransactionHint", + "Test startTransactionHint wo/ distribution key") +{ + TC_PROPERTY("distributionkey", (unsigned)0); + INITIALIZER(run_drop_table); + INITIALIZER(run_create_table); + INITIALIZER(run_startHint); + INITIALIZER(run_drop_table); +} +TESTCASE("startTransactionHint_dk", + "Test startTransactionHint with distribution key") +{ + TC_PROPERTY("distributionkey", (unsigned)~0); + INITIALIZER(run_drop_table); + INITIALIZER(run_create_table); + INITIALIZER(run_startHint); + INITIALIZER(run_drop_table); +} +NDBT_TESTSUITE_END(testPartitioning); + +int main(int argc, const char** argv){ + ndb_init(); + testPartitioning.setCreateTable(false); + return testPartitioning.execute(argc, argv); +} + + + diff --git a/ndb/test/ndbapi/testReadPerf.cpp b/ndb/test/ndbapi/testReadPerf.cpp index 3adcb5a2d9b..ba5f3c4232d 100644 --- a/ndb/test/ndbapi/testReadPerf.cpp +++ b/ndb/test/ndbapi/testReadPerf.cpp @@ -119,7 +119,13 @@ main(int argc, const char** argv){ myRandom48Init(NdbTick_CurrentMillisecond()); memset(g_times, 0, sizeof(g_times)); - g_ndb = new Ndb("TEST_DB"); + Ndb_cluster_connection con; + if(con.connect(12, 5, 1)) + { + return NDBT_ProgramExit(NDBT_FAILED); + } + + g_ndb = new Ndb(&con, "TEST_DB"); if(g_ndb->init() != 0){ g_err << "init() failed" << endl; goto error; @@ -266,7 +272,6 @@ run_read(){ NdbScanOperation * pSp; NdbIndexOperation * pUp; NdbIndexScanOperation * pIp; - NdbResultSet * rs = (NdbResultSet*)~0; Uint32 start_row = rand() % (rows - range); Uint32 stop_row = start_row + range; @@ -319,27 +324,27 @@ run_read(){ } break; case 4: - pOp = pIp = pTrans->getNdbIndexScanOperation(g_ordered,g_table); - rs = pIp->readTuples(NdbScanOperation::LM_CommittedRead, 0, 0); + pOp = pSp = pIp = pTrans->getNdbIndexScanOperation(g_ordered,g_table); + pIp->readTuples(NdbScanOperation::LM_CommittedRead, 0, 0); check = pIp->setBound(pk, NdbIndexScanOperation::BoundEQ, &start_row); break; case 5: - pOp = pIp = pTrans->getNdbIndexScanOperation(g_ordered,g_table); - rs = pIp->readTuples(NdbScanOperation::LM_CommittedRead, 0, 0); + pOp = pSp = pIp = pTrans->getNdbIndexScanOperation(g_ordered,g_table); + pIp->readTuples(NdbScanOperation::LM_CommittedRead, 0, 0); check = pIp->setBound(pk, NdbIndexScanOperation::BoundLE, &start_row); check = pIp->setBound(pk, NdbIndexScanOperation::BoundGT, &stop_row); start_row = stop_row; break; case 6: - pOp = pIp = pTrans->getNdbIndexScanOperation(g_ordered,g_table); - rs = pIp->readTuples(NdbScanOperation::LM_CommittedRead, 0, 0, true); + pOp = pSp = pIp = pTrans->getNdbIndexScanOperation(g_ordered,g_table); + pIp->readTuples(NdbScanOperation::LM_CommittedRead, 0, 0, true); check = pIp->setBound(pk, NdbIndexScanOperation::BoundLE, &start_row); check = pIp->setBound(pk, NdbIndexScanOperation::BoundGT, &stop_row); start_row = stop_row; break; case 7: pOp = pSp = pTrans->getNdbScanOperation(g_table); - rs = pSp->readTuples(NdbScanOperation::LM_CommittedRead, 0, 0); + pSp->readTuples(NdbScanOperation::LM_CommittedRead, 0, 0); NdbScanFilter filter(pOp) ; filter.begin(NdbScanFilter::AND); filter.ge(pk, start_row); @@ -355,7 +360,6 @@ run_read(){ ndbout << pTrans->getNdbError() << endl; } assert(check == 0); - assert(rs); for(int j = 0; j<g_tab->getNoOfColumns(); j++){ res = pOp->getValue(j); @@ -368,7 +372,7 @@ run_read(){ } assert(check == 0); if(g_paramters[P_OPER].value >= 4){ - while((check = rs->nextResult(true)) == 0){ + while((check = pSp->nextResult(true)) == 0){ cnt++; } @@ -377,13 +381,13 @@ run_read(){ return -1; } assert(check == 1); - rs->close(); + pSp->close(); } } assert(g_paramters[P_OPER].value < 4 || (cnt == range)); - + pTrans->close(); - + stop = NdbTick_CurrentMillisecond(); g_times[g_paramters[P_OPER].value] += (stop - start1); return 0; diff --git a/ndb/test/ndbapi/testScan.cpp b/ndb/test/ndbapi/testScan.cpp index f1018d29846..2802f1c950e 100644 --- a/ndb/test/ndbapi/testScan.cpp +++ b/ndb/test/ndbapi/testScan.cpp @@ -316,11 +316,16 @@ int runScanReadIndex(NDBT_Context* ctx, NDBT_Step* step){ while (pIdx && i<loops && !ctx->isTestStopped()) { g_info << i << ": "; bool sort = (rand() % 100) > 50 ? true : false; + bool desc = (rand() % 100) > 50 ? true : false; + desc = false; // random causes too many deadlocks + int scan_flags = + (NdbScanOperation::SF_OrderBy & -(int)sort) | + (NdbScanOperation::SF_Descending & -(int)desc); NdbOperation::LockMode lm = (NdbOperation::LockMode)(rand() % 3); if (hugoTrans.scanReadRecords(GETNDB(step), pIdx, records, abort, parallelism, lm, - sort) != 0){ + scan_flags) != 0){ return NDBT_FAILED; } i++; @@ -333,6 +338,8 @@ int runScanReadCommitted(NDBT_Context* ctx, NDBT_Step* step){ int records = ctx->getNumRecords(); int parallelism = ctx->getProperty("Parallelism", 240); int abort = ctx->getProperty("AbortProb", 5); + bool tupScan = ctx->getProperty("TupScan"); + int scan_flags = (NdbScanOperation::SF_TupScan & -(int)tupScan); int i = 0; HugoTransactions hugoTrans(*ctx->getTab()); @@ -340,7 +347,8 @@ int runScanReadCommitted(NDBT_Context* ctx, NDBT_Step* step){ g_info << i << ": "; if (hugoTrans.scanReadRecords(GETNDB(step), records, abort, parallelism, - NdbOperation::LM_CommittedRead) != 0){ + NdbOperation::LM_CommittedRead, + scan_flags) != 0){ return NDBT_FAILED; } i++; @@ -1013,8 +1021,7 @@ int runScanRestart(NDBT_Context* ctx, NDBT_Step* step){ return NDBT_FAILED; } - NdbResultSet* rs = pOp->readTuples(); - if( rs == 0 ) { + if( pOp->readTuples() ) { ERR(pCon->getNdbError()); return NDBT_FAILED; } @@ -1042,7 +1049,7 @@ int runScanRestart(NDBT_Context* ctx, NDBT_Step* step){ int res; int row = 0; - while(row < record && (res = rs->nextResult()) == 0) { + while(row < record && (res = pOp->nextResult()) == 0) { if(calc.verifyRowValues(&tmpRow) != 0){ abort(); return NDBT_FAILED; @@ -1055,14 +1062,14 @@ int runScanRestart(NDBT_Context* ctx, NDBT_Step* step){ return NDBT_FAILED; } g_info << " restarting" << endl; - if((res = rs->restart()) != 0){ + if((res = pOp->restart()) != 0){ ERR(pCon->getNdbError()); abort(); return NDBT_FAILED; } row = 0; - while((res = rs->nextResult()) == 0) { + while((res = pOp->nextResult()) == 0) { if(calc.verifyRowValues(&tmpRow) != 0){ abort(); return NDBT_FAILED; @@ -1080,6 +1087,44 @@ int runScanRestart(NDBT_Context* ctx, NDBT_Step* step){ } +int +runScanParallelism(NDBT_Context* ctx, NDBT_Step* step){ + int loops = ctx->getNumLoops() + 3; + int records = ctx->getNumRecords(); + int abort = ctx->getProperty("AbortProb", 15); + + Uint32 fib[] = { 1, 2 }; + Uint32 parallelism = 0; // start with 0 + int i = 0; + HugoTransactions hugoTrans(*ctx->getTab()); + while (i<loops && !ctx->isTestStopped()) { + g_info << i << ": "; + + if (hugoTrans.scanReadRecords(GETNDB(step), records, abort, parallelism, + NdbOperation::LM_Read) != 0){ + return NDBT_FAILED; + } + if (hugoTrans.scanReadRecords(GETNDB(step), records, abort, parallelism, + NdbOperation::LM_Exclusive) != 0){ + return NDBT_FAILED; + } + if (hugoTrans.scanReadRecords(GETNDB(step), records, abort, parallelism, + NdbOperation::LM_CommittedRead) != 0){ + return NDBT_FAILED; + } + if (hugoTrans.scanUpdateRecords(GETNDB(step), records, abort, parallelism) + != 0){ + return NDBT_FAILED; + } + i++; + parallelism = fib[0]; + Uint32 next = fib[0] + fib[1]; + fib[0] = fib[1]; + fib[1] = next; + } + return NDBT_OK; +} + NDBT_TESTSUITE(testScan); TESTCASE("ScanRead", "Verify scan requirement: It should be possible "\ @@ -1113,6 +1158,18 @@ TESTCASE("ScanReadCommitted240", "downgraded to the maximum parallelism value for the current config)"){ INITIALIZER(runLoadTable); TC_PROPERTY("Parallelism", 240); + TC_PROPERTY("TupScan", (Uint32)0); + STEP(runScanReadCommitted); + FINALIZER(runClearTable); +} +TESTCASE("ScanTupReadCommitted240", + "Verify scan requirement: It should be possible to scan read committed with "\ + "parallelism, test with parallelism 240(240 would automatically be "\ + "downgraded to the maximum parallelism value for the current config). "\ + "Scans TUP pages directly without using ACC."){ + INITIALIZER(runLoadTable); + TC_PROPERTY("Parallelism", 240); + TC_PROPERTY("TupScan", 1); STEP(runScanReadCommitted); FINALIZER(runClearTable); } @@ -1540,6 +1597,12 @@ TESTCASE("ScanRestart", STEP(runScanRestart); FINALIZER(runClearTable); } +TESTCASE("ScanParallelism", + "Test scan with different parallelism"){ + INITIALIZER(runLoadTable); + STEP(runScanParallelism); + FINALIZER(runClearTable); +} NDBT_TESTSUITE_END(testScan); int main(int argc, const char** argv){ diff --git a/ndb/test/ndbapi/testScanPerf.cpp b/ndb/test/ndbapi/testScanPerf.cpp index 45f0468bc70..a730136c3af 100644 --- a/ndb/test/ndbapi/testScanPerf.cpp +++ b/ndb/test/ndbapi/testScanPerf.cpp @@ -38,10 +38,10 @@ struct Parameter { #define P_ROWS 7 #define P_LOOPS 8 #define P_CREATE 9 -#define P_LOAD 10 #define P_RESET 11 +#define P_MULTI 12 -#define P_MAX 12 +#define P_MAX 13 static Parameter @@ -57,7 +57,8 @@ g_paramters[] = { { "iterations", 3, 1, ~0 }, { "create_drop", 1, 0, 1 }, { "data", 1, 0, 1 }, - { "q-reset bounds", 0, 1, 0 } + { "q-reset bounds", 0, 1, 0 }, + { "multi read range", 1000, 1, ~0 } }; static Ndb* g_ndb = 0; @@ -67,10 +68,7 @@ static char g_tablename[256]; static char g_indexname[256]; int create_table(); -int load_table(); int run_scan(); -int clear_table(); -int drop_table(); int main(int argc, const char** argv){ @@ -101,7 +99,13 @@ main(int argc, const char** argv){ myRandom48Init(NdbTick_CurrentMillisecond()); - g_ndb = new Ndb("TEST_DB"); + Ndb_cluster_connection con; + if(con.connect(12, 5, 1)) + { + return NDBT_ProgramExit(NDBT_FAILED); + } + + g_ndb = new Ndb(&con, "TEST_DB"); if(g_ndb->init() != 0){ g_err << "init() failed" << endl; goto error; @@ -117,14 +121,8 @@ main(int argc, const char** argv){ BaseString::snprintf(g_indexname, sizeof(g_indexname), "IDX_%s", T); if(create_table()) goto error; - if(load_table()) - goto error; if(run_scan()) goto error; - if(clear_table()) - goto error; - if(drop_table()) - goto error; } if(g_ndb) delete g_ndb; @@ -139,6 +137,7 @@ create_table(){ NdbDictionary::Dictionary* dict = g_ndb->getDictionary(); assert(dict); if(g_paramters[P_CREATE].value){ + g_ndb->getDictionary()->dropTable(g_tablename); const NdbDictionary::Table * pTab = NDBT_Tables::getTable(g_tablename); assert(pTab); NdbDictionary::Table copy = * pTab; @@ -167,46 +166,18 @@ create_table(){ g_index = dict->getIndex(g_indexname, g_tablename); assert(g_table); assert(g_index); - return 0; -} -int -drop_table(){ - if(!g_paramters[P_CREATE].value) - return 0; - if(g_ndb->getDictionary()->dropTable(g_table->getName()) != 0){ - g_err << "Failed to drop table: " << g_table->getName() << endl; - return -1; - } - g_table = 0; - return 0; -} - -int -load_table(){ - if(!g_paramters[P_LOAD].value) - return 0; - - int rows = g_paramters[P_ROWS].value; - HugoTransactions hugoTrans(* g_table); - if (hugoTrans.loadTable(g_ndb, rows)){ - g_err.println("Failed to load %s with %d rows", g_table->getName(), rows); - return -1; + if(g_paramters[P_CREATE].value) + { + int rows = g_paramters[P_ROWS].value; + HugoTransactions hugoTrans(* g_table); + if (hugoTrans.loadTable(g_ndb, rows)){ + g_err.println("Failed to load %s with %d rows", + g_table->getName(), rows); + return -1; + } } - return 0; -} - -int -clear_table(){ - if(!g_paramters[P_LOAD].value) - return 0; - int rows = g_paramters[P_ROWS].value; - UtilTransactions utilTrans(* g_table); - if (utilTrans.clearTable(g_ndb, rows) != 0){ - g_err.println("Failed to clear table %s", g_table->getName()); - return -1; - } return 0; } @@ -227,13 +198,12 @@ run_scan(){ Uint32 tot = g_paramters[P_ROWS].value; - if(g_paramters[P_BOUND].value == 2 || g_paramters[P_FILT].value == 2) + if(g_paramters[P_BOUND].value >= 2 || g_paramters[P_FILT].value == 2) iter *= g_paramters[P_ROWS].value; NdbScanOperation * pOp = 0; NdbIndexScanOperation * pIOp = 0; NdbConnection * pTrans = 0; - NdbResultSet * rs = 0; int check = 0; for(int i = 0; i<iter; i++){ @@ -246,7 +216,7 @@ run_scan(){ } int par = g_paramters[P_PARRA].value; - int bat = g_paramters[P_BATCH].value; + int bat = 0; // g_paramters[P_BATCH].value; NdbScanOperation::LockMode lm; switch(g_paramters[P_LOCK].value){ case 0: @@ -265,13 +235,13 @@ run_scan(){ if(g_paramters[P_ACCESS].value == 0){ pOp = pTrans->getNdbScanOperation(g_tablename); assert(pOp); - rs = pOp->readTuples(lm, bat, par); + pOp->readTuples(lm, bat, par); } else { if(g_paramters[P_RESET].value == 0 || pIOp == 0) { pOp= pIOp= pTrans->getNdbIndexScanOperation(g_indexname, g_tablename); bool ord = g_paramters[P_ACCESS].value == 2; - rs = pIOp->readTuples(lm, bat, par, ord); + pIOp->readTuples(lm, bat, par, ord); } else { @@ -294,14 +264,26 @@ run_scan(){ #else pIOp->setBound((Uint32)0, NdbIndexScanOperation::BoundEQ, &row); #endif + if(g_paramters[P_RESET].value == 2) + goto execute; + break; + } + case 3: { // read multi + int multi = g_paramters[P_MULTI].value; + int tot = g_paramters[P_ROWS].value; + for(; multi > 0 && i < iter; --multi, i++) + { + int row = rand() % tot; + pIOp->setBound((Uint32)0, NdbIndexScanOperation::BoundEQ, &row); + pIOp->end_of_bound(i); + } + if(g_paramters[P_RESET].value == 2) + goto execute; break; } } - if(g_paramters[P_RESET].value == 2) - goto execute; } assert(pOp); - assert(rs); switch(g_paramters[P_FILT].value){ case 0: // All @@ -337,15 +319,18 @@ run_scan(){ for(int i = 0; i<g_table->getNoOfColumns(); i++){ pOp->getValue(i); } + + if(g_paramters[P_RESET].value == 1) + g_paramters[P_RESET].value = 2; execute: int rows = 0; check = pTrans->execute(NoCommit); assert(check == 0); int fetch = g_paramters[P_FETCH].value; - while((check = rs->nextResult(true)) == 0){ + while((check = pOp->nextResult(true)) == 0){ do { rows++; - } while(!fetch && ((check = rs->nextResult(false)) == 0)); + } while(!fetch && ((check = pOp->nextResult(false)) == 0)); if(check == -1){ err(pTrans->getNdbError()); return -1; diff --git a/ndb/test/ndbapi/testTimeout.cpp b/ndb/test/ndbapi/testTimeout.cpp index 71c11b25859..b02751ec819 100644 --- a/ndb/test/ndbapi/testTimeout.cpp +++ b/ndb/test/ndbapi/testTimeout.cpp @@ -87,47 +87,6 @@ int runClearTable(NDBT_Context* ctx, NDBT_Step* step){ result = NDBT_FAILED; \ break; } -int runTimeoutTrans(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(); - - int timeout = ctx->getProperty("TransactionInactiveTimeout",TIMEOUT); - - int minSleep = (int)(timeout * 1.5); - int maxSleep = timeout * 2; - ndbout << "TransactionInactiveTimeout="<< timeout - << ", minSleep="<<minSleep - << ", maxSleep="<<maxSleep<<endl; - - HugoOperations hugoOps(*ctx->getTab()); - Ndb* pNdb = GETNDB(step); - - for (int l = 0; l < loops && result == NDBT_OK; l++){ - - do{ - // Commit transaction - CHECK(hugoOps.startTransaction(pNdb) == 0); - CHECK(hugoOps.pkReadRecord(pNdb, stepNo) == 0); - CHECK(hugoOps.execute_NoCommit(pNdb) == 0); - - int sleep = minSleep + myRandom48(maxSleep-minSleep); - ndbout << "Sleeping for " << sleep << " milliseconds" << endl; - NdbSleep_MilliSleep(sleep); - - // Expect that transaction has timed-out - CHECK(hugoOps.execute_Commit(pNdb) == 237); - - } while(false); - - hugoOps.closeTransaction(pNdb); - } - - return result; -} - int runTimeoutTrans2(NDBT_Context* ctx, NDBT_Step* step){ int result = NDBT_OK; int loops = ctx->getNumLoops(); @@ -407,27 +366,6 @@ TESTCASE("DontTimeoutTransaction5", FINALIZER(resetTransactionTimeout); FINALIZER(runClearTable); } -TESTCASE("TimeoutTransaction", - "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); - STEPS(runTimeoutTrans, 1); - FINALIZER(resetTransactionTimeout); - FINALIZER(runClearTable); -} -TESTCASE("TimeoutTransaction5", - "Test that the transaction does timeout " \ - "if we sleep during the transaction. Use a sleep " \ - "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 "\ diff --git a/ndb/test/ndbapi/test_event.cpp b/ndb/test/ndbapi/test_event.cpp index cb2793e42b9..2df50f21e43 100644 --- a/ndb/test/ndbapi/test_event.cpp +++ b/ndb/test/ndbapi/test_event.cpp @@ -14,11 +14,11 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "NDBT_Test.hpp" -#include "NDBT_ReturnCodes.h" -#include "HugoTransactions.hpp" -#include "UtilTransactions.hpp" -#include "TestNdbEventOperation.hpp" +#include <NDBT_Test.hpp> +#include <NDBT_ReturnCodes.h> +#include <HugoTransactions.hpp> +#include <UtilTransactions.hpp> +#include <TestNdbEventOperation.hpp> #define GETNDB(ps) ((NDBT_NdbApiStep*)ps)->getNdb() @@ -32,6 +32,69 @@ int runCreateEvent(NDBT_Context* ctx, NDBT_Step* step) return NDBT_OK; } +int runCreateShadowTable(NDBT_Context* ctx, NDBT_Step* step) +{ + const NdbDictionary::Table *table= ctx->getTab(); + char buf[1024]; + sprintf(buf, "%s_SHADOW", table->getName()); + + GETNDB(step)->getDictionary()->dropTable(buf); + if (GETNDB(step)->getDictionary()->getTable(buf)) + { + g_err << "unsucessful drop of " << buf << endl; + return NDBT_FAILED; + } + + NdbDictionary::Table table_shadow(*table); + table_shadow.setName(buf); + GETNDB(step)->getDictionary()->createTable(table_shadow); + if (GETNDB(step)->getDictionary()->getTable(buf)) + return NDBT_OK; + + g_err << "unsucessful create of " << buf << endl; + return NDBT_FAILED; +} + +int runCreateDropEventOperation(NDBT_Context* ctx, NDBT_Step* step) +{ + int loops = ctx->getNumLoops(); + int records = ctx->getNumRecords(); + HugoTransactions hugoTrans(*ctx->getTab()); + EventOperationStats stats; + + Ndb *pNdb=GETNDB(step); + const NdbDictionary::Table& tab= *ctx->getTab(); + NdbEventOperation *pOp; + char eventName[1024]; + sprintf(eventName,"%s_EVENT",tab.getName()); + int noEventColumnName = tab.getNoOfColumns(); + + for (int i= 0; i < loops; i++) + { +#if 1 + if (hugoTrans.eventOperation(GETNDB(step), (void*)&stats, 0) != 0){ + return NDBT_FAILED; + } +#else + g_info << "create EventOperation\n"; + pOp = pNdb->createEventOperation(eventName, 100); + if ( pOp == NULL ) { + g_err << "Event operation creation failed\n"; + return NDBT_FAILED; + } + + g_info << "dropping event operation" << endl; + int res = pNdb->dropEventOperation(pOp); + if (res != 0) { + g_err << "operation execution failed\n"; + return NDBT_FAILED; + } +#endif + } + + return NDBT_OK; +} + int theThreadIdCounter = 0; int runEventOperation(NDBT_Context* ctx, NDBT_Step* step) @@ -43,7 +106,7 @@ int runEventOperation(NDBT_Context* ctx, NDBT_Step* step) EventOperationStats stats; - g_info << "***** Id " << tId << endl; + g_info << "***** start Id " << tId << endl; // sleep(tId); @@ -62,12 +125,13 @@ int runEventOperation(NDBT_Context* ctx, NDBT_Step* step) ret = NDBT_FAILED; if (ret == NDBT_FAILED) { - ndbout << "n_inserts = " << stats.n_inserts << endl; - ndbout << "n_deletes = " << stats.n_deletes << endl; - ndbout << "n_updates = " << stats.n_updates << endl; - ndbout << "n_consecutive = " << stats.n_consecutive << endl; - ndbout << "n_duplicates = " << stats.n_duplicates << endl; - ndbout << "n_inconsistent_gcis = " << stats.n_inconsistent_gcis << endl; + g_info << "***** end Id " << tId << endl; + ndbout_c("n_inserts = %d (%d)", stats.n_inserts, records); + ndbout_c("n_deletes = %d (%d)", stats.n_deletes, records); + ndbout_c("n_updates = %d (%d)", stats.n_updates, records); + ndbout_c("n_consecutive = %d (%d)", stats.n_consecutive, 3); + ndbout_c("n_duplicates = %d (%d)", stats.n_duplicates, 0); + ndbout_c("n_inconsistent_gcis = %d (%d)", stats.n_inconsistent_gcis, 0); } return ret; @@ -94,6 +158,36 @@ int runEventLoad(NDBT_Context* ctx, NDBT_Step* step) return NDBT_OK; } +int runEventMixedLoad(NDBT_Context* ctx, NDBT_Step* step) +{ + int loops = ctx->getNumLoops(); + int records = ctx->getNumRecords(); + HugoTransactions hugoTrans(*ctx->getTab()); + + sleep(5); + + if (hugoTrans.loadTable(GETNDB(step), 3*records, 1, true, 1) != 0){ + return NDBT_FAILED; + } + if (hugoTrans.pkDelRecords(GETNDB(step), 3*records, 1, true, 1) != 0){ + return NDBT_FAILED; + } + if (hugoTrans.loadTable(GETNDB(step), records, 1, true, 1) != 0){ + return NDBT_FAILED; + } + if (hugoTrans.pkUpdateRecords(GETNDB(step), records, 1, 1) != 0){ + return NDBT_FAILED; + } + if (hugoTrans.pkUpdateRecords(GETNDB(step), records, 1, 1) != 0){ + return NDBT_FAILED; + } + if (hugoTrans.pkUpdateRecords(GETNDB(step), records, 1, 1) != 0){ + return NDBT_FAILED; + } + + return NDBT_OK; +} + int runDropEvent(NDBT_Context* ctx, NDBT_Step* step) { HugoTransactions hugoTrans(*ctx->getTab()); @@ -105,6 +199,246 @@ int runDropEvent(NDBT_Context* ctx, NDBT_Step* step) return NDBT_OK; } +int runVerify(NDBT_Context* ctx, NDBT_Step* step) +{ + int records = ctx->getNumRecords(); + const NdbDictionary::Table * table= ctx->getTab(); + char buf[1024]; + + sprintf(buf, "%s_SHADOW", table->getName()); + + HugoTransactions hugoTrans(*table); + if (hugoTrans.compare(GETNDB(step), buf, 0)) + { + return NDBT_FAILED; + } + + return NDBT_OK; +} + +int runEventApplier(NDBT_Context* ctx, NDBT_Step* step) +{ + DBUG_ENTER("runEventApplier"); + + int records = ctx->getNumRecords(); + int loops = ctx->getNumLoops(); + const NdbDictionary::Table * table= ctx->getTab(); + char buf[1024]; + + sprintf(buf, "%s_SHADOW", table->getName()); + const NdbDictionary::Table * table_shadow; + if ((table_shadow = GETNDB(step)->getDictionary()->getTable(buf)) == 0) + { + g_err << "Unable to get table " << buf << endl; + DBUG_RETURN(NDBT_FAILED); + } + + sprintf(buf, "%s_EVENT", table->getName()); + NdbEventOperation *pOp; + pOp = GETNDB(step)->createEventOperation(buf, 10*records); + if ( pOp == NULL ) { + g_err << "Event operation creation failed on %s" << buf << endl; + DBUG_RETURN(NDBT_FAILED); + } + + int i; + int n_columns= table->getNoOfColumns(); + NdbRecAttr* recAttr[1024]; + NdbRecAttr* recAttrPre[1024]; + for (i = 0; i < n_columns; i++) { + recAttr[i] = pOp->getValue(table->getColumn(i)->getName()); + recAttrPre[i] = pOp->getPreValue(table->getColumn(i)->getName()); + } + + if (pOp->execute()) { // This starts changes to "start flowing" + g_err << "execute operation execution failed: \n"; + g_err << pOp->getNdbError().code << " " + << pOp->getNdbError().message << endl; + DBUG_RETURN(NDBT_FAILED); + } + + int r= 0; + int res; + while (r < 10*records){ + //printf("now waiting for event...\n"); + res= GETNDB(step)->pollEvents(1000); // wait for event or 1000 ms + if (res <= 0) + { + ndbout_c("********************"); + continue; + } + + //printf("got data! %d\n", r); + int overrun= 0; + while (pOp->next(&overrun) > 0) + { + if (overrun) + { + g_err << "buffer overrun\n"; + DBUG_RETURN(NDBT_FAILED); + } + r++; + + Uint32 gci= pOp->getGCI(); + + if (!pOp->isConsistent()) { + g_err << "A node failure has occured and events might be missing\n"; + DBUG_RETURN(NDBT_FAILED); + } + + int noRetries= 0; + do + { + NdbTransaction *trans= GETNDB(step)->startTransaction(); + if (trans == 0) + { + g_err << "startTransaction failed " + << GETNDB(step)->getNdbError().code << " " + << GETNDB(step)->getNdbError().message << endl; + DBUG_RETURN(NDBT_FAILED); + } + + NdbOperation *op= trans->getNdbOperation(table_shadow); + if (op == 0) + { + g_err << "getNdbOperation failed " + << trans->getNdbError().code << " " + << trans->getNdbError().message << endl; + DBUG_RETURN(NDBT_FAILED); + } + + switch (pOp->getEventType()) { + case NdbDictionary::Event::TE_INSERT: + if (op->insertTuple()) + { + g_err << "insertTuple " + << op->getNdbError().code << " " + << op->getNdbError().message << endl; + DBUG_RETURN(NDBT_FAILED); + } + break; + case NdbDictionary::Event::TE_DELETE: + if (op->deleteTuple()) + { + g_err << "deleteTuple " + << op->getNdbError().code << " " + << op->getNdbError().message << endl; + DBUG_RETURN(NDBT_FAILED); + } + break; + case NdbDictionary::Event::TE_UPDATE: + if (op->updateTuple()) + { + g_err << "updateTuple " + << op->getNdbError().code << " " + << op->getNdbError().message << endl; + DBUG_RETURN(NDBT_FAILED); + } + break; + default: + abort(); + } + + for (i= 0; i < n_columns; i++) + { + if (recAttr[i]->isNULL()) + { + if (table->getColumn(i)->getPrimaryKey()) + { + g_err << "internal error: primary key isNull()=" + << recAttr[i]->isNULL() << endl; + DBUG_RETURN(NDBT_FAILED); + } + switch (pOp->getEventType()) { + case NdbDictionary::Event::TE_INSERT: + if (recAttr[i]->isNULL() < 0) + { + g_err << "internal error: missing value for insert\n"; + DBUG_RETURN(NDBT_FAILED); + } + break; + case NdbDictionary::Event::TE_DELETE: + break; + case NdbDictionary::Event::TE_UPDATE: + break; + default: + abort(); + } + } + if (table->getColumn(i)->getPrimaryKey() && + op->equal(i,recAttr[i]->aRef())) + { + g_err << "equal " << i << " " + << op->getNdbError().code << " " + << op->getNdbError().message << endl; + DBUG_RETURN(NDBT_FAILED); + } + } + + switch (pOp->getEventType()) { + case NdbDictionary::Event::TE_INSERT: + for (i= 0; i < n_columns; i++) + { + if (!table->getColumn(i)->getPrimaryKey() && + op->setValue(i,recAttr[i]->isNULL() ? 0:recAttr[i]->aRef())) + { + g_err << "setValue(insert) " << i << " " + << op->getNdbError().code << " " + << op->getNdbError().message << endl; + DBUG_RETURN(NDBT_FAILED); + } + } + break; + case NdbDictionary::Event::TE_DELETE: + break; + case NdbDictionary::Event::TE_UPDATE: + for (i= 0; i < n_columns; i++) + { + if (!table->getColumn(i)->getPrimaryKey() && + recAttr[i]->isNULL() >= 0 && + op->setValue(i,recAttr[i]->isNULL() ? 0:recAttr[i]->aRef())) + { + g_err << "setValue(update) " << i << " " + << op->getNdbError().code << " " + << op->getNdbError().message << endl; + DBUG_RETURN(NDBT_FAILED); + } + } + break; + case NdbDictionary::Event::TE_ALL: + abort(); + } + if (trans->execute(Commit) == 0) + { + trans->close(); + // everything ok + break; + } + if (noRetries++ == 10 || + trans->getNdbError().status != NdbError::TemporaryError) + { + g_err << "execute " << r << " failed " + << trans->getNdbError().code << " " + << trans->getNdbError().message << endl; + trans->close(); + DBUG_RETURN(NDBT_FAILED); + } + trans->close(); + NdbSleep_MilliSleep(100); // sleep before retying + } while(1); + } + } + + if (GETNDB(step)->dropEventOperation(pOp)) { + g_err << "dropEventOperation execution failed " + << GETNDB(step)->getNdbError().code << " " + << GETNDB(step)->getNdbError().message << endl; + DBUG_RETURN(NDBT_FAILED); + } + + DBUG_RETURN(NDBT_OK); +} + // INITIALIZER(runInsert); // STEP(runPkRead); // VERIFIER(runVerifyInsert); @@ -116,25 +450,37 @@ TESTCASE("BasicEventOperation", "NOTE! No errors are allowed!" ){ INITIALIZER(runCreateEvent); STEP(runEventOperation); - STEP(runEventOperation); - STEP(runEventOperation); - STEP(runEventOperation); STEP(runEventLoad); FINALIZER(runDropEvent); } -NDBT_TESTSUITE_END(test_event); - -#if 0 -NDBT_TESTSUITE(test_event); +TESTCASE("CreateDropEventOperation", + "Verify that we can Create and Drop many times" + "NOTE! No errors are allowed!" ){ + INITIALIZER(runCreateEvent); + STEP(runCreateDropEventOperation); + FINALIZER(runDropEvent); +} TESTCASE("ParallellEventOperation", - "Verify that we can listen to Events in Parallell" + "Verify that we can listen to Events in parallell" "NOTE! No errors are allowed!" ){ - INITIALIZER(runCreateAllEvent); + INITIALIZER(runCreateEvent); + STEP(runEventOperation); STEP(runEventOperation); + STEP(runEventLoad); + FINALIZER(runDropEvent); +} +TESTCASE("EventOperationApplier", + "Verify that if we apply the data we get from event " + "operation is the same as the original table" + "NOTE! No errors are allowed!" ){ + INITIALIZER(runCreateEvent); + INITIALIZER(runCreateShadowTable); + STEP(runEventApplier); + STEP(runEventMixedLoad); FINALIZER(runDropEvent); + FINALIZER(runVerify); } NDBT_TESTSUITE_END(test_event); -#endif int main(int argc, const char** argv){ ndb_init(); diff --git a/ndb/test/ndbapi/test_event_multi_table.cpp b/ndb/test/ndbapi/test_event_multi_table.cpp new file mode 100644 index 00000000000..f16504029fa --- /dev/null +++ b/ndb/test/ndbapi/test_event_multi_table.cpp @@ -0,0 +1,487 @@ +/* Copyright (C) 2005 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 <ndb_opts.h> +#include <NDBT_Test.hpp> +#include <NDBT_ReturnCodes.h> +#include <HugoTransactions.hpp> +#include <UtilTransactions.hpp> +#include <TestNdbEventOperation.hpp> + +static void usage() +{ + ndb_std_print_version(); +} + +static int start_transaction(Ndb *ndb, Vector<HugoOperations*> &ops) +{ + if (ops[0]->startTransaction(ndb) != NDBT_OK) + return -1; + NdbTransaction * t= ops[0]->getTransaction(); + for (int i= ops.size()-1; i > 0; i--) + { + ops[i]->setTransaction(t); + } + return 0; +} + +static int close_transaction(Ndb *ndb, Vector<HugoOperations*> &ops) +{ + if (ops[0]->closeTransaction(ndb) != NDBT_OK) + return -1; + for (int i= ops.size()-1; i > 0; i--) + { + ops[i]->setTransaction(NULL); + } + return 0; +} + +static int execute_commit(Ndb *ndb, Vector<HugoOperations*> &ops) +{ + if (ops[0]->execute_Commit(ndb) != NDBT_OK) + return -1; + return 0; +} + +static int copy_events(Ndb *ndb, + Vector<NdbEventOperation *> &ops, + Vector<const NdbDictionary::Table *> &tabs, + Vector<Vector<NdbRecAttr *> > &values) +{ + DBUG_ENTER("copy_events"); + int r= 0; + while (1) + { + int res= ndb->pollEvents(1000); // wait for event or 1000 ms + DBUG_PRINT("info", ("pollEvents res=%d", r)); + if (res <= 0) + { + break; + } + for (unsigned i_ops= 0; i_ops < ops.size(); i_ops++) + { + NdbEventOperation *pOp= ops[i_ops]; + const NdbDictionary::Table *table= tabs[i_ops]; + Vector<NdbRecAttr *> &recAttr= values[i_ops]; + + int overrun= 0; + unsigned i; + unsigned n_columns= table->getNoOfColumns(); + while (pOp->next(&overrun) > 0) + { + if (overrun) + { + g_err << "buffer overrun\n"; + DBUG_RETURN(-1); + } + r++; + + Uint32 gci= pOp->getGCI(); + + if (!pOp->isConsistent()) { + g_err << "A node failure has occured and events might be missing\n"; + DBUG_RETURN(-1); + } + + int noRetries= 0; + do + { + NdbTransaction *trans= ndb->startTransaction(); + if (trans == 0) + { + g_err << "startTransaction failed " + << ndb->getNdbError().code << " " + << ndb->getNdbError().message << endl; + DBUG_RETURN(-1); + } + + NdbOperation *op= trans->getNdbOperation(table); + if (op == 0) + { + g_err << "getNdbOperation failed " + << trans->getNdbError().code << " " + << trans->getNdbError().message << endl; + DBUG_RETURN(-1); + } + + switch (pOp->getEventType()) { + case NdbDictionary::Event::TE_INSERT: + if (op->insertTuple()) + { + g_err << "insertTuple " + << op->getNdbError().code << " " + << op->getNdbError().message << endl; + DBUG_RETURN(-1); + } + break; + case NdbDictionary::Event::TE_DELETE: + if (op->deleteTuple()) + { + g_err << "deleteTuple " + << op->getNdbError().code << " " + << op->getNdbError().message << endl; + DBUG_RETURN(-1); + } + break; + case NdbDictionary::Event::TE_UPDATE: + if (op->updateTuple()) + { + g_err << "updateTuple " + << op->getNdbError().code << " " + << op->getNdbError().message << endl; + DBUG_RETURN(-1); + } + break; + default: + abort(); + } + + for (i= 0; i < n_columns; i++) + { + if (recAttr[i]->isNULL()) + { + if (table->getColumn(i)->getPrimaryKey()) + { + g_err << "internal error: primary key isNull()=" + << recAttr[i]->isNULL() << endl; + DBUG_RETURN(NDBT_FAILED); + } + switch (pOp->getEventType()) { + case NdbDictionary::Event::TE_INSERT: + if (recAttr[i]->isNULL() < 0) + { + g_err << "internal error: missing value for insert\n"; + DBUG_RETURN(NDBT_FAILED); + } + break; + case NdbDictionary::Event::TE_DELETE: + break; + case NdbDictionary::Event::TE_UPDATE: + break; + default: + abort(); + } + } + if (table->getColumn(i)->getPrimaryKey() && + op->equal(i,recAttr[i]->aRef())) + { + g_err << "equal " << i << " " + << op->getNdbError().code << " " + << op->getNdbError().message << endl; + DBUG_RETURN(NDBT_FAILED); + } + } + + switch (pOp->getEventType()) { + case NdbDictionary::Event::TE_INSERT: + for (i= 0; i < n_columns; i++) + { + if (!table->getColumn(i)->getPrimaryKey() && + op->setValue(i,recAttr[i]->isNULL() ? 0:recAttr[i]->aRef())) + { + g_err << "setValue(insert) " << i << " " + << op->getNdbError().code << " " + << op->getNdbError().message << endl; + DBUG_RETURN(-1); + } + } + break; + case NdbDictionary::Event::TE_DELETE: + break; + case NdbDictionary::Event::TE_UPDATE: + for (i= 0; i < n_columns; i++) + { + if (!table->getColumn(i)->getPrimaryKey() && + recAttr[i]->isNULL() >= 0 && + op->setValue(i,recAttr[i]->isNULL() ? 0:recAttr[i]->aRef())) + { + g_err << "setValue(update) " << i << " " + << op->getNdbError().code << " " + << op->getNdbError().message << endl; + DBUG_RETURN(NDBT_FAILED); + } + } + break; + case NdbDictionary::Event::TE_ALL: + abort(); + } + if (trans->execute(Commit) == 0) + { + trans->close(); + // everything ok + break; + } + if (noRetries++ == 10 || + trans->getNdbError().status != NdbError::TemporaryError) + { + g_err << "execute " << r << " failed " + << trans->getNdbError().code << " " + << trans->getNdbError().message << endl; + trans->close(); + DBUG_RETURN(-1); + } + trans->close(); + NdbSleep_MilliSleep(100); // sleep before retying + } while(1); + } + } + } + DBUG_RETURN(r); +} + +static int verify_copy(Ndb *ndb, + Vector<const NdbDictionary::Table *> &tabs1, + Vector<const NdbDictionary::Table *> &tabs2) +{ + for (unsigned i= 0; i < tabs1.size(); i++) + if (tabs1[i]) + { + HugoTransactions hugoTrans(*tabs1[i]); + if (hugoTrans.compare(ndb, tabs2[i]->getName(), 0)) + return -1; + } + return 0; +} + +NDB_STD_OPTS_VARS; + +static const char* _dbname = "TEST_DB"; +static struct my_option my_long_options[] = +{ + NDB_STD_OPTS(""), + { "database", 'd', "Name of database table is in", + (gptr*) &_dbname, (gptr*) &_dbname, 0, + GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} +}; + +int +main(int argc, char** argv) +{ + NDB_INIT(argv[0]); + const char *load_default_groups[]= { "mysql_cluster",0 }; + load_defaults("my",load_default_groups,&argc,&argv); + + int ho_error; +#ifndef DBUG_OFF + opt_debug= "d:t:F:L"; +#endif + if ((ho_error=handle_options(&argc, &argv, my_long_options, + ndb_std_get_one_option))) + return NDBT_ProgramExit(NDBT_WRONGARGS); + + DBUG_ENTER("main"); + Ndb_cluster_connection con(opt_connect_str); + if(con.connect(12, 5, 1)) + { + DBUG_RETURN(NDBT_ProgramExit(NDBT_FAILED)); + } + + + Ndb ndb(&con,_dbname); + ndb.init(); + while (ndb.waitUntilReady() != 0); + + NdbDictionary::Dictionary * dict = ndb.getDictionary(); + int no_error= 1; + int i; + + // create all tables + Vector<const NdbDictionary::Table*> pTabs; + for (i= 0; no_error && argc; argc--, i++) + { + dict->dropTable(argv[i]); + NDBT_Tables::createTable(&ndb, argv[i]); + const NdbDictionary::Table *pTab= dict->getTable(argv[i]); + if (pTab == 0) + { + ndbout << "Failed to create table" << endl; + ndbout << dict->getNdbError() << endl; + no_error= 0; + break; + } + pTabs.push_back(pTab); + } + pTabs.push_back(NULL); + + // create an event for each table + for (i= 0; no_error && pTabs[i]; i++) + { + HugoTransactions ht(*pTabs[i]); + if (ht.createEvent(&ndb)){ + no_error= 0; + break; + } + } + + // create an event operation for each event + Vector<NdbEventOperation *> pOps; + for (i= 0; no_error && pTabs[i]; i++) + { + char buf[1024]; + sprintf(buf, "%s_EVENT", pTabs[i]->getName()); + NdbEventOperation *pOp= ndb.createEventOperation(buf, 1000); + if ( pOp == NULL ) + { + no_error= 0; + break; + } + pOps.push_back(pOp); + } + + // get storage for each event operation + Vector<Vector<NdbRecAttr*> > values; + Vector<Vector<NdbRecAttr*> > pre_values; + for (i= 0; no_error && pTabs[i]; i++) + { + int n_columns= pTabs[i]->getNoOfColumns(); + Vector<NdbRecAttr*> tmp_a; + Vector<NdbRecAttr*> tmp_b; + for (int j = 0; j < n_columns; j++) { + tmp_a.push_back(pOps[i]->getValue(pTabs[i]->getColumn(j)->getName())); + tmp_b.push_back(pOps[i]->getPreValue(pTabs[i]->getColumn(j)->getName())); + } + values.push_back(tmp_a); + pre_values.push_back(tmp_b); + } + + // start receiving events + for (i= 0; no_error && pTabs[i]; i++) + { + if ( pOps[i]->execute() ) + { + no_error= 0; + break; + } + } + + // create a "shadow" table for each table + Vector<const NdbDictionary::Table*> pShadowTabs; + for (i= 0; no_error && pTabs[i]; i++) + { + char buf[1024]; + sprintf(buf, "%s_SHADOW", pTabs[i]->getName()); + + dict->dropTable(buf); + if (dict->getTable(buf)) + { + no_error= 0; + break; + } + + NdbDictionary::Table table_shadow(*pTabs[i]); + table_shadow.setName(buf); + dict->createTable(table_shadow); + pShadowTabs.push_back(dict->getTable(buf)); + if (!pShadowTabs[i]) + { + no_error= 0; + break; + } + } + + // create a hugo operation per table + Vector<HugoOperations *> hugo_ops; + for (i= 0; no_error && pTabs[i]; i++) + { + hugo_ops.push_back(new HugoOperations(*pTabs[i])); + } + + sleep(5); + + // insert 3 records per table + do { + if (start_transaction(&ndb, hugo_ops)) + { + no_error= 0; + break; + } + for (i= 0; no_error && pTabs[i]; i++) + { + hugo_ops[i]->pkInsertRecord(&ndb, 0, 3); + } + if (execute_commit(&ndb, hugo_ops)) + { + no_error= 0; + break; + } + if(close_transaction(&ndb, hugo_ops)) + { + no_error= 0; + break; + } + } while(0); + + // copy events and verify + do { + if (copy_events(&ndb, pOps, pShadowTabs, values) < 0) + { + no_error= 0; + break; + } + if (verify_copy(&ndb, pTabs, pShadowTabs)) + { + no_error= 0; + break; + } + } while (0); + + // update 2 records in first table + do { + if (start_transaction(&ndb, hugo_ops)) + { + no_error= 0; + break; + } + + hugo_ops[0]->pkUpdateRecord(&ndb, 2); + + if (execute_commit(&ndb, hugo_ops)) + { + no_error= 0; + break; + } + if(close_transaction(&ndb, hugo_ops)) + { + no_error= 0; + break; + } + } while(0); + + // copy events and verify + do { + if (copy_events(&ndb, pOps, pShadowTabs, values) < 0) + { + no_error= 0; + break; + } + if (verify_copy(&ndb, pTabs, pShadowTabs)) + { + no_error= 0; + break; + } + } while (0); + + if (no_error) + DBUG_RETURN(NDBT_ProgramExit(NDBT_OK)); + DBUG_RETURN(NDBT_ProgramExit(NDBT_FAILED)); +} + +template class Vector<HugoOperations *>; +template class Vector<NdbEventOperation *>; +template class Vector<NdbRecAttr*>; +template class Vector<Vector<NdbRecAttr*> >; diff --git a/ndb/test/run-test/16node-tests.txt b/ndb/test/run-test/16node-tests.txt new file mode 100644 index 00000000000..11ade56c28c --- /dev/null +++ b/ndb/test/run-test/16node-tests.txt @@ -0,0 +1,733 @@ +# 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 + +max-time: 500 +cmd: testTimeout +args: 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: 500 +cmd: testScan +args: -n ScanRead488O -l 10 T6 + +max-time: 1000 +cmd: testScan +args: -n ScanRead488_Mixed -l 10 T6 + +max-time: 500 +cmd: testScan +args: -n ScanRead488Timeout -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: 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 + +max-time: 500 +cmd: testScan +args: -n ScanParallelism + +# +# 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 FragmentTypeAllSmall 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: 150000 +cmd: testOperations +args: + +max-time: 15000 +cmd: testTransactions +args: + +max-time: 1500 +cmd: testRestartGci +args: T6 + +max-time: 600 +cmd: testBlobs +args: + +max-time: 5000 +cmd: testOIBasic +args: + +max-time: 2500 +cmd: testBitfield +args: + +max-time: 2500 +cmd: testPartitioning +args: + +max-time: 25000 +cmd: atrt-mysql-test-run +args: --force + +# +# 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: atrt-testBackup +args: -n BackupOne T1 T6 T3 I3 + +# +# +# SYSTEM RESTARTS +# +max-time: 1500 +cmd: testSystemRestart +args: -n SR3 T6 + +max-time: 1500 +cmd: testSystemRestart +args: -n SR4 T6 + +# +# NODE RESTARTS +# +max-time: 2500 +cmd: testNodeRestart +args: -n NoLoad T6 + +max-time: 2500 +cmd: testNodeRestart +args: -n MixedPkRead T6 T8 T13 + +max-time: 2500 +cmd: testNodeRestart +args: -l 1 -n MixedPkReadPkUpdate + +max-time: 2500 +cmd: testNodeRestart +args: -l 1 -n MixedReadUpdateScan + +max-time: 2500 +cmd: testNodeRestart +args: -n CommittedRead T1 + +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: 1500 +cmd: testSystemRestart +args: -l 1 -n SR6 T1 + +max-time: 1500 +cmd: testSystemRestart +args: -l 1 -n SR7 T1 + +max-time: 1500 +cmd: testSystemRestart +args: -l 1 -n SR8 T1 + +max-time: 1500 +cmd: testSystemRestart +args: -l 1 -n SR9 T1 + +# +max-time: 2500 +cmd: test_event +args: -n BasicEventOperation T1 T6 + +# +# +# 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 + +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 + +# OLD FLEX +max-time: 500 +cmd: flexBench +args: -c 25 -t 10 + +max-time: 500 +cmd: flexHammer +args: -r 5 -t 32 + diff --git a/ndb/test/run-test/Makefile.am b/ndb/test/run-test/Makefile.am index cf08542ae97..60d64a7697f 100644 --- a/ndb/test/run-test/Makefile.am +++ b/ndb/test/run-test/Makefile.am @@ -6,7 +6,7 @@ include $(top_srcdir)/ndb/config/type_util.mk.am include $(top_srcdir)/ndb/config/type_mgmapiclient.mk.am test_PROGRAMS = atrt -test_DATA=daily-basic-tests.txt daily-devel-tests.txt \ +test_DATA=daily-basic-tests.txt daily-devel-tests.txt 16node-tests.txt \ conf-daily-basic-ndbmaster.txt \ conf-daily-basic-shark.txt \ conf-daily-devel-ndbmaster.txt \ diff --git a/ndb/test/run-test/basic.txt b/ndb/test/run-test/basic.txt index a952320db08..ec9e21359e5 100644 --- a/ndb/test/run-test/basic.txt +++ b/ndb/test/run-test/basic.txt @@ -374,7 +374,7 @@ args: -n FragmentTypeSingle T1 max-time: 1500 cmd: testDict -args: -n FragmentTypeAll T1 T6 T7 T8 +args: -n FragmentTypeAllSmall T1 T6 T7 T8 max-time: 1500 cmd: testDict diff --git a/ndb/test/run-test/daily-basic-tests.txt b/ndb/test/run-test/daily-basic-tests.txt index fc04664564f..8b44594a9b5 100644 --- a/ndb/test/run-test/daily-basic-tests.txt +++ b/ndb/test/run-test/daily-basic-tests.txt @@ -75,7 +75,7 @@ max-time: 500 cmd: testBasic args: -n PkInsert -max-time: 600 +max-time: 660 cmd: testBasic args: -n UpdateAndRead @@ -207,34 +207,9 @@ 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 +args: T1 # SCAN TESTS # @@ -434,14 +409,9 @@ max-time: 500 cmd: testScan args: -l 100 -n Scan-bug8262 T7 -# OLD FLEX max-time: 500 -cmd: flexBench -args: -c 25 -t 10 - -max-time: 500 -cmd: flexHammer -args: -r 5 -t 32 +cmd: testScan +args: -n ScanParallelism # # DICT TESTS @@ -475,7 +445,7 @@ args: -n FragmentTypeSingle T1 max-time: 1500 cmd: testDict -args: -n FragmentTypeAll T1 T6 T7 T8 +args: -n FragmentTypeAllSmall T1 T6 T7 T8 max-time: 1500 cmd: testDict @@ -554,6 +524,10 @@ max-time: 500 cmd: testNdbApi args: -n Bug_11133 T1 +max-time: 500 +cmd: testNdbApi +args: -n Scan_4006 T1 + #max-time: 500 #cmd: testInterpreter #args: T1 @@ -562,7 +536,7 @@ max-time: 150000 cmd: testOperations args: -max-time: 150000 +max-time: 15000 cmd: testTransactions args: @@ -574,10 +548,18 @@ max-time: 600 cmd: testBlobs args: -max-time: 2500 +max-time: 5000 cmd: testOIBasic args: +max-time: 2500 +cmd: testBitfield +args: + +max-time: 2500 +cmd: testPartitioning +args: + # # # SYSTEM RESTARTS @@ -625,3 +607,42 @@ args: -n SR_UNDO T7 max-time: 1500 cmd: testSystemRestart args: -n SR_UNDO T8 + +# OLD FLEX +max-time: 500 +cmd: flexBench +args: -c 25 -t 10 + +max-time: 500 +cmd: flexHammer +args: -r 5 -t 32 + +max-time: 300 +cmd: DbCreate +args: + +max-time: 180 +cmd: DbAsyncGenerator +args: -time 60 -p 1 +type: bench + +max-time: 180 +cmd: DbAsyncGenerator +args: -time 60 -p 25 +type: bench + +max-time: 180 +cmd: DbAsyncGenerator +args: -time 60 -p 100 +type: bench + +max-time: 180 +cmd: DbAsyncGenerator +args: -time 60 -p 200 +type: bench + +max-time: 180 +cmd: DbAsyncGenerator +args: -time 60 -p 1 -proc 25 +type: bench + diff --git a/ndb/test/run-test/daily-devel-tests.txt b/ndb/test/run-test/daily-devel-tests.txt index 9812ec2ceaa..20f54e031e5 100644 --- a/ndb/test/run-test/daily-devel-tests.txt +++ b/ndb/test/run-test/daily-devel-tests.txt @@ -206,34 +206,5 @@ args: -l 1 -n SR9 T1 # max-time: 2500 cmd: test_event -args: -n BasicEventOperation T1 T6 - -max-time: 300 -cmd: DbCreate -args: - -max-time: 180 -cmd: DbAsyncGenerator -args: -time 60 -p 1 -type: bench - -max-time: 180 -cmd: DbAsyncGenerator -args: -time 60 -p 25 -type: bench - -max-time: 180 -cmd: DbAsyncGenerator -args: -time 60 -p 100 -type: bench - -max-time: 180 -cmd: DbAsyncGenerator -args: -time 60 -p 200 -type: bench - -max-time: 180 -cmd: DbAsyncGenerator -args: -time 60 -p 1 -proc 25 -type: bench +args: -n EventOperationApplier diff --git a/ndb/test/src/HugoAsynchTransactions.cpp b/ndb/test/src/HugoAsynchTransactions.cpp index f75293f5a14..5d2eb451c0b 100644 --- a/ndb/test/src/HugoAsynchTransactions.cpp +++ b/ndb/test/src/HugoAsynchTransactions.cpp @@ -17,11 +17,12 @@ #include <NdbSleep.h> #include <HugoAsynchTransactions.hpp> -HugoAsynchTransactions::HugoAsynchTransactions(const NdbDictionary::Table& _tab): - HugoTransactions(_tab), - transactionsCompleted(0), - numTransactions(0), - transactions(NULL){ +HugoAsynchTransactions::HugoAsynchTransactions(const NdbDictionary::Table& _t) + : HugoTransactions(_t), + transactionsCompleted(0), + numTransactions(0), + transactions(NULL) +{ } HugoAsynchTransactions::~HugoAsynchTransactions(){ diff --git a/ndb/test/src/HugoCalculator.cpp b/ndb/test/src/HugoCalculator.cpp index 62c35c54a7a..8e01f6442bb 100644 --- a/ndb/test/src/HugoCalculator.cpp +++ b/ndb/test/src/HugoCalculator.cpp @@ -14,8 +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 <ndb_global.h> #include "HugoCalculator.hpp" #include <NDBT.hpp> +#include <Base64.hpp> + +static +Uint32 +myRand(Uint64 * seed) +{ + const Uint64 mul= 0x5deece66dull; + const Uint64 add= 0xb; + Uint64 loc_result = *seed * mul + add; + + * seed= loc_result; + return loc_result >> 1; +} + +static char base64_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789+/"; /* ************************************************************* * HugoCalculator @@ -40,7 +58,8 @@ HugoCalculator::HugoCalculator(const NdbDictionary::Table& tab) : m_tab(tab) { // The "number of updates" column for this table is found in the last column for (i=m_tab.getNoOfColumns()-1; i>=0; i--){ const NdbDictionary::Column* attr = m_tab.getColumn(i); - if (attr->getType() == NdbDictionary::Column::Unsigned){ + if (attr->getType() == NdbDictionary::Column::Unsigned && + !attr->getPrimaryKey()){ m_updatesCol = i; break; } @@ -51,29 +70,18 @@ HugoCalculator::HugoCalculator(const NdbDictionary::Table& tab) : m_tab(tab) { #endif // Check that idCol is not conflicting with updatesCol assert(m_idCol != m_updatesCol && m_idCol != -1 && m_updatesCol != -1); -}; +} Int32 HugoCalculator::calcValue(int record, int attrib, int updates) const { - const NdbDictionary::Column* attr = m_tab.getColumn(attrib); - // If this is the "id" column - if (attrib == m_idCol) - return record; - - // If this is the update column - if (attrib == m_updatesCol) - return updates; - - - Int32 val; - if (attr->getPrimaryKey()) - val = record + attrib; - else - val = record + attrib + updates; - return val; -}; + + Int32 i; + calcValue(record, attrib, updates, (char*)&i, sizeof(i)); + + return i; +} #if 0 HugoCalculator::U_Int32 calcValue(int record, int attrib, int updates) const; HugoCalculator::U_Int64 calcValue(int record, int attrib, int updates) const; @@ -81,49 +89,121 @@ HugoCalculator::Int64 calcValue(int record, int attrib, int updates) const; HugoCalculator::float calcValue(int record, int attrib, int updates) const; HugoCalculator::double calcValue(int record, int attrib, int updates) const; #endif + const char* HugoCalculator::calcValue(int record, int attrib, int updates, - char* buf) const { - const char a[26] = {"UAWBORCTDPEFQGNYHISJMKXLZ"}; + char* buf, + int len) const { + Uint64 seed; const NdbDictionary::Column* attr = m_tab.getColumn(attrib); - int val = calcValue(record, attrib, updates); - - int len; - if (attr->getPrimaryKey()){ - // Create a string where val is printed as chars in the beginning - // of the string, then fill with other chars - // The string length is set to the same size as the attribute - len = attr->getLength(); - BaseString::snprintf(buf, len, "%d", val); - for(int i=strlen(buf); i < len; i++) - buf[i] = a[((val^i)%25)]; - } else{ + Uint32 val; + do + { + if (attrib == m_idCol) + { + val= record; + memcpy(buf, &val, 4); + return buf; + } - // Fill buf with some pattern so that we can detect - // anomalies in the area that we don't fill with chars - int i; - for (i = 0; i<attr->getLength(); i++) - buf[i] = ((i+2) % 255); + // If this is the update column + if (attrib == m_updatesCol) + { + val= updates; + memcpy(buf, &val, 4); + return buf; + } + + if (attr->getPrimaryKey()) + { + seed = record + attrib; + } + else + { + seed = record + attrib + updates; + } + } while (0); + + val = myRand(&seed); + + if(attr->getNullable() && (((val >> 16) & 255) > 220)) + return NULL; + + int pos= 0; + switch(attr->getType()){ + case NdbDictionary::Column::Tinyint: + case NdbDictionary::Column::Tinyunsigned: + case NdbDictionary::Column::Smallint: + case NdbDictionary::Column::Smallunsigned: + case NdbDictionary::Column::Mediumint: + case NdbDictionary::Column::Mediumunsigned: + case NdbDictionary::Column::Int: + case NdbDictionary::Column::Unsigned: + case NdbDictionary::Column::Bigint: + case NdbDictionary::Column::Bigunsigned: + case NdbDictionary::Column::Float: + case NdbDictionary::Column::Double: + case NdbDictionary::Column::Olddecimal: + case NdbDictionary::Column::Olddecimalunsigned: + case NdbDictionary::Column::Decimal: + case NdbDictionary::Column::Decimalunsigned: + case NdbDictionary::Column::Binary: + case NdbDictionary::Column::Datetime: + case NdbDictionary::Column::Time: + case NdbDictionary::Column::Date: + case NdbDictionary::Column::Bit: + while (len > 4) + { + memcpy(buf+pos, &val, 4); + pos += 4; + len -= 4; + val= myRand(&seed); + } - // Calculate length of the string to create. We want the string - // length to be varied between max and min of this attribute. - - len = val % (attr->getLength() + 1); - // If len == 0 return NULL if this is a nullable attribute - if (len == 0){ - if(attr->getNullable() == true) - return NULL; - else - len++; + memcpy(buf+pos, &val, len); + if(attr->getType() == NdbDictionary::Column::Bit) + { + Uint32 bits= attr->getLength(); + Uint32 tmp = bits >> 5; + Uint32 size = bits & 31; + ((Uint32*)buf)[tmp] &= ((1 << size) - 1); } - for(i=0; i < len; i++) - buf[i] = a[((val^i)%25)]; - buf[len] = 0; + break; + case NdbDictionary::Column::Varbinary: + case NdbDictionary::Column::Varchar: + case NdbDictionary::Column::Text: + case NdbDictionary::Column::Char: + case NdbDictionary::Column::Longvarchar: + case NdbDictionary::Column::Longvarbinary: + { + char* ptr= (char*)&val; + while(len >= 4) + { + len -= 4; + buf[pos++] = base64_table[ptr[0] & 0x3f]; + buf[pos++] = base64_table[ptr[1] & 0x3f]; + buf[pos++] = base64_table[ptr[2] & 0x3f]; + buf[pos++] = base64_table[ptr[3] & 0x3f]; + val= myRand(&seed); + } + + for(; len; len--, pos++) + buf[pos] = base64_table[ptr[len] & 0x3f]; + + pos--; + break; } + case NdbDictionary::Column::Blob: + case NdbDictionary::Column::Undefined: + abort(); + break; + } + + return buf; -}; +} int HugoCalculator::verifyRowValues(NDBT_ResultRow* const pRow) const{ @@ -131,104 +211,48 @@ HugoCalculator::verifyRowValues(NDBT_ResultRow* const pRow) const{ id = pRow->attributeStore(m_idCol)->u_32_value(); updates = pRow->attributeStore(m_updatesCol)->u_32_value(); - + int result = 0; + // Check the values of each column for (int i = 0; i<m_tab.getNoOfColumns(); i++){ if (i != m_updatesCol && id != m_idCol) { - const NdbDictionary::Column* attr = m_tab.getColumn(i); - switch (attr->getType()){ - case NdbDictionary::Column::Char: - case NdbDictionary::Column::Varchar: - case NdbDictionary::Column::Binary: - case NdbDictionary::Column::Varbinary:{ - int result = 0; - char* buf = new char[attr->getLength()+1]; - const char* res = calcValue(id, i, updates, buf); - if (res == NULL){ - if (!pRow->attributeStore(i)->isNULL()){ - g_err << "|- NULL ERROR: expected a NULL but the column was not null" << endl; - g_err << "|- The row: \"" << (*pRow) << "\"" << endl; - result = -1; - } - } else{ - if (memcmp(res, pRow->attributeStore(i)->aRef(), pRow->attributeStore(i)->arraySize()) != 0){ - // if (memcmp(res, pRow->attributeStore(i)->aRef(), pRow->attributeStore(i)->getLength()) != 0){ - g_err << "arraySize(): " - << pRow->attributeStore(i)->arraySize() - << ", NdbDict::Column::getLength(): " << attr->getLength() - << endl; - const char* buf2 = pRow->attributeStore(i)->aRef(); - for (Uint32 j = 0; j < pRow->attributeStore(i)->arraySize(); j++) + Uint32 len = attr->getSizeInBytes(); + char buf[8000]; + const char* res = calcValue(id, i, updates, buf, len); + if (res == NULL){ + if (!pRow->attributeStore(i)->isNULL()){ + g_err << "|- NULL ERROR: expected a NULL but the column was not null" << endl; + g_err << "|- The row: \"" << (*pRow) << "\"" << endl; + result = -1; + } + } else{ + if (memcmp(res, pRow->attributeStore(i)->aRef(), len) != 0){ + g_err << "Column: " << attr->getName() << endl; + const char* buf2 = pRow->attributeStore(i)->aRef(); + for (Uint32 j = 0; j < len; j++) + { + g_err << j << ":" << hex << (Uint32)(Uint8)buf[j] << "[" << hex << (Uint32)(Uint8)buf2[j] << "]"; + if (buf[j] != buf2[j]) { - g_err << j << ":" << buf[j] << "[" << buf2[j] << "]"; - if (buf[j] != buf2[j]) - { - g_err << "==>Match failed!"; - } - g_err << endl; + g_err << "==>Match failed!"; } g_err << endl; - g_err << "|- Invalid data found in attribute " << i << ": \"" - << pRow->attributeStore(i)->aRef() - << "\" != \"" << res << "\"" << endl - << "Length of expected=" << (unsigned)strlen(res) << endl - << "Lenght of read=" - << (unsigned)strlen(pRow->attributeStore(i)->aRef()) << endl; - g_err << "|- The row: \"" << (* pRow) << "\"" << endl; - result = -1; } - } - delete []buf; - if (result != 0) - return result; - } - break; - case NdbDictionary::Column::Int: - case NdbDictionary::Column::Unsigned:{ - Int32 cval = calcValue(id, i, updates); - Int32 val = pRow->attributeStore(i)->int32_value(); - if (val != cval){ - g_err << "|- Invalid data found: \"" << val << "\" != \"" - << cval << "\"" << endl; - g_err << "|- The row: \"" << (* pRow) << "\"" << endl; - return -1; - } - break; - } - case NdbDictionary::Column::Bigint: - case NdbDictionary::Column::Bigunsigned:{ - Uint64 cval = calcValue(id, i, updates); - Uint64 val = pRow->attributeStore(i)->u_64_value(); - if (val != cval){ - g_err << "|- Invalid data found: \"" << val << "\" != \"" - << cval << "\"" - << endl; + g_err << endl; + g_err << "|- Invalid data found in attribute " << i << ": \"" + << pRow->attributeStore(i)->aRef() + << "\" != \"" << res << "\"" << endl + << "Length of expected=" << (unsigned)strlen(res) << endl + << "Lenght of read=" + << (unsigned)strlen(pRow->attributeStore(i)->aRef()) << endl; g_err << "|- The row: \"" << (* pRow) << "\"" << endl; - return -1; + result = -1; } } - break; - case NdbDictionary::Column::Float:{ - float cval = calcValue(id, i, updates); - float val = pRow->attributeStore(i)->float_value(); - if (val != cval){ - g_err << "|- Invalid data found: \"" << val << "\" != \"" - << cval << "\"" << endl; - g_err << "|- The row: \"" << (* pRow) << "\"" << endl; - return -1; - } - } - break; - case NdbDictionary::Column::Undefined: - default: - assert(false); - break; - } - } } - return 0; + return result; } int diff --git a/ndb/test/src/HugoOperations.cpp b/ndb/test/src/HugoOperations.cpp index 6b1a1ca395b..f2e54971766 100644 --- a/ndb/test/src/HugoOperations.cpp +++ b/ndb/test/src/HugoOperations.cpp @@ -31,6 +31,19 @@ int HugoOperations::startTransaction(Ndb* pNdb){ return NDBT_OK; } +int HugoOperations::setTransaction(NdbTransaction* new_trans){ + + if (pTrans != NULL){ + ndbout << "HugoOperations::startTransaction, pTrans != NULL" << endl; + return NDBT_FAILED; + } + pTrans = new_trans; + if (pTrans == NULL) { + return NDBT_FAILED; + } + return NDBT_OK; +} + void HugoOperations::setTransactionId(Uint64 id){ if (pTrans != NULL){ @@ -40,11 +53,7 @@ HugoOperations::setTransactionId(Uint64 id){ int HugoOperations::closeTransaction(Ndb* pNdb){ - if (pTrans != NULL){ - pNdb->closeTransaction(pTrans); - pTrans = NULL; - } - pTrans = NULL; + UtilTransactions::closeTransaction(pNdb); m_result_sets.clear(); m_executed_result_sets.clear(); @@ -63,8 +72,16 @@ int HugoOperations::pkReadRecord(Ndb* pNdb, int a; allocRows(numRecords); int check; + + NdbOperation* pOp = 0; + pIndexScanOp = 0; + for(int r=0; r < numRecords; r++){ - NdbOperation* pOp = pTrans->getNdbOperation(tab.getName()); + + if(pOp == 0) + { + pOp = getOperation(pTrans, NdbOperation::ReadRequest); + } if (pOp == NULL) { ERR(pTrans->getNdbError()); return NDBT_FAILED; @@ -73,13 +90,16 @@ int HugoOperations::pkReadRecord(Ndb* pNdb, rand_lock_mode: switch(lm){ case NdbOperation::LM_Read: - check = pOp->readTuple(); - break; case NdbOperation::LM_Exclusive: - check = pOp->readTupleExclusive(); - break; case NdbOperation::LM_CommittedRead: - check = pOp->dirtyRead(); + if(idx && idx->getType() == NdbDictionary::Index::OrderedIndex && + pIndexScanOp == 0) + { + pIndexScanOp = ((NdbIndexScanOperation*)pOp); + check = pIndexScanOp->readTuples(lm); + } + else + check = pOp->readTuple(lm); break; default: lm = (NdbOperation::LockMode)((rand() >> 16) & 3); @@ -100,15 +120,22 @@ rand_lock_mode: } } } + + if(pIndexScanOp) + pIndexScanOp->end_of_bound(r); - // Define attributes to read - for(a = 0; a<tab.getNoOfColumns(); a++){ - if((rows[r]->attributeStore(a) = - pOp->getValue(tab.getColumn(a)->getName())) == 0) { - ERR(pTrans->getNdbError()); - return NDBT_FAILED; - } - } + if(r == 0 || pIndexScanOp == 0) + { + // Define attributes to read + for(a = 0; a<tab.getNoOfColumns(); a++){ + if((rows[r]->attributeStore(a) = + pOp->getValue(tab.getColumn(a)->getName())) == 0) { + ERR(pTrans->getNdbError()); + return NDBT_FAILED; + } + } + } + pOp = pIndexScanOp; } return NDBT_OK; } @@ -121,7 +148,7 @@ int HugoOperations::pkUpdateRecord(Ndb* pNdb, allocRows(numRecords); int check; for(int r=0; r < numRecords; r++){ - NdbOperation* pOp = pTrans->getNdbOperation(tab.getName()); + NdbOperation* pOp = getOperation(pTrans, NdbOperation::UpdateRequest); if (pOp == NULL) { ERR(pTrans->getNdbError()); return NDBT_FAILED; @@ -133,26 +160,37 @@ int HugoOperations::pkUpdateRecord(Ndb* pNdb, return NDBT_FAILED; } - // Define primary keys - for(a = 0; a<tab.getNoOfColumns(); a++){ - if (tab.getColumn(a)->getPrimaryKey() == true){ - if(equalForAttr(pOp, a, r+recordNo) != 0){ - ERR(pTrans->getNdbError()); - return NDBT_FAILED; - } + if(setValues(pOp, r+recordNo, updatesValue) != NDBT_OK) + { + return NDBT_FAILED; + } + } + return NDBT_OK; +} + +int +HugoOperations::setValues(NdbOperation* pOp, int rowId, int updateId) +{ + // Define primary keys + int a; + for(a = 0; a<tab.getNoOfColumns(); a++){ + if (tab.getColumn(a)->getPrimaryKey() == true){ + if(equalForAttr(pOp, a, rowId) != 0){ + ERR(pTrans->getNdbError()); + return NDBT_FAILED; } } - - // Define attributes to update - for(a = 0; a<tab.getNoOfColumns(); a++){ - if (tab.getColumn(a)->getPrimaryKey() == false){ - if(setValueForAttr(pOp, a, recordNo+r, updatesValue ) != 0){ - ERR(pTrans->getNdbError()); - return NDBT_FAILED; - } + } + + for(a = 0; a<tab.getNoOfColumns(); a++){ + if (tab.getColumn(a)->getPrimaryKey() == false){ + if(setValueForAttr(pOp, a, rowId, updateId ) != 0){ + ERR(pTrans->getNdbError()); + return NDBT_FAILED; } - } + } } + return NDBT_OK; } @@ -163,7 +201,7 @@ int HugoOperations::pkInsertRecord(Ndb* pNdb, int a, check; for(int r=0; r < numRecords; r++){ - NdbOperation* pOp = pTrans->getNdbOperation(tab.getName()); + NdbOperation* pOp = getOperation(pTrans, NdbOperation::InsertRequest); if (pOp == NULL) { ERR(pTrans->getNdbError()); return NDBT_FAILED; @@ -175,25 +213,10 @@ int HugoOperations::pkInsertRecord(Ndb* pNdb, return NDBT_FAILED; } - // Define primary keys - for(a = 0; a<tab.getNoOfColumns(); a++){ - if (tab.getColumn(a)->getPrimaryKey() == true){ - if(equalForAttr(pOp, a, r+recordNo) != 0){ - ERR(pTrans->getNdbError()); - return NDBT_FAILED; - } - } + if(setValues(pOp, r+recordNo, updatesValue) != NDBT_OK) + { + return NDBT_FAILED; } - - // Define attributes to update - for(a = 0; a<tab.getNoOfColumns(); a++){ - if (tab.getColumn(a)->getPrimaryKey() == false){ - if(setValueForAttr(pOp, a, recordNo+r, updatesValue ) != 0){ - ERR(pTrans->getNdbError()); - return NDBT_FAILED; - } - } - } } return NDBT_OK; } @@ -240,9 +263,9 @@ int HugoOperations::pkWriteRecord(Ndb* pNdb, return NDBT_OK; } -int HugoOperations::pkDeleteRecord(Ndb* pNdb, - int recordNo, - int numRecords){ +int HugoOperations::pkWritePartialRecord(Ndb* pNdb, + int recordNo, + int numRecords){ int a, check; for(int r=0; r < numRecords; r++){ @@ -252,7 +275,7 @@ int HugoOperations::pkDeleteRecord(Ndb* pNdb, return NDBT_FAILED; } - check = pOp->deleteTuple(); + check = pOp->writeTuple(); if( check == -1 ) { ERR(pTrans->getNdbError()); return NDBT_FAILED; @@ -270,65 +293,37 @@ int HugoOperations::pkDeleteRecord(Ndb* pNdb, } return NDBT_OK; } -#if 0 -NdbResultSet* -HugoOperations::scanReadRecords(Ndb* pNdb, ScanLock lock){ - - NDBT_ResultRow * m_tmpRow = new NDBT_ResultRow(tab); - - NdbScanOperation* pOp = pTrans->getNdbScanOperation(tab.getName()); - if (pOp == NULL) { - ERR(pTrans->getNdbError()); - return 0; - } - - int check = 0; - NdbResultSet * rs = 0; - switch(lock){ - case SL_ReadHold: - rs = pOp->readTuples(NdbScanOperation::LM_Read, 1, 1); - break; - case SL_Exclusive: - rs = pOp->readTuples(NdbScanOperation::LM_Exclusive, 1, 1); - break; - case SL_Read: - default: - rs = pOp->readTuples(NdbScanOperation::LM_Dirty, 1, 1); - } - - if( rs == 0) { - ERR(pTrans->getNdbError()); - return 0; - } - - check = pOp->interpret_exit_ok(); - if( check == -1 ) { - ERR(pTrans->getNdbError()); - return 0; - } +int HugoOperations::pkDeleteRecord(Ndb* pNdb, + int recordNo, + int numRecords){ - // Define attributes to read - for(int a = 0; a<tab.getNoOfColumns(); a++){ - if((m_tmpRow->attributeStore(a) = - pOp->getValue(tab.getColumn(a)->getName())) == 0) { + int a, check; + for(int r=0; r < numRecords; r++){ + NdbOperation* pOp = getOperation(pTrans, NdbOperation::DeleteRequest); + if (pOp == NULL) { ERR(pTrans->getNdbError()); - return 0; + return NDBT_FAILED; + } + + check = pOp->deleteTuple(); + if( check == -1 ) { + ERR(pTrans->getNdbError()); + return NDBT_FAILED; + } + + // Define primary keys + for(a = 0; a<tab.getNoOfColumns(); a++){ + if (tab.getColumn(a)->getPrimaryKey() == true){ + if(equalForAttr(pOp, a, r+recordNo) != 0){ + ERR(pTrans->getNdbError()); + return NDBT_FAILED; + } + } } - } - return rs; -} - -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){ @@ -353,7 +348,7 @@ int HugoOperations::execute_Commit(Ndb* pNdb, 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; + NdbScanOperation* rs = m_result_sets[i].m_result_set; int res = rs->nextResult(); switch(res){ case 1: @@ -402,7 +397,7 @@ int HugoOperations::execute_NoCommit(Ndb* pNdb, AbortOption eao){ 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; + NdbScanOperation* rs = m_result_sets[i].m_result_set; int res = rs->nextResult(); switch(res){ case 1: @@ -441,21 +436,29 @@ int HugoOperations::execute_Rollback(Ndb* pNdb){ } void -HugoOperations_async_callback(int res, NdbConnection* pCon, void* ho) +HugoOperations_async_callback(int res, NdbTransaction* pCon, void* ho) { ((HugoOperations*)ho)->callback(res, pCon); } void -HugoOperations::callback(int res, NdbConnection* pCon) +HugoOperations::callback(int res, NdbTransaction* pCon) { assert(pCon == pTrans); m_async_reply= 1; - m_async_return= res; + if(res) + { + m_async_return = pCon->getNdbError().code; + } + else + { + m_async_return = 0; + } } int -HugoOperations::execute_async(Ndb* pNdb, ExecType et, AbortOption eao){ +HugoOperations::execute_async(Ndb* pNdb, NdbTransaction::ExecType et, + NdbTransaction::AbortOption eao){ m_async_reply= 0; pTrans->executeAsynchPrepare(et, @@ -475,16 +478,18 @@ HugoOperations::wait_async(Ndb* pNdb, int timeout) if(m_async_reply) { + if(m_async_return) + ndbout << "ERROR: " << pNdb->getNdbError(m_async_return) << endl; return m_async_return; } ndbout_c("wait returned nothing..."); return -1; } -HugoOperations::HugoOperations(const NdbDictionary::Table& _tab): - UtilTransactions(_tab), - calc(_tab), - pTrans(NULL) +HugoOperations::HugoOperations(const NdbDictionary::Table& _tab, + const NdbDictionary::Index* idx): + UtilTransactions(_tab, idx), + calc(_tab) { } @@ -501,101 +506,32 @@ HugoOperations::~HugoOperations(){ int HugoOperations::equalForAttr(NdbOperation* pOp, int attrId, int rowId){ - int check = 0; + int check = -1; const NdbDictionary::Column* attr = tab.getColumn(attrId); if (attr->getPrimaryKey() == false){ g_info << "Can't call equalForAttr on non PK attribute" << endl; return NDBT_FAILED; } - switch (attr->getType()){ - case NdbDictionary::Column::Char: - case NdbDictionary::Column::Varchar: - case NdbDictionary::Column::Binary: - case NdbDictionary::Column::Varbinary:{ - char buf[8000]; - memset(buf, 0, sizeof(buf)); - check = pOp->equal( attr->getName(), calc.calcValue(rowId, attrId, 0, buf)); - break; - } - case NdbDictionary::Column::Int: - check = pOp->equal( attr->getName(), (Int32)calc.calcValue(rowId, attrId, 0)); - break; - case NdbDictionary::Column::Unsigned: - check = pOp->equal( attr->getName(), (Uint32)calc.calcValue(rowId, attrId, 0)); - break; - case NdbDictionary::Column::Bigint: - check = pOp->equal( attr->getName(), (Int64)calc.calcValue(rowId, attrId, 0)); - break; - case NdbDictionary::Column::Bigunsigned: - check = pOp->equal( attr->getName(), (Uint64)calc.calcValue(rowId, attrId, 0)); - break; - case NdbDictionary::Column::Float: - g_info << "Float not allowed as PK value" << endl; - check = -1; - break; - - default: - g_info << "default" << endl; - check = -1; - break; - } - return check; + int len = attr->getSizeInBytes(); + char buf[8000]; + memset(buf, 0, sizeof(buf)); + return pOp->equal( attr->getName(), + calc.calcValue(rowId, attrId, 0, buf, len)); } int HugoOperations::setValueForAttr(NdbOperation* pOp, int attrId, int rowId, int updateId){ - int check = 0; + int check = -1; const NdbDictionary::Column* attr = tab.getColumn(attrId); - - if (attr->getTupleKey()){ - // Don't set values for TupleId PKs - return check; - } - switch (attr->getType()){ - case NdbDictionary::Column::Char: - case NdbDictionary::Column::Varchar: - case NdbDictionary::Column::Binary: - case NdbDictionary::Column::Varbinary:{ - char buf[8000]; - check = pOp->setValue( attr->getName(), - calc.calcValue(rowId, attrId, updateId, buf)); - break; - } - case NdbDictionary::Column::Int:{ - Int32 val = calc.calcValue(rowId, attrId, updateId); - check = pOp->setValue( attr->getName(), val); - } - break; - case NdbDictionary::Column::Bigint:{ - Int64 val = calc.calcValue(rowId, attrId, updateId); - check = pOp->setValue( attr->getName(), - val); - } - break; - case NdbDictionary::Column::Unsigned:{ - Uint32 val = calc.calcValue(rowId, attrId, updateId); - check = pOp->setValue( attr->getName(), val); - } - break; - case NdbDictionary::Column::Bigunsigned:{ - Uint64 val = calc.calcValue(rowId, attrId, updateId); - check = pOp->setValue( attr->getName(), - val); - } - break; - case NdbDictionary::Column::Float: - check = pOp->setValue( attr->getName(), - (float)calc.calcValue(rowId, attrId, updateId)); - break; - default: - check = -1; - break; - } - return check; + int len = attr->getSizeInBytes(); + char buf[8000]; + memset(buf, 0, sizeof(buf)); + return pOp->setValue( attr->getName(), + calc.calcValue(rowId, attrId, updateId, buf, len)); } int @@ -611,7 +547,7 @@ HugoOperations::verifyUpdatesValue(int updatesValue, int _numRows){ result = NDBT_FAILED; continue; } - + if(calc.getUpdatesValue(rows[i]) != updatesValue){ result = NDBT_FAILED; g_err << "Invalid updates value for row " << i << endl @@ -621,7 +557,7 @@ HugoOperations::verifyUpdatesValue(int updatesValue, int _numRows){ continue; } } - + if(_numRows == 0){ g_err << "No rows -> Invalid updates value" << endl; return NDBT_FAILED; @@ -631,14 +567,12 @@ HugoOperations::verifyUpdatesValue(int updatesValue, int _numRows){ } void HugoOperations::allocRows(int _numRows){ - deallocRows(); - if(_numRows <= 0){ g_info << "Illegal value for num rows : " << _numRows << endl; abort(); } - for(int b=0; b<_numRows; b++){ + for(int b=rows.size(); b<_numRows; b++){ rows.push_back(new NDBT_ResultRow(tab)); } } @@ -694,7 +628,7 @@ int HugoOperations::compareRecordToCopy(int numRecords ){ void HugoOperations::refresh() { - NdbConnection* t = getTransaction(); + NdbTransaction * t = getTransaction(); if(t) t->refresh(); } @@ -799,12 +733,10 @@ HugoOperations::scanReadRecords(Ndb* pNdb, NdbScanOperation::LockMode lm, if(!pOp) return -1; - NdbResultSet * rs = pOp->readTuples(lm, 1, 1); - - if(!rs){ + if(pOp->readTuples(lm, 0, 1)){ return -1; } - + for(int a = 0; a<tab.getNoOfColumns(); a++){ if((rows[0]->attributeStore(a) = pOp->getValue(tab.getColumn(a)->getName())) == 0) { @@ -812,8 +744,8 @@ HugoOperations::scanReadRecords(Ndb* pNdb, NdbScanOperation::LockMode lm, return NDBT_FAILED; } } - - RsPair p = {rs, records}; + + RsPair p = {pOp, records}; m_result_sets.push_back(p); return 0; diff --git a/ndb/test/src/HugoTransactions.cpp b/ndb/test/src/HugoTransactions.cpp index 5d5b2fa99df..3260b921985 100644 --- a/ndb/test/src/HugoTransactions.cpp +++ b/ndb/test/src/HugoTransactions.cpp @@ -18,8 +18,9 @@ #include <NdbSleep.h> -HugoTransactions::HugoTransactions(const NdbDictionary::Table& _tab): - HugoOperations(_tab), +HugoTransactions::HugoTransactions(const NdbDictionary::Table& _tab, + const NdbDictionary::Index* idx): + HugoOperations(_tab, idx), row(_tab){ m_defaultScanUpdateMethod = 3; @@ -34,7 +35,8 @@ HugoTransactions::scanReadRecords(Ndb* pNdb, int records, int abortPercent, int parallelism, - NdbOperation::LockMode lm) + NdbOperation::LockMode lm, + int scan_flags) { int retryAttempt = 0; @@ -64,17 +66,14 @@ HugoTransactions::scanReadRecords(Ndb* pNdb, return NDBT_FAILED; } - pOp = pTrans->getNdbScanOperation(tab.getName()); + pOp = getScanOperation(pTrans); if (pOp == NULL) { ERR(pTrans->getNdbError()); closeTransaction(pNdb); return NDBT_FAILED; } - NdbResultSet * rs; - rs = pOp ->readTuples(lm); - - if( rs == 0 ) { + if( pOp ->readTuples(lm, scan_flags, parallelism) ) { ERR(pTrans->getNdbError()); closeTransaction(pNdb); return NDBT_FAILED; @@ -123,7 +122,7 @@ HugoTransactions::scanReadRecords(Ndb* pNdb, int eof; int rows = 0; - while((eof = rs->nextResult(true)) == 0){ + while((eof = pOp->nextResult(true)) == 0){ rows++; if (calc.verifyRowValues(&row) != 0){ closeTransaction(pNdb); @@ -133,7 +132,7 @@ HugoTransactions::scanReadRecords(Ndb* pNdb, if (abortCount == rows && abortTrans == true){ ndbout << "Scan is aborted" << endl; g_info << "Scan is aborted" << endl; - rs->close(); + pOp->close(); if( check == -1 ) { ERR(pTrans->getNdbError()); closeTransaction(pNdb); @@ -189,7 +188,7 @@ HugoTransactions::scanReadRecords(Ndb* pNdb, int abortPercent, int parallelism, NdbOperation::LockMode lm, - bool sorted) + int scan_flags) { int retryAttempt = 0; @@ -226,10 +225,7 @@ HugoTransactions::scanReadRecords(Ndb* pNdb, return NDBT_FAILED; } - NdbResultSet * rs; - rs = pOp ->readTuples(lm, 0, parallelism, sorted); - - if( rs == 0 ) { + if( pOp ->readTuples(lm, scan_flags, parallelism) ) { ERR(pTrans->getNdbError()); closeTransaction(pNdb); return NDBT_FAILED; @@ -278,7 +274,7 @@ HugoTransactions::scanReadRecords(Ndb* pNdb, int eof; int rows = 0; - while((eof = rs->nextResult(true)) == 0){ + while((eof = pOp->nextResult(true)) == 0){ rows++; if (calc.verifyRowValues(&row) != 0){ closeTransaction(pNdb); @@ -288,7 +284,7 @@ HugoTransactions::scanReadRecords(Ndb* pNdb, if (abortCount == rows && abortTrans == true){ ndbout << "Scan is aborted" << endl; g_info << "Scan is aborted" << endl; - rs->close(); + pOp->close(); if( check == -1 ) { ERR(pTrans->getNdbError()); closeTransaction(pNdb); @@ -361,161 +357,7 @@ 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, a; - NdbOperation *pOp; - - - while (true){ - - if (retryAttempt >= retryMax){ - g_info << "ERROR: has retried this operation " << retryAttempt - << " times, failing!" << endl; - return NDBT_FAILED; - } - - pTrans = pNdb->startTransaction(); - if (pTrans == NULL) { - const NdbError err = pNdb->getNdbError(); - - if (err.status == NdbError::TemporaryError){ - ERR(err); - NdbSleep_MilliSleep(50); - retryAttempt++; - continue; - } - ERR(err); - return NDBT_FAILED; - } - - pOp = pTrans->getNdbOperation(tab.getName()); - if (pOp == NULL) { - ERR(pTrans->getNdbError()); - closeTransaction(pNdb); - return NDBT_FAILED; - } - - check = pOp->openScanExclusive(parallelism); - if( check == -1 ) { - ERR(pTrans->getNdbError()); - closeTransaction(pNdb); - return NDBT_FAILED; - } - - check = pOp->interpret_exit_ok(); - if( check == -1 ) { - ERR(pTrans->getNdbError()); - closeTransaction(pNdb); - return NDBT_FAILED; - } - - // Read all attributes from this table - for(a=0; a<tab.getNoOfColumns(); a++){ - if((row.attributeStore(a) = pOp->getValue(tab.getColumn(a)->getName())) == NULL){ - ERR(pTrans->getNdbError()); - closeTransaction(pNdb); - return NDBT_FAILED; - } - } - - check = pTrans->executeScan(); - if( check == -1 ) { - const NdbError err = pTrans->getNdbError(); - if (err.status == NdbError::TemporaryError){ - ERR(err); - closeTransaction(pNdb); - NdbSleep_MilliSleep(50); - retryAttempt++; - continue; - } - ERR(err); - closeTransaction(pNdb); - return NDBT_FAILED; - } - - // Abort after 1-100 or 1-records rows - int ranVal = rand(); - int abortCount = ranVal % (records == 0 ? 100 : records); - bool abortTrans = false; - if (abort > 0){ - // Abort if abortCount is less then abortPercent - if (abortCount < abortPercent) - abortTrans = true; - } - - - int eof; - int rows = 0; - - eof = pTrans->nextScanResult(); - while(eof == 0){ - rows++; - - if (abortCount == rows && abortTrans == true){ - g_info << "Scan is aborted" << endl; - // This scan should be aborted - check = pTrans->stopScan(); - if( check == -1 ) { - ERR(pTrans->getNdbError()); - closeTransaction(pNdb); - return NDBT_FAILED; - } - - closeTransaction(pNdb); - return NDBT_OK; - } - int res = takeOverAndUpdateRecord(pNdb, pOp); - if(res == RESTART_SCAN){ - eof = -2; - continue; - } - if (res != 0){ - closeTransaction(pNdb); - return res; - } - - eof = pTrans->nextScanResult(); - } - if (eof == -1) { - const NdbError err = pTrans->getNdbError(); - - if (err.status == NdbError::TemporaryError){ - ERR(err); - NdbSleep_MilliSleep(50); - switch (err.code){ - case 488: - case 245: - case 490: - // Too many active scans, no limit on number of retry attempts - break; - default: - retryAttempt++; - } - continue; - } - ERR(err); - closeTransaction(pNdb); - return NDBT_FAILED; - } - - if(eof == -2){ - closeTransaction(pNdb); - NdbSleep_MilliSleep(50); - retryAttempt++; - continue; - } - - closeTransaction(pNdb); - - g_info << rows << " rows have been updated" << endl; - return NDBT_OK; - } - return NDBT_FAILED; -#endif } // Scan all records exclusive and update @@ -527,166 +369,7 @@ 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, a; - NdbOperation *pOp; - - - while (true){ - - if (retryAttempt >= retryMax){ - g_info << "ERROR: has retried this operation " << retryAttempt - << " times, failing!" << endl; - return NDBT_FAILED; - } - - pTrans = pNdb->startTransaction(); - if (pTrans == NULL) { - const NdbError err = pNdb->getNdbError(); - - if (err.status == NdbError::TemporaryError){ - ERR(err); - NdbSleep_MilliSleep(50); - retryAttempt++; - continue; - } - ERR(err); - return NDBT_FAILED; - } - - pOp = pTrans->getNdbOperation(tab.getName()); - if (pOp == NULL) { - ERR(pTrans->getNdbError()); - closeTransaction(pNdb); - return NDBT_FAILED; - } - - check = pOp->openScanExclusive(parallelism); - if( check == -1 ) { - ERR(pTrans->getNdbError()); - closeTransaction(pNdb); - return NDBT_FAILED; - } - - check = pOp->interpret_exit_ok(); - if( check == -1 ) { - ERR(pTrans->getNdbError()); - closeTransaction(pNdb); - return NDBT_FAILED; - } - - // Read all attributes from this table - for(a=0; a<tab.getNoOfColumns(); a++){ - if((row.attributeStore(a) = pOp->getValue(tab.getColumn(a)->getName())) == NULL){ - ERR(pTrans->getNdbError()); - closeTransaction(pNdb); - return NDBT_FAILED; - } - } - - check = pTrans->executeScan(); - if( check == -1 ) { - const NdbError err = pTrans->getNdbError(); - if (err.status == NdbError::TemporaryError){ - ERR(err); - closeTransaction(pNdb); - NdbSleep_MilliSleep(50); - retryAttempt++; - continue; - } - ERR(err); - closeTransaction(pNdb); - return NDBT_FAILED; - } - - // Abort after 1-100 or 1-records rows - int ranVal = rand(); - int abortCount = ranVal % (records == 0 ? 100 : records); - bool abortTrans = false; - if (abort > 0){ - // Abort if abortCount is less then abortPercent - if (abortCount < abortPercent) - abortTrans = true; - } - - int eof; - int rows = 0; - - while((eof = pTrans->nextScanResult(true)) == 0){ - pUpTrans = pNdb->startTransaction(); - if (pUpTrans == NULL) { - const NdbError err = pNdb->getNdbError(); - - if (err.status == NdbError::TemporaryError){ - ERR(err); - NdbSleep_MilliSleep(50); - retryAttempt++; - continue; - } - ERR(err); - return NDBT_FAILED; - } - do { - rows++; - if (addRowToUpdate(pNdb, pUpTrans, pOp) != 0){ - pNdb->closeTransaction(pUpTrans); - closeTransaction(pNdb); - return NDBT_FAILED; - } - } while((eof = pTrans->nextScanResult(false)) == 0); - - if (abortCount == rows && abortTrans == true){ - g_info << "Scan is aborted" << endl; - // This scan should be aborted - check = pTrans->stopScan(); - if( check == -1 ) { - ERR(pTrans->getNdbError()); - closeTransaction(pNdb); - pNdb->closeTransaction(pUpTrans); - return NDBT_FAILED; - } - - closeTransaction(pNdb); - pNdb->closeTransaction(pUpTrans); - return NDBT_OK; - } - - check = pUpTrans->execute(Commit); - if( check == -1 ) { - const NdbError err = pUpTrans->getNdbError(); - ERR(err); - pNdb->closeTransaction(pUpTrans); - closeTransaction(pNdb); - return NDBT_FAILED; - } - pNdb->closeTransaction(pUpTrans); - } - if (eof == -1) { - const NdbError err = pTrans->getNdbError(); - - if (err.status == NdbError::TemporaryError){ - ERR(err); - closeTransaction(pNdb); - NdbSleep_MilliSleep(50); - retryAttempt++; - continue; - } - ERR(err); - closeTransaction(pNdb); - return NDBT_FAILED; - } - - closeTransaction(pNdb); - - g_info << rows << " rows have been updated" << endl; - return NDBT_OK; - } - return NDBT_FAILED; -#endif } int @@ -719,15 +402,14 @@ restart: return NDBT_FAILED; } - pOp = pTrans->getNdbScanOperation(tab.getName()); + pOp = getScanOperation(pTrans); if (pOp == NULL) { ERR(pTrans->getNdbError()); closeTransaction(pNdb); return NDBT_FAILED; } - NdbResultSet *rs = pOp->readTuplesExclusive(parallelism); - if( rs == 0 ) { + if( pOp->readTuplesExclusive(parallelism) ) { ERR(pTrans->getNdbError()); closeTransaction(pNdb); return NDBT_FAILED; @@ -765,10 +447,10 @@ restart: } int rows = 0; - while((check = rs->nextResult(true)) == 0){ + while((check = pOp->nextResult(true)) == 0){ do { rows++; - NdbOperation* pUp = rs->updateTuple(); + NdbOperation* pUp = pOp->updateCurrentTuple(); if(pUp == 0){ ERR(pTrans->getNdbError()); closeTransaction(pNdb); @@ -792,7 +474,7 @@ restart: closeTransaction(pNdb); return NDBT_OK; } - } while((check = rs->nextResult(false)) == 0); + } while((check = pOp->nextResult(false)) == 0); if(check != -1){ check = pTrans->execute(Commit); @@ -858,7 +540,11 @@ HugoTransactions::loadTable(Ndb* pNdb, g_info << "|- Inserting records..." << endl; for (int c=0 ; c<records ; ){ - bool closeTrans; + bool closeTrans = true; + + if(c + batch > records) + batch = records - c; + if (retryAttempt >= retryMax){ g_info << "Record " << c << " could not be inserted, has retried " << retryAttempt << " times " << endl; @@ -887,30 +573,11 @@ HugoTransactions::loadTable(Ndb* pNdb, } } - for(int b = 0; b < batch && c+b<records; b++){ - - pOp = pTrans->getNdbOperation(tab.getName()); - if (pOp == NULL) { - ERR(pTrans->getNdbError()); - closeTransaction(pNdb); - return NDBT_FAILED; - } - - check = pOp->insertTuple(); - if( check == -1 ) { - ERR(pTrans->getNdbError()); - closeTransaction(pNdb); - return NDBT_FAILED; - } - - // Set a calculated value for each attribute in this table - for (a = 0; a<tab.getNoOfColumns(); a++){ - if(setValueForAttr(pOp, a, c+b, 0 ) != 0){ - ERR(pTrans->getNdbError()); - closeTransaction(pNdb); - return NDBT_FAILED; - } - } + if(pkInsertRecord(pNdb, c, batch) != NDBT_OK) + { + ERR(pTrans->getNdbError()); + closeTransaction(pNdb); + return NDBT_FAILED; } // Execute the transaction and insert the record @@ -976,6 +643,9 @@ HugoTransactions::loadTable(Ndb* pNdb, c = c+batch; retryAttempt = 0; } + + if(pTrans) + closeTransaction(pNdb); return NDBT_OK; } @@ -986,8 +656,20 @@ HugoTransactions::fillTable(Ndb* pNdb, int retryAttempt = 0; int retryMax = 5; NdbOperation *pOp; + + const int org = batch; + const int cols = tab.getNoOfColumns(); + const int brow = tab.getRowSizeInBytes(); + const int bytes = 12 + brow + 4 * cols; + 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; + } - g_info << "|- Inserting records..." << endl; for (int c=0 ; ; ){ if (retryAttempt >= retryMax){ @@ -1012,30 +694,11 @@ HugoTransactions::fillTable(Ndb* pNdb, return NDBT_FAILED; } - for(b = 0; b < batch; b++){ - - pOp = pTrans->getNdbOperation(tab.getName()); - if (pOp == NULL) { - ERR(pTrans->getNdbError()); - closeTransaction(pNdb); - return NDBT_FAILED; - } - - check = pOp->insertTuple(); - if( check == -1 ) { - ERR(pTrans->getNdbError()); - closeTransaction(pNdb); - return NDBT_FAILED; - } - - // Set a calculated value for each attribute in this table - for (a = 0; a<tab.getNoOfColumns(); a++){ - if(setValueForAttr(pOp, a, c+b, 0 ) != 0){ - ERR(pTrans->getNdbError()); - closeTransaction(pNdb); - return NDBT_FAILED; - } - } + if(pkInsertRecord(pNdb, c, batch) != NDBT_OK) + { + ERR(pTrans->getNdbError()); + closeTransaction(pNdb); + return NDBT_FAILED; } // Execute the transaction and insert the record @@ -1113,7 +776,9 @@ HugoTransactions::createEvent(Ndb* pNdb){ NdbDictionary::Dictionary *myDict = pNdb->getDictionary(); if (!myDict) { - printf("Event Creation failedDictionary not found"); + g_err << "Dictionary not found " + << pNdb->getNdbError().code << " " + << pNdb->getNdbError().message << endl; return NDBT_FAILED; } @@ -1134,21 +799,33 @@ HugoTransactions::createEvent(Ndb* pNdb){ if (res == 0) myEvent.print(); - else { - g_info << "Event creation failed\n"; - g_info << "trying drop Event, maybe event exists\n"; + else if (myDict->getNdbError().classification == + NdbError::SchemaObjectExists) + { + g_info << "Event creation failed event exists\n"; res = myDict->dropEvent(eventName); if (res) { - g_err << "failed to drop event\n"; + g_err << "Failed to drop event: " + << myDict->getNdbError().code << " : " + << myDict->getNdbError().message << endl; return NDBT_FAILED; } // try again res = myDict->createEvent(myEvent); // Add event to database if (res) { - g_err << "failed to create event\n"; + g_err << "Failed to create event (1): " + << myDict->getNdbError().code << " : " + << myDict->getNdbError().message << endl; return NDBT_FAILED; } } + else + { + g_err << "Failed to create event (2): " + << myDict->getNdbError().code << " : " + << myDict->getNdbError().message << endl; + return NDBT_FAILED; + } return NDBT_OK; } @@ -1164,6 +841,7 @@ struct receivedEvent { }; int XXXXX = 0; + int HugoTransactions::eventOperation(Ndb* pNdb, void* pstats, int records) { @@ -1234,7 +912,9 @@ HugoTransactions::eventOperation(Ndb* pNdb, void* pstats, // set up the callbacks g_info << function << "execute\n"; if (pOp->execute()) { // This starts changes to "start flowing" - g_err << function << "operation execution failed\n"; + g_err << function << "operation execution failed: \n"; + g_err << pOp->getNdbError().code << " " + << pOp->getNdbError().message << endl; return NDBT_FAILED; } @@ -1362,36 +1042,36 @@ HugoTransactions::eventOperation(Ndb* pNdb, void* pstats, stats.n_duplicates += recDeleteEvent[i].count-1; } } - + return NDBT_OK; } int HugoTransactions::pkReadRecords(Ndb* pNdb, int records, - int batchsize, + int batch, NdbOperation::LockMode lm){ int reads = 0; int r = 0; int retryAttempt = 0; const int retryMax = 100; int check, a; - NdbOperation *pOp; - if (batchsize == 0) { - g_info << "ERROR: Argument batchsize == 0 in pkReadRecords(). Not allowed." << endl; + if (batch == 0) { + g_info << "ERROR: Argument batch == 0 in pkReadRecords(). Not allowed." << endl; return NDBT_FAILED; } - allocRows(batchsize); - while (r < records){ + if(r + batch > records) + batch = records - r; + if (retryAttempt >= retryMax){ g_info << "ERROR: has retried this operation " << retryAttempt << " times, failing!" << endl; return NDBT_FAILED; } - + pTrans = pNdb->startTransaction(); if (pTrans == NULL) { const NdbError err = pNdb->getNdbError(); @@ -1405,64 +1085,18 @@ HugoTransactions::pkReadRecords(Ndb* pNdb, ERR(err); return NDBT_FAILED; } - - for(int b=0; (b<batchsize) && (r+b < records); b++){ - pOp = pTrans->getNdbOperation(tab.getName()); - if (pOp == NULL) { - ERR(pTrans->getNdbError()); - closeTransaction(pNdb); - return NDBT_FAILED; - } - - rand_lock_mode: - switch(lm){ - case NdbOperation::LM_Read: - check = pOp->readTuple(); - break; - case NdbOperation::LM_Exclusive: - check = pOp->readTupleExclusive(); - break; - case NdbOperation::LM_CommittedRead: - check = pOp->dirtyRead(); - break; - default: - lm = (NdbOperation::LockMode)((rand() >> 16) & 3); - goto rand_lock_mode; - } - - if( check == -1 ) { - ERR(pTrans->getNdbError()); - closeTransaction(pNdb); - return NDBT_FAILED; - } - // Define primary keys - for(a = 0; a<tab.getNoOfColumns(); a++){ - if (tab.getColumn(a)->getPrimaryKey() == true){ - if(equalForAttr(pOp, a, r+b) != 0){ - ERR(pTrans->getNdbError()); - closeTransaction(pNdb); - return NDBT_FAILED; - } - } - } - - // Define attributes to read - for(a = 0; a<tab.getNoOfColumns(); a++){ - if((rows[b]->attributeStore(a) = - pOp->getValue(tab.getColumn(a)->getName())) == 0) { - ERR(pTrans->getNdbError()); - closeTransaction(pNdb); - return NDBT_FAILED; - } - } - + if(pkReadRecord(pNdb, r, batch, lm) != NDBT_OK) + { + ERR(pTrans->getNdbError()); + closeTransaction(pNdb); + return NDBT_FAILED; } - + check = pTrans->execute(Commit); if( check == -1 ) { const NdbError err = pTrans->getNdbError(); - + if (err.status == NdbError::TemporaryError){ ERR(err); closeTransaction(pNdb); @@ -1481,19 +1115,48 @@ HugoTransactions::pkReadRecords(Ndb* pNdb, closeTransaction(pNdb); return NDBT_FAILED; } - } else{ - for (int b=0; (b<batchsize) && (r+b<records); b++){ - if (calc.verifyRowValues(rows[b]) != 0){ + } else { + if(pIndexScanOp) + { + int rows_found = 0; + while((check = pIndexScanOp->nextResult()) == 0) + { + rows_found++; + if (calc.verifyRowValues(rows[0]) != 0){ + closeTransaction(pNdb); + return NDBT_FAILED; + } + } + if(check != 1 || rows_found > batch) + { closeTransaction(pNdb); return NDBT_FAILED; } - reads++; - r++; + else if(rows_found < batch) + { + if(batch == 1){ + g_info << r << ": not found" << endl; abort(); } + else + g_info << "Found " << rows_found << " of " + << batch << " rows" << endl; + } + r += batch; + reads += rows_found; + } + else + { + for (int b=0; (b<batch) && (r+b<records); b++){ + if (calc.verifyRowValues(rows[b]) != 0){ + closeTransaction(pNdb); + return NDBT_FAILED; + } + reads++; + r++; + } } } - + closeTransaction(pNdb); - } deallocRows(); g_info << reads << " records read" << endl; @@ -1518,6 +1181,8 @@ HugoTransactions::pkUpdateRecords(Ndb* pNdb, g_info << "|- Updating records (batch=" << batch << ")..." << endl; while (r < records){ + if(r + batch > records) + batch = records - r; if (retryAttempt >= retryMax){ g_info << "ERROR: has retried this operation " << retryAttempt @@ -1542,43 +1207,13 @@ HugoTransactions::pkUpdateRecords(Ndb* pNdb, return NDBT_FAILED; } - for(b = 0; b<batch && (r+b) < records; b++){ - pOp = pTrans->getNdbOperation(tab.getName()); - if (pOp == NULL) { - ERR(pTrans->getNdbError()); - closeTransaction(pNdb); - return NDBT_FAILED; - } - - check = pOp->readTupleExclusive(); - if( check == -1 ) { - ERR(pTrans->getNdbError()); - closeTransaction(pNdb); - return NDBT_FAILED; - } - - // Define primary keys - for(a = 0; a<tab.getNoOfColumns(); a++){ - if (tab.getColumn(a)->getPrimaryKey() == true){ - if(equalForAttr(pOp, a, r+b) != 0){ - ERR(pTrans->getNdbError()); - closeTransaction(pNdb); - return NDBT_FAILED; - } - } - } - - // Define attributes to read - for(a = 0; a<tab.getNoOfColumns(); a++){ - if((rows[b]->attributeStore(a) = - pOp->getValue(tab.getColumn(a)->getName())) == 0) { - ERR(pTrans->getNdbError()); - closeTransaction(pNdb); - return NDBT_FAILED; - } - } + if(pkReadRecord(pNdb, r, batch, NdbOperation::LM_Exclusive) != NDBT_OK) + { + ERR(pTrans->getNdbError()); + closeTransaction(pNdb); + return NDBT_FAILED; } - + check = pTrans->execute(NoCommit); if( check == -1 ) { const NdbError err = pTrans->getNdbError(); @@ -1594,52 +1229,62 @@ HugoTransactions::pkUpdateRecords(Ndb* pNdb, closeTransaction(pNdb); return NDBT_FAILED; } - - for(b = 0; b<batch && (b+r)<records; b++){ - if (calc.verifyRowValues(rows[b]) != 0){ - closeTransaction(pNdb); - return NDBT_FAILED; - } - - int updates = calc.getUpdatesValue(rows[b]) + 1; - - NdbOperation* pUpdOp; - pUpdOp = pTrans->getNdbOperation(tab.getName()); - if (pUpdOp == NULL) { - ERR(pTrans->getNdbError()); - closeTransaction(pNdb); - return NDBT_FAILED; - } - - check = pUpdOp->updateTuple(); - if( check == -1 ) { - ERR(pTrans->getNdbError()); - closeTransaction(pNdb); - return NDBT_FAILED; - } - - for(a = 0; a<tab.getNoOfColumns(); a++){ - if (tab.getColumn(a)->getPrimaryKey() == true){ - if(equalForAttr(pUpdOp, a, r+b) != 0){ - ERR(pTrans->getNdbError()); + + if(pIndexScanOp) + { + int rows_found = 0; + while((check = pIndexScanOp->nextResult(true)) == 0) + { + do { + + if (calc.verifyRowValues(rows[0]) != 0){ closeTransaction(pNdb); return NDBT_FAILED; } - } - } - - for(a = 0; a<tab.getNoOfColumns(); a++){ - if (tab.getColumn(a)->getPrimaryKey() == false){ - if(setValueForAttr(pUpdOp, a, r+b, updates ) != 0){ + + int updates = calc.getUpdatesValue(rows[0]) + 1; + + if(pkUpdateRecord(pNdb, r+rows_found, 1, updates) != NDBT_OK) + { ERR(pTrans->getNdbError()); closeTransaction(pNdb); return NDBT_FAILED; } + rows_found++; + } while((check = pIndexScanOp->nextResult(false)) == 0); + + if(check != 2) + break; + if((check = pTrans->execute(NoCommit)) != 0) + break; + } + if(check != 1 || rows_found != batch) + { + closeTransaction(pNdb); + return NDBT_FAILED; + } + } + else + { + for(b = 0; b<batch && (b+r)<records; b++) + { + if (calc.verifyRowValues(rows[b]) != 0) + { + closeTransaction(pNdb); + return NDBT_FAILED; + } + + int updates = calc.getUpdatesValue(rows[b]) + 1; + + if(pkUpdateRecord(pNdb, r+b, 1, updates) != NDBT_OK) + { + ERR(pTrans->getNdbError()); + closeTransaction(pNdb); + return NDBT_FAILED; } } + check = pTrans->execute(Commit); } - - check = pTrans->execute(Commit); if( check == -1 ) { const NdbError err = pTrans->getNdbError(); @@ -1658,13 +1303,12 @@ HugoTransactions::pkUpdateRecords(Ndb* pNdb, else{ updated += batch; } - - + closeTransaction(pNdb); - + r += batch; // Read next record } - + deallocRows(); g_info << "|- " << updated << " records updated" << endl; return NDBT_OK; @@ -1713,7 +1357,7 @@ HugoTransactions::pkInterpretedUpdateRecords(Ndb* pNdb, if( check == -1 ) { ERR(pTrans->getNdbError()); closeTransaction(pNdb); - return NDBT_FAILED; + return NDBT_FAILED; } // Define primary keys @@ -1861,6 +1505,8 @@ HugoTransactions::pkDelRecords(Ndb* pNdb, g_info << "|- Deleting records..." << endl; while (r < records){ + if(r + batch > records) + batch = records - r; if (retryAttempt >= retryMax){ g_info << "ERROR: has retried this operation " << retryAttempt @@ -1885,30 +1531,13 @@ HugoTransactions::pkDelRecords(Ndb* pNdb, return NDBT_FAILED; } - pOp = pTrans->getNdbOperation(tab.getName()); - if (pOp == NULL) { - ERR(pTrans->getNdbError()); - closeTransaction(pNdb); - return NDBT_FAILED; - } - - check = pOp->deleteTuple(); - if( check == -1 ) { + if(pkDeleteRecord(pNdb, r, batch) != NDBT_OK) + { ERR(pTrans->getNdbError()); closeTransaction(pNdb); return NDBT_FAILED; } - // Define primary keys - for(a = 0; a<tab.getNoOfColumns(); a++){ - if (tab.getColumn(a)->getPrimaryKey() == true){ - if(equalForAttr(pOp, a, r) != 0){ - ERR(pTrans->getNdbError()); - closeTransaction(pNdb); - return NDBT_FAILED; - } - } - } check = pTrans->execute(Commit); if( check == -1) { const NdbError err = pTrans->getNdbError(); @@ -1946,11 +1575,11 @@ HugoTransactions::pkDelRecords(Ndb* pNdb, } } else { - deleted++; + deleted += batch; } closeTransaction(pNdb); - - r++; // Read next record + + r += batch; // Read next record } @@ -1972,6 +1601,7 @@ HugoTransactions::lockRecords(Ndb* pNdb, const int retryMax = 100; int check, a, b; NdbOperation *pOp; + NdbOperation::LockMode lm = NdbOperation::LM_Exclusive; // Calculate how many records to lock in each batch if (percentToLock <= 0) @@ -1984,6 +1614,9 @@ HugoTransactions::lockRecords(Ndb* pNdb, allocRows(lockBatch); while (r < records){ + if(r + lockBatch > records) + lockBatch = records - r; + g_info << "|- Locking " << lockBatch << " records..." << endl; if (retryAttempt >= retryMax){ @@ -2006,42 +1639,13 @@ HugoTransactions::lockRecords(Ndb* pNdb, return NDBT_FAILED; } - for(b = 0; (b<lockBatch) && (r+b < records); b++){ - pOp = pTrans->getNdbOperation(tab.getName()); - if (pOp == NULL) { - ERR(pTrans->getNdbError()); - closeTransaction(pNdb); - return NDBT_FAILED; - } - - check = pOp->readTupleExclusive(); - if( check == -1 ) { - ERR(pTrans->getNdbError()); - closeTransaction(pNdb); - return NDBT_FAILED; - } - - // Define primary keys - for(a = 0; a<tab.getNoOfColumns(); a++){ - if (tab.getColumn(a)->getPrimaryKey() == true){ - if(equalForAttr(pOp, a, r+b) != 0){ - ERR(pTrans->getNdbError()); - closeTransaction(pNdb); - return NDBT_FAILED; - } - } - } - - // Define attributes to read - for(a = 0; a<tab.getNoOfColumns(); a++){ - if((rows[b]->attributeStore(a) = - pOp->getValue(tab.getColumn(a)->getName())) == 0) { - ERR(pTrans->getNdbError()); - closeTransaction(pNdb); - return NDBT_FAILED; - } - } + if(pkReadRecord(pNdb, r, lockBatch, lm) != NDBT_OK) + { + ERR(pTrans->getNdbError()); + closeTransaction(pNdb); + return NDBT_FAILED; } + // NoCommit lockTime times with 100 millis interval int sleepInterval = 50; int lockCount = lockTime / sleepInterval; @@ -2099,8 +1703,7 @@ HugoTransactions::lockRecords(Ndb* pNdb, } closeTransaction(pNdb); - - + } deallocRows(); g_info << "|- Record locking completed" << endl; @@ -2111,7 +1714,7 @@ int HugoTransactions::indexReadRecords(Ndb* pNdb, const char * idxName, int records, - int batchsize){ + int batch){ int reads = 0; int r = 0; int retryAttempt = 0; @@ -2119,24 +1722,23 @@ HugoTransactions::indexReadRecords(Ndb* pNdb, int check, a; NdbOperation *pOp; NdbIndexScanOperation *sOp; - NdbResultSet * rs; const NdbDictionary::Index* pIndex = pNdb->getDictionary()->getIndex(idxName, tab.getName()); const bool ordered = (pIndex->getType()==NdbDictionary::Index::OrderedIndex); - if (batchsize == 0) { - g_info << "ERROR: Argument batchsize == 0 in indexReadRecords(). " + if (batch == 0) { + g_info << "ERROR: Argument batch == 0 in indexReadRecords(). " << "Not allowed." << endl; return NDBT_FAILED; } if (ordered) { - batchsize = 1; + batch = 1; } - allocRows(batchsize); + allocRows(batch); while (r < records){ if (retryAttempt >= retryMax){ @@ -2159,7 +1761,7 @@ HugoTransactions::indexReadRecords(Ndb* pNdb, return NDBT_FAILED; } - for(int b=0; (b<batchsize) && (r+b < records); b++){ + for(int b=0; (b<batch) && (r+b < records); b++){ if(!ordered){ pOp = pTrans->getNdbIndexOperation(idxName, tab.getName()); if (pOp == NULL) { @@ -2175,9 +1777,7 @@ HugoTransactions::indexReadRecords(Ndb* pNdb, closeTransaction(pNdb); return NDBT_FAILED; } - - check = 0; - rs = sOp->readTuples(); + check = sOp->readTuples(); } if( check == -1 ) { @@ -2209,7 +1809,7 @@ HugoTransactions::indexReadRecords(Ndb* pNdb, } check = pTrans->execute(Commit); - check = (check == -1 ? -1 : !ordered ? check : rs->nextResult(true)); + check = (check == -1 ? -1 : !ordered ? check : sOp->nextResult(true)); if( check == -1 ) { const NdbError err = pTrans->getNdbError(); @@ -2232,7 +1832,7 @@ HugoTransactions::indexReadRecords(Ndb* pNdb, return NDBT_FAILED; } } else{ - for (int b=0; (b<batchsize) && (r+b<records); b++){ + for (int b=0; (b<batch) && (r+b<records); b++){ if (calc.verifyRowValues(rows[b]) != 0){ closeTransaction(pNdb); return NDBT_FAILED; @@ -2240,7 +1840,7 @@ HugoTransactions::indexReadRecords(Ndb* pNdb, reads++; r++; } - if(ordered && rs->nextResult(true) == 0){ + if(ordered && sOp->nextResult(true) == 0){ ndbout << "Error when comparing records " << " - index op next_result to many" << endl; closeTransaction(pNdb); @@ -2260,7 +1860,7 @@ int HugoTransactions::indexUpdateRecords(Ndb* pNdb, const char * idxName, int records, - int batchsize){ + int batch){ int updated = 0; int r = 0; @@ -2269,17 +1869,16 @@ HugoTransactions::indexUpdateRecords(Ndb* pNdb, int check, a, b; NdbOperation *pOp; NdbScanOperation * sOp; - NdbResultSet * rs; const NdbDictionary::Index* pIndex = pNdb->getDictionary()->getIndex(idxName, tab.getName()); const bool ordered = (pIndex->getType()==NdbDictionary::Index::OrderedIndex); if (ordered){ - batchsize = 1; + batch = 1; } - allocRows(batchsize); + allocRows(batch); while (r < records){ if (retryAttempt >= retryMax){ @@ -2302,7 +1901,7 @@ HugoTransactions::indexUpdateRecords(Ndb* pNdb, return NDBT_FAILED; } - for(b = 0; b<batchsize && (b+r)<records; b++){ + for(b = 0; b<batch && (b+r)<records; b++){ if(!ordered){ pOp = pTrans->getNdbIndexOperation(idxName, tab.getName()); if (pOp == NULL) { @@ -2326,7 +1925,7 @@ HugoTransactions::indexUpdateRecords(Ndb* pNdb, } check = 0; - rs = sOp->readTuplesExclusive(); + sOp->readTuplesExclusive(); } // Define primary keys @@ -2352,7 +1951,7 @@ HugoTransactions::indexUpdateRecords(Ndb* pNdb, } check = pTrans->execute(NoCommit); - check = (check == -1 ? -1 : !ordered ? check : rs->nextResult(true)); + check = (check == -1 ? -1 : !ordered ? check : sOp->nextResult(true)); if( check == -1 ) { const NdbError err = pTrans->getNdbError(); ERR(err); @@ -2367,12 +1966,12 @@ HugoTransactions::indexUpdateRecords(Ndb* pNdb, } if(ordered && check != 0){ - g_err << "Row: " << r << " not found!!" << endl; + g_err << check << " - Row: " << r << " not found!!" << endl; closeTransaction(pNdb); return NDBT_FAILED; } - for(b = 0; b<batchsize && (b+r)<records; b++){ + for(b = 0; b<batch && (b+r)<records; b++){ if (calc.verifyRowValues(rows[b]) != 0){ closeTransaction(pNdb); return NDBT_FAILED; @@ -2385,7 +1984,7 @@ HugoTransactions::indexUpdateRecords(Ndb* pNdb, pUpdOp = pTrans->getNdbIndexOperation(idxName, tab.getName()); check = (pUpdOp == 0 ? -1 : pUpdOp->updateTuple()); } else { - pUpdOp = rs->updateTuple(); + pUpdOp = sOp->updateCurrentTuple(); } if (pUpdOp == NULL) { @@ -2437,12 +2036,12 @@ HugoTransactions::indexUpdateRecords(Ndb* pNdb, ndbout << "r = " << r << endl; return NDBT_FAILED; } else { - updated += batchsize; + updated += batch; } closeTransaction(pNdb); - r+= batchsize; // Read next record + r+= batch; // Read next record } g_info << "|- " << updated << " records updated" << endl; diff --git a/ndb/test/src/NDBT_ResultRow.cpp b/ndb/test/src/NDBT_ResultRow.cpp index 11554b4a9b3..ab8d7b07ea1 100644 --- a/ndb/test/src/NDBT_ResultRow.cpp +++ b/ndb/test/src/NDBT_ResultRow.cpp @@ -84,7 +84,7 @@ NDBT_ResultRow::header (NdbOut & out) const { return out; } -BaseString NDBT_ResultRow::c_str() { +BaseString NDBT_ResultRow::c_str() const { BaseString str; @@ -137,3 +137,10 @@ NDBT_ResultRow::clone () const { return row; } + +bool +NDBT_ResultRow::operator==(const NDBT_ResultRow& other) const +{ + // quick and dirty + return c_str() == other.c_str(); +} diff --git a/ndb/test/src/NDBT_Tables.cpp b/ndb/test/src/NDBT_Tables.cpp index ff6db3e892c..5a5fecd85c1 100644 --- a/ndb/test/src/NDBT_Tables.cpp +++ b/ndb/test/src/NDBT_Tables.cpp @@ -48,7 +48,7 @@ const NDBT_Attribute T2Attribs[] = { NDBT_Attribute("KOL1", NdbDictionary::Column::Bigunsigned, 1, true), NDBT_Attribute("KOL2", NdbDictionary::Column::Unsigned), - NDBT_Attribute("KOL3", NdbDictionary::Column::Unsigned), + NDBT_Attribute("KOL3", NdbDictionary::Column::Bit, 23), NDBT_Attribute("KOL4", NdbDictionary::Column::Unsigned, 1, false, true), // Nullable NDBT_Attribute("KOL5", NdbDictionary::Column::Unsigned) @@ -820,21 +820,25 @@ NDBT_Tables::createAllTables(Ndb* pNdb){ int NDBT_Tables::createTable(Ndb* pNdb, const char* _name, bool _temp, - bool existsOk){ + bool existsOk, NDBT_CreateTableHook f){ const NdbDictionary::Table* tab = NDBT_Tables::getTable(_name); if (tab == NULL){ ndbout << "Could not create table " << _name << ", it doesn't exist in list of tables "\ - "that NDBT_Tables can create!" << endl; + "that NDBT_Tables can create!" << endl; return NDBT_WRONGARGS; } - + int r = 0; do { NdbDictionary::Table tmpTab(* tab); tmpTab.setStoredTable(_temp ? 0 : 1); - + if(f != 0 && f(pNdb, tmpTab, 0)) + { + ndbout << "Failed to create table" << endl; + return NDBT_FAILED; + } r = pNdb->getDictionary()->createTable(tmpTab); if(r == -1){ if(!existsOk){ @@ -883,6 +887,11 @@ NDBT_Tables::createTable(Ndb* pNdb, const char* _name, bool _temp, } } } + if(f != 0 && f(pNdb, tmpTab, 1)) + { + ndbout << "Failed to create table" << endl; + return NDBT_FAILED; + } } while(false); return r; diff --git a/ndb/test/src/NDBT_Test.cpp b/ndb/test/src/NDBT_Test.cpp index 6355c21c997..8fecf56531f 100644 --- a/ndb/test/src/NDBT_Test.cpp +++ b/ndb/test/src/NDBT_Test.cpp @@ -15,6 +15,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include <ndb_global.h> +#include <my_pthread.h> #include "NDBT.hpp" #include "NDBT_Test.hpp" @@ -26,7 +27,9 @@ // No verbose outxput -NDBT_Context::NDBT_Context(){ +NDBT_Context::NDBT_Context(Ndb_cluster_connection& con) + : m_cluster_connection(con) +{ tab = NULL; suite = NULL; testcase = NULL; @@ -248,7 +251,7 @@ int NDBT_Step::execute(NDBT_Context* ctx) { g_info << " |- " << name << " started [" << ctx->suite->getDate() << "]" << endl; - result = setUp(); + result = setUp(ctx->m_cluster_connection); if (result != NDBT_OK){ return result; } @@ -288,10 +291,10 @@ NDBT_NdbApiStep::NDBT_NdbApiStep(NDBT_TestCase* ptest, int -NDBT_NdbApiStep::setUp(){ - ndb = new Ndb( "TEST_DB" ); +NDBT_NdbApiStep::setUp(Ndb_cluster_connection& con){ + ndb = new Ndb(&con, "TEST_DB" ); ndb->init(1024); - + int result = ndb->waitUntilReady(300); // 5 minutes if (result != 0){ g_err << name << ": Ndb was not ready" << endl; @@ -624,8 +627,7 @@ int NDBT_TestCase::execute(NDBT_Context* ctx){ << endl; } return res; -}; - +} void NDBT_TestCase::startTimer(NDBT_Context* ctx){ timer.doStart(); @@ -757,14 +759,15 @@ int NDBT_TestSuite::addTest(NDBT_TestCase* pTest){ return 0; } -int NDBT_TestSuite::executeAll(const char* _testname){ +int NDBT_TestSuite::executeAll(Ndb_cluster_connection& con, + const char* _testname){ if(tests.size() == 0) return NDBT_FAILED; - Ndb ndb("TEST_DB"); + Ndb ndb(&con, "TEST_DB"); ndb.init(1024); - int result = ndb.waitUntilReady(300); // 5 minutes + int result = ndb.waitUntilReady(500); // 5 minutes if (result != 0){ g_err << name <<": Ndb was not ready" << endl; return NDBT_FAILED; @@ -777,18 +780,19 @@ int NDBT_TestSuite::executeAll(const char* _testname){ for (int t=0; t < NDBT_Tables::getNumTables(); t++){ const NdbDictionary::Table* ptab = NDBT_Tables::getTable(t); ndbout << "|- " << ptab->getName() << endl; - execute(&ndb, ptab, _testname); + execute(con, &ndb, ptab, _testname); } testSuiteTimer.doStop(); return reportAllTables(_testname); } int -NDBT_TestSuite::executeOne(const char* _tabname, const char* _testname){ +NDBT_TestSuite::executeOne(Ndb_cluster_connection& con, + const char* _tabname, const char* _testname){ if(tests.size() == 0) return NDBT_FAILED; - Ndb ndb("TEST_DB"); + Ndb ndb(&con, "TEST_DB"); ndb.init(1024); int result = ndb.waitUntilReady(300); // 5 minutes @@ -805,7 +809,7 @@ NDBT_TestSuite::executeOne(const char* _tabname, const char* _testname){ ndbout << "|- " << ptab->getName() << endl; - execute(&ndb, ptab, _testname); + execute(con, &ndb, ptab, _testname); if (numTestsFail > 0){ return NDBT_FAILED; @@ -814,7 +818,8 @@ NDBT_TestSuite::executeOne(const char* _tabname, const char* _testname){ } } -void NDBT_TestSuite::execute(Ndb* ndb, const NdbDictionary::Table* pTab, +void NDBT_TestSuite::execute(Ndb_cluster_connection& con, + Ndb* ndb, const NdbDictionary::Table* pTab, const char* _testname){ int result; @@ -856,14 +861,14 @@ void NDBT_TestSuite::execute(Ndb* ndb, const NdbDictionary::Table* pTab, pTab2 = pTab; } - ctx = new NDBT_Context(); + ctx = new NDBT_Context(con); ctx->setTab(pTab2); ctx->setNumRecords(records); ctx->setNumLoops(loops); if(remote_mgm != NULL) ctx->setRemoteMgm(remote_mgm); ctx->setSuite(this); - + result = tests[t]->execute(ctx); tests[t]->saveTestResult(pTab, result); if (result != NDBT_OK) @@ -1035,14 +1040,19 @@ int NDBT_TestSuite::execute(int argc, const char** argv){ loops = _loops; timer = _timer; + Ndb_cluster_connection con; + if(con.connect(12, 5, 1)) + { + return NDBT_ProgramExit(NDBT_FAILED); + } + if(optind == argc){ // No table specified - res = executeAll(_testname); + res = executeAll(con, _testname); } else { testSuiteTimer.doStart(); - Ndb ndb("TEST_DB"); ndb.init(); for(int i = optind; i<argc; i++){ - executeOne(argv[i], _testname); + executeOne(con, argv[i], _testname); } testSuiteTimer.doStop(); res = report(_testname); diff --git a/ndb/test/src/NdbBackup.cpp b/ndb/test/src/NdbBackup.cpp index 28724323bd7..fe101b9c80b 100644 --- a/ndb/test/src/NdbBackup.cpp +++ b/ndb/test/src/NdbBackup.cpp @@ -342,7 +342,7 @@ NdbBackup::NF(NdbRestarter& _restarter, int *NFDuringBackup_codes, const int sz, } return NDBT_OK; -}; +} int FailS_codes[] = { diff --git a/ndb/test/src/NdbRestarts.cpp b/ndb/test/src/NdbRestarts.cpp index 607e48c4126..c0f31af84ce 100644 --- a/ndb/test/src/NdbRestarts.cpp +++ b/ndb/test/src/NdbRestarts.cpp @@ -213,7 +213,7 @@ NdbRestarts::NdbRestart::NdbRestart(const char* _name, m_restartFunc = _func; m_numRequiredNodes = _requiredNodes; // m_arg1 = arg1; -}; +} int NdbRestarts::getNumRestarts(){ @@ -367,7 +367,7 @@ int restartRandomNodeGraceful(NdbRestarter& _restarter, "Could not restart node "<<nodeId); return NDBT_OK; -}; +} int restartRandomNodeAbort(NdbRestarter& _restarter, const NdbRestarts::NdbRestart* _restart){ @@ -382,7 +382,7 @@ int restartRandomNodeAbort(NdbRestarter& _restarter, "Could not restart node "<<nodeId); return NDBT_OK; -}; +} int restartRandomNodeError(NdbRestarter& _restarter, const NdbRestarts::NdbRestart* _restart){ @@ -397,7 +397,7 @@ int restartRandomNodeError(NdbRestarter& _restarter, "Could not restart node "<<nodeId); return NDBT_OK; -}; +} int restartMasterNodeError(NdbRestarter& _restarter, const NdbRestarts::NdbRestart* _restart){ @@ -410,7 +410,7 @@ int restartMasterNodeError(NdbRestarter& _restarter, "Could not restart node "<<nodeId); return NDBT_OK; -}; +} int restartRandomNodeInitial(NdbRestarter& _restarter, const NdbRestarts::NdbRestart* _restart){ @@ -425,7 +425,7 @@ int restartRandomNodeInitial(NdbRestarter& _restarter, "Could not restart node "<<nodeId); return NDBT_OK; -}; +} int twoNodeFailure(NdbRestarter& _restarter, const NdbRestarts::NdbRestart* _restart){ @@ -453,7 +453,7 @@ int twoNodeFailure(NdbRestarter& _restarter, "Could not restart node "<< nodeId); return NDBT_OK; -}; +} int twoMasterNodeFailure(NdbRestarter& _restarter, const NdbRestarts::NdbRestart* _restart){ @@ -478,7 +478,7 @@ int twoMasterNodeFailure(NdbRestarter& _restarter, "Could not restart node "<< nodeId); return NDBT_OK; -}; +} int get50PercentOfNodes(NdbRestarter& restarter, int * _nodes){ @@ -519,7 +519,7 @@ int fiftyPercentFail(NdbRestarter& _restarter, "Could not start all nodes"); return NDBT_OK; -}; +} int restartAllNodesGracfeul(NdbRestarter& _restarter, @@ -533,7 +533,7 @@ int restartAllNodesGracfeul(NdbRestarter& _restarter, return NDBT_OK; -}; +} int restartAllNodesAbort(NdbRestarter& _restarter, const NdbRestarts::NdbRestart* _restart){ @@ -545,7 +545,7 @@ int restartAllNodesAbort(NdbRestarter& _restarter, "Could not restart all nodes"); return NDBT_OK; -}; +} int restartAllNodesError9999(NdbRestarter& _restarter, const NdbRestarts::NdbRestart* _restart){ @@ -557,7 +557,7 @@ int restartAllNodesError9999(NdbRestarter& _restarter, "Could not restart all nodes "); return NDBT_OK; -}; +} int fiftyPercentStopAndWait(NdbRestarter& _restarter, const NdbRestarts::NdbRestart* _restart){ @@ -590,7 +590,7 @@ int fiftyPercentStopAndWait(NdbRestarter& _restarter, g_info << _restart->m_name << endl; return NDBT_OK; -}; +} int NFDuringNR_codes[] = { @@ -713,7 +713,7 @@ int restartNFDuringNR(NdbRestarter& _restarter, } return NDBT_OK; -}; +} int NRDuringLCP_Master_codes[] = { @@ -864,7 +864,7 @@ int stopOnError(NdbRestarter& _restarter, } while (false); return NDBT_OK; -}; +} int getRandomNodeId(NdbRestarter& _restarter) { myRandom48Init(NdbTick_CurrentMillisecond()); diff --git a/ndb/test/src/NdbSchemaOp.cpp b/ndb/test/src/NdbSchemaOp.cpp index a296094ea9d..4281ceb02c8 100644 --- a/ndb/test/src/NdbSchemaOp.cpp +++ b/ndb/test/src/NdbSchemaOp.cpp @@ -113,7 +113,7 @@ NdbSchemaOp::createAttribute( const char* anAttrName, AttrType anAttrType, StorageMode aStorageMode, bool nullable, - StorageAttributeType aStorageAttr, + int aStorageAttr, int aDistributionKeyFlag, int aDistributionGroupFlag, int aDistributionGroupNoOfBits, @@ -158,7 +158,6 @@ NdbSchemaOp::createAttribute( const char* anAttrName, col.setPrimaryKey(false); col.setDistributionKey(aDistributionKeyFlag); - col.setDistributionGroup(aDistributionGroupFlag,aDistributionGroupNoOfBits); col.setAutoIncrement(aAutoIncrement); col.setDefaultValue(aDefaultValue != 0 ? aDefaultValue : ""); diff --git a/ndb/test/src/UtilTransactions.cpp b/ndb/test/src/UtilTransactions.cpp index 92073143d34..31c323045ed 100644 --- a/ndb/test/src/UtilTransactions.cpp +++ b/ndb/test/src/UtilTransactions.cpp @@ -20,13 +20,20 @@ #define VERBOSE 0 -UtilTransactions::UtilTransactions(const NdbDictionary::Table& _tab): - tab(_tab){ +UtilTransactions::UtilTransactions(const NdbDictionary::Table& _tab, + const NdbDictionary::Index* _idx): + tab(_tab), idx(_idx), pTrans(0) +{ m_defaultClearMethod = 3; } -UtilTransactions::UtilTransactions(Ndb* ndb, const char * name) : - tab(* ndb->getDictionary()->getTable(name)){ +UtilTransactions::UtilTransactions(Ndb* ndb, + const char * name, + const char * index) : + tab(* ndb->getDictionary()->getTable(name)), + idx(index ? ndb->getDictionary()->getIndex(index, name) : 0), + pTrans(0) +{ m_defaultClearMethod = 3; } @@ -51,313 +58,29 @@ UtilTransactions::clearTable(Ndb* pNdb, int UtilTransactions::clearTable1(Ndb* pNdb, int records, - int parallelism){ -#if 1 + int parallelism) +{ return clearTable3(pNdb, records, 1); -#else - // Scan all records exclusive and delete - // them one by one - int retryAttempt = 0; - const int retryMax = 100; - int check; - NdbConnection *pTrans; - NdbOperation *pOp; - - while (true){ - - if (retryAttempt >= retryMax){ - g_info << "ERROR: Has retried this operation " << retryAttempt - << " times, failing!" << endl; - return NDBT_FAILED; - } - - - pTrans = pNdb->startTransaction(); - if (pTrans == NULL) { - NdbError err = pNdb->getNdbError(); - - if (err.status == NdbError::TemporaryError){ - ERR(err); - NdbSleep_MilliSleep(50); - retryAttempt++; - continue; - } - ERR(err); - RETURN_FAIL(err); - } - - pOp = pTrans->getNdbOperation(tab.getName()); - if (pOp == NULL) { - NdbError err = pNdb->getNdbError(); - ERR(err); - pNdb->closeTransaction(pTrans); - RETURN_FAIL(err); - } - - check = pOp->openScanExclusive(parallelism); - if( check == -1 ) { - NdbError err = pNdb->getNdbError(); - ERR(pTrans->getNdbError()); - pNdb->closeTransaction(pTrans); - RETURN_FAIL(err); - } - - check = pOp->interpret_exit_ok(); - if( check == -1 ) { - NdbError err = pNdb->getNdbError(); - ERR(pTrans->getNdbError()); - pNdb->closeTransaction(pTrans); - RETURN_FAIL(err); - } -#if 0 - // It's not necessary to read and PK's - // Information about the PK's are sent in - // KEYINFO20 signals anyway and used by takeOverScan - - // Read the primary keys from this table - for(int a=0; a<tab.getNoOfColumns(); a++){ - if (tab.getColumn(a)->getPrimaryKey()){ - if(pOp->getValue(tab.getColumn(a)->getName()) == NULL){ - ERR(pTrans->getNdbError()); - pNdb->closeTransaction(pTrans); - RETURN_FAIL(err); - } - } - } -#endif - - check = pTrans->executeScan(); - if( check == -1 ) { - NdbError err = pTrans->getNdbError(); - - if (err.status == NdbError::TemporaryError){ - ERR(err); - pNdb->closeTransaction(pTrans); - NdbSleep_MilliSleep(50); - retryAttempt++; - continue; - } - ERR(err); - pNdb->closeTransaction(pTrans); - RETURN_FAIL(err); - } - - int eof; - int rows = 0; - - eof = pTrans->nextScanResult(); - while(eof == 0){ - rows++; - - int res = takeOverAndDeleteRecord(pNdb, pOp); - if(res == RESTART_SCAN){ - eof = -2; - continue; - } - - if (res != 0){ - NdbError err = pNdb->getNdbError(res); - pNdb->closeTransaction(pTrans); - RETURN_FAIL(err); - } - - eof = pTrans->nextScanResult(); - } - - if (eof == -1) { - const NdbError err = pTrans->getNdbError(); - - if (err.status == NdbError::TemporaryError){ - ERR(err); - pNdb->closeTransaction(pTrans); - NdbSleep_MilliSleep(50); - // If error = 488 there should be no limit on number of retry attempts - if (err.code != 488) - retryAttempt++; - continue; - } - ERR(err); - pNdb->closeTransaction(pTrans); - RETURN_FAIL(err); - } - - if(eof == -2){ - pNdb->closeTransaction(pTrans); - NdbSleep_MilliSleep(50); - retryAttempt++; - continue; - } - - pNdb->closeTransaction(pTrans); - - g_info << rows << " deleted" << endl; - - return NDBT_OK; - } - return NDBT_FAILED; -#endif } int UtilTransactions::clearTable2(Ndb* pNdb, - int records, - int parallelism){ -#if 1 + int records, + int parallelism) +{ return clearTable3(pNdb, records, parallelism); -#else - // Scan all records exclusive and delete - // them one by one - int retryAttempt = 0; - const int retryMax = 10; - int deletedRows = 0; - int check; - NdbConnection *pTrans; - NdbOperation *pOp; - - while (true){ - - if (retryAttempt >= retryMax){ - g_info << "ERROR: has retried this operation " << retryAttempt - << " times, failing!" << endl; - return NDBT_FAILED; - } - - - pTrans = pNdb->startTransaction(); - if (pTrans == NULL) { - const NdbError err = pNdb->getNdbError(); - - if (err.status == NdbError::TemporaryError){ - ERR(err); - NdbSleep_MilliSleep(50); - retryAttempt++; - continue; - } - ERR(err); - return NDBT_FAILED; - } - - pOp = pTrans->getNdbOperation(tab.getName()); - if (pOp == NULL) { - ERR(pTrans->getNdbError()); - pNdb->closeTransaction(pTrans); - return NDBT_FAILED; - } - - check = pOp->openScanExclusive(parallelism); - if( check == -1 ) { - ERR(pTrans->getNdbError()); - pNdb->closeTransaction(pTrans); - return NDBT_FAILED; - } - - check = pOp->interpret_exit_ok(); - if( check == -1 ) { - ERR(pTrans->getNdbError()); - pNdb->closeTransaction(pTrans); - return NDBT_FAILED; - } -#if 0 - // It's not necessary to read any PK's - // Information about the PK's are sent in - // KEYINFO20 signals anyway and used by takeOverScan - - // Read the primary keys from this table - for(int a=0; a<tab.getNoOfColumns(); a++){ - if (tab.getColumn(a)->getPrimaryKey()){ - if(pOp->getValue(tab.getColumn(a)->getName()) == NULL){ - ERR(pTrans->getNdbError()); - pNdb->closeTransaction(pTrans); - return -1; - } - } - } -#endif - - check = pTrans->executeScan(); - if( check == -1 ) { - ERR(pTrans->getNdbError()); - pNdb->closeTransaction(pTrans); - return NDBT_FAILED; - } - - int eof; - NdbConnection* pDelTrans; - - while((eof = pTrans->nextScanResult(true)) == 0){ - pDelTrans = pNdb->startTransaction(); - if (pDelTrans == NULL) { - const NdbError err = pNdb->getNdbError(); -#if 0 - if (err.status == NdbError::TemporaryError){ - ERR(err); - NdbSleep_MilliSleep(50); - retryAttempt++; - continue; - } -#endif - ERR(err); - pNdb->closeTransaction(pDelTrans); - return NDBT_FAILED; - } - do { - deletedRows++; - if (addRowToDelete(pNdb, pDelTrans, pOp) != 0){ - pNdb->closeTransaction(pDelTrans); - pNdb->closeTransaction(pTrans); - return NDBT_FAILED; - } - } while((eof = pTrans->nextScanResult(false)) == 0); - - check = pDelTrans->execute(Commit); - if( check == -1 ) { - const NdbError err = pDelTrans->getNdbError(); - ERR(err); - pNdb->closeTransaction(pDelTrans); - pNdb->closeTransaction(pTrans); - return NDBT_FAILED; - } - pNdb->closeTransaction(pDelTrans); - - } - if (eof == -1) { - const NdbError err = pTrans->getNdbError(); - - if (err.status == NdbError::TemporaryError){ - ERR(err); - pNdb->closeTransaction(pTrans); - NdbSleep_MilliSleep(50); - // If error = 488 there should be no limit on number of retry attempts - if (err.code != 488) - retryAttempt++; - continue; - } - ERR(err); - pNdb->closeTransaction(pTrans); - return NDBT_FAILED; - } - - pNdb->closeTransaction(pTrans); - - g_info << deletedRows << " rows deleted" << endl; - - return NDBT_OK; - } - return NDBT_FAILED; -#endif } int UtilTransactions::clearTable3(Ndb* pNdb, - int records, - int parallelism){ + int records, + int parallelism){ // Scan all records exclusive and delete // them one by one int retryAttempt = 0; const int retryMax = 10; int deletedRows = 0; int check; - NdbConnection *pTrans; NdbScanOperation *pOp; NdbError err; @@ -380,13 +103,13 @@ UtilTransactions::clearTable3(Ndb* pNdb, } goto failed; } - - pOp = pTrans->getNdbScanOperation(tab.getName()); + + pOp = getScanOperation(pTrans); if (pOp == NULL) { err = pTrans->getNdbError(); if(err.status == NdbError::TemporaryError){ ERR(err); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); NdbSleep_MilliSleep(50); par = 1; goto restart; @@ -394,8 +117,7 @@ UtilTransactions::clearTable3(Ndb* pNdb, goto failed; } - NdbResultSet * rs = pOp->readTuplesExclusive(par); - if( rs == 0 ) { + if( pOp->readTuplesExclusive(par) ) { err = pTrans->getNdbError(); goto failed; } @@ -404,20 +126,20 @@ UtilTransactions::clearTable3(Ndb* pNdb, err = pTrans->getNdbError(); if(err.status == NdbError::TemporaryError){ ERR(err); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); NdbSleep_MilliSleep(50); continue; } goto failed; } - while((check = rs->nextResult(true)) == 0){ + while((check = pOp->nextResult(true)) == 0){ do { - if (rs->deleteTuple() != 0){ + if (pOp->deleteCurrentTuple() != 0){ goto failed; } deletedRows++; - } while((check = rs->nextResult(false)) == 0); + } while((check = pOp->nextResult(false)) == 0); if(check != -1){ check = pTrans->execute(Commit); @@ -428,7 +150,7 @@ UtilTransactions::clearTable3(Ndb* pNdb, if(check == -1){ if(err.status == NdbError::TemporaryError){ ERR(err); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); NdbSleep_MilliSleep(50); par = 1; goto restart; @@ -440,20 +162,20 @@ UtilTransactions::clearTable3(Ndb* pNdb, err = pTrans->getNdbError(); if(err.status == NdbError::TemporaryError){ ERR(err); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); NdbSleep_MilliSleep(50); par = 1; goto restart; } goto failed; } - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); return NDBT_OK; } return NDBT_FAILED; failed: - if(pTrans != 0) pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); ERR(err); return (err.code != 0 ? err.code : NDBT_FAILED); } @@ -468,7 +190,6 @@ UtilTransactions::copyTableData(Ndb* pNdb, int insertedRows = 0; int parallelism = 240; int check; - NdbConnection *pTrans; NdbScanOperation *pOp; NDBT_ResultRow row(tab); @@ -498,22 +219,20 @@ UtilTransactions::copyTableData(Ndb* pNdb, pOp = pTrans->getNdbScanOperation(tab.getName()); if (pOp == NULL) { ERR(pTrans->getNdbError()); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); return NDBT_FAILED; } - NdbResultSet* rs = pOp->readTuples(NdbScanOperation::LM_Read, - parallelism); - if( check == -1 ) { + if( pOp->readTuples(NdbScanOperation::LM_Read, parallelism) ) { ERR(pTrans->getNdbError()); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); return NDBT_FAILED; } check = pOp->interpret_exit_ok(); if( check == -1 ) { ERR(pTrans->getNdbError()); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); return NDBT_FAILED; } @@ -522,7 +241,7 @@ UtilTransactions::copyTableData(Ndb* pNdb, if ((row.attributeStore(a) = pOp->getValue(tab.getColumn(a)->getName())) == 0) { ERR(pTrans->getNdbError()); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); return NDBT_FAILED; } } @@ -530,26 +249,26 @@ UtilTransactions::copyTableData(Ndb* pNdb, check = pTrans->execute(NoCommit); if( check == -1 ) { ERR(pTrans->getNdbError()); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); return NDBT_FAILED; } int eof; - while((eof = rs->nextResult(true)) == 0){ + while((eof = pOp->nextResult(true)) == 0){ do { insertedRows++; if (addRowToInsert(pNdb, pTrans, row, destName) != 0){ - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); return NDBT_FAILED; } - } while((eof = rs->nextResult(false)) == 0); + } while((eof = pOp->nextResult(false)) == 0); check = pTrans->execute(Commit); pTrans->restart(); if( check == -1 ) { const NdbError err = pTrans->getNdbError(); ERR(err); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); return NDBT_FAILED; } } @@ -558,7 +277,7 @@ UtilTransactions::copyTableData(Ndb* pNdb, if (err.status == NdbError::TemporaryError){ ERR(err); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); NdbSleep_MilliSleep(50); // If error = 488 there should be no limit on number of retry attempts if (err.code != 488) @@ -566,11 +285,11 @@ UtilTransactions::copyTableData(Ndb* pNdb, continue; } ERR(err); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); return NDBT_FAILED; } - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); g_info << insertedRows << " rows copied" << endl; @@ -628,7 +347,6 @@ UtilTransactions::scanReadRecords(Ndb* pNdb, int retryAttempt = 0; const int retryMax = 100; int check; - NdbConnection *pTrans; NdbScanOperation *pOp; NDBT_ResultRow row(tab); @@ -654,10 +372,10 @@ UtilTransactions::scanReadRecords(Ndb* pNdb, return NDBT_FAILED; } - pOp = pTrans->getNdbScanOperation(tab.getName()); + pOp = getScanOperation(pTrans); if (pOp == NULL) { const NdbError err = pNdb->getNdbError(); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); if (err.status == NdbError::TemporaryError){ ERR(err); @@ -669,17 +387,16 @@ UtilTransactions::scanReadRecords(Ndb* pNdb, return NDBT_FAILED; } - NdbResultSet * rs = pOp->readTuples(lm, 0, parallelism); - if( rs == 0 ) { + if( pOp->readTuples(lm, 0, parallelism) ) { ERR(pTrans->getNdbError()); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); return NDBT_FAILED; } check = pOp->interpret_exit_ok(); if( check == -1 ) { ERR(pTrans->getNdbError()); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); return NDBT_FAILED; } @@ -691,7 +408,7 @@ UtilTransactions::scanReadRecords(Ndb* pNdb, if ((row.attributeStore(attrib_list[a]) = pOp->getValue(tab.getColumn(attrib_list[a])->getName())) == 0) { ERR(pTrans->getNdbError()); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); return NDBT_FAILED; } } @@ -704,13 +421,13 @@ UtilTransactions::scanReadRecords(Ndb* pNdb, if (err.status == NdbError::TemporaryError){ ERR(err); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); NdbSleep_MilliSleep(50); retryAttempt++; continue; } ERR(err); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); return NDBT_FAILED; } @@ -718,7 +435,7 @@ UtilTransactions::scanReadRecords(Ndb* pNdb, int rows = 0; - while((eof = rs->nextResult()) == 0){ + while((eof = pOp->nextResult()) == 0){ rows++; // Call callback for each record returned @@ -730,17 +447,17 @@ UtilTransactions::scanReadRecords(Ndb* pNdb, if (err.status == NdbError::TemporaryError){ ERR(err); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); NdbSleep_MilliSleep(50); retryAttempt++; continue; } ERR(err); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); return NDBT_FAILED; } - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); g_info << rows << " rows have been read" << endl; if (records != 0 && rows != records){ g_info << "Check expected number of records failed" << endl @@ -766,37 +483,26 @@ UtilTransactions::selectCount(Ndb* pNdb, int check; NdbScanOperation *pOp; + if(!pTrans) + pTrans = pNdb->startTransaction(); + while (true){ + if (retryAttempt >= retryMax){ g_info << "ERROR: has retried this operation " << retryAttempt << " times, failing!" << endl; return NDBT_FAILED; } - if(!pTrans) - pTrans = pNdb->startTransaction(); - - if(!pTrans) - { - const NdbError err = pNdb->getNdbError(); - - if (err.status == NdbError::TemporaryError) - continue; - return NDBT_FAILED; - } - - pOp = pTrans->getNdbScanOperation(tab.getName()); + pOp = getScanOperation(pTrans); if (pOp == NULL) { ERR(pTrans->getNdbError()); - pNdb->closeTransaction(pTrans); - pTrans = 0; + closeTransaction(pNdb); return NDBT_FAILED; } - NdbResultSet * rs = pOp->readTuples(lm); - if( rs == 0) { + if( pOp->readTuples(lm) ) { ERR(pTrans->getNdbError()); - pNdb->closeTransaction(pTrans); - pTrans = 0; + closeTransaction(pNdb); return NDBT_FAILED; } @@ -809,8 +515,7 @@ UtilTransactions::selectCount(Ndb* pNdb, check = pOp->interpret_exit_ok(); if( check == -1 ) { ERR(pTrans->getNdbError()); - pNdb->closeTransaction(pTrans); - pTrans = 0; + closeTransaction(pNdb); return NDBT_FAILED; } } @@ -819,8 +524,7 @@ UtilTransactions::selectCount(Ndb* pNdb, check = pTrans->execute(NoCommit); if( check == -1 ) { ERR(pTrans->getNdbError()); - pNdb->closeTransaction(pTrans); - pTrans = 0; + closeTransaction(pNdb); return NDBT_FAILED; } @@ -828,27 +532,24 @@ UtilTransactions::selectCount(Ndb* pNdb, int rows = 0; - while((eof = rs->nextResult()) == 0){ + while((eof = pOp->nextResult()) == 0){ rows++; } if (eof == -1) { const NdbError err = pTrans->getNdbError(); if (err.status == NdbError::TemporaryError){ - pNdb->closeTransaction(pTrans); - pTrans = 0; + closeTransaction(pNdb); NdbSleep_MilliSleep(50); retryAttempt++; continue; } ERR(err); - pNdb->closeTransaction(pTrans); - pTrans = 0; + closeTransaction(pNdb); return NDBT_FAILED; } - pNdb->closeTransaction(pTrans); - pTrans = 0; + closeTransaction(pNdb); if (count_rows != NULL){ *count_rows = rows; @@ -922,14 +623,13 @@ UtilTransactions::scanAndCompareUniqueIndex(Ndb* pNdb, int retryAttempt = 0; const int retryMax = 100; int check; - NdbConnection *pTrans; NdbScanOperation *pOp; NDBT_ResultRow row(tab); parallelism = 1; while (true){ - +restart: if (retryAttempt >= retryMax){ g_info << "ERROR: has retried this operation " << retryAttempt << " times, failing!" << endl; @@ -953,7 +653,7 @@ UtilTransactions::scanAndCompareUniqueIndex(Ndb* pNdb, pOp = pTrans->getNdbScanOperation(tab.getName()); if (pOp == NULL) { const NdbError err = pNdb->getNdbError(); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); ERR(err); if (err.status == NdbError::TemporaryError){ @@ -964,23 +664,23 @@ UtilTransactions::scanAndCompareUniqueIndex(Ndb* pNdb, return NDBT_FAILED; } - NdbResultSet* rs; + int rs; if(transactional){ rs = pOp->readTuples(NdbScanOperation::LM_Read, 0, parallelism); } else { rs = pOp->readTuples(NdbScanOperation::LM_CommittedRead, 0, parallelism); } - if( rs == 0 ) { + if( rs != 0 ) { ERR(pTrans->getNdbError()); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); return NDBT_FAILED; } check = pOp->interpret_exit_ok(); if( check == -1 ) { ERR(pTrans->getNdbError()); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); return NDBT_FAILED; } @@ -989,7 +689,7 @@ UtilTransactions::scanAndCompareUniqueIndex(Ndb* pNdb, if ((row.attributeStore(a) = pOp->getValue(tab.getColumn(a)->getName())) == 0) { ERR(pTrans->getNdbError()); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); return NDBT_FAILED; } } @@ -1000,13 +700,13 @@ UtilTransactions::scanAndCompareUniqueIndex(Ndb* pNdb, if (err.status == NdbError::TemporaryError){ ERR(err); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); NdbSleep_MilliSleep(50); retryAttempt++; continue; } ERR(err); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); return NDBT_FAILED; } @@ -1014,17 +714,32 @@ UtilTransactions::scanAndCompareUniqueIndex(Ndb* pNdb, int rows = 0; - while((eof = rs->nextResult()) == 0){ + while((eof = pOp->nextResult()) == 0){ rows++; // ndbout << row.c_str().c_str() << endl; - if (readRowFromTableAndIndex(pNdb, pTrans, pIndex, row) != NDBT_OK){ - pNdb->closeTransaction(pTrans); + + while((eof= pOp->nextResult(false)) == 0); + if(eof == 2) + eof = pOp->nextResult(true); // this should give -1 + if(eof == -1) + { + const NdbError err = pTrans->getNdbError(); + + if (err.status == NdbError::TemporaryError){ + ERR(err); + closeTransaction(pNdb); + NdbSleep_MilliSleep(50); + retryAttempt++; + goto restart; + } + } + closeTransaction(pNdb); return NDBT_FAILED; } } @@ -1033,18 +748,17 @@ UtilTransactions::scanAndCompareUniqueIndex(Ndb* pNdb, if (err.status == NdbError::TemporaryError){ ERR(err); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); NdbSleep_MilliSleep(50); retryAttempt++; - rows--; continue; } ERR(err); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); return NDBT_FAILED; } - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); return NDBT_OK; } @@ -1062,7 +776,6 @@ UtilTransactions::readRowFromTableAndIndex(Ndb* pNdb, const int retryMax = 100; int check, a; NdbConnection *pTrans1=NULL; - NdbResultSet *cursor= NULL; NdbOperation *pOp; int return_code= NDBT_FAILED; @@ -1112,7 +825,6 @@ UtilTransactions::readRowFromTableAndIndex(Ndb* pNdb, check = pOp->readTuple(); if( check == -1 ) { ERR(pTrans1->getNdbError()); - pNdb->closeTransaction(pTrans1); goto close_all; } @@ -1190,7 +902,7 @@ UtilTransactions::readRowFromTableAndIndex(Ndb* pNdb, if (pIndexOp) { not_ok = pIndexOp->readTuple() == -1; } else { - not_ok = (cursor= pScanOp->readTuples()) == 0; + not_ok = pScanOp->readTuples(); } if( not_ok ) { @@ -1244,7 +956,7 @@ UtilTransactions::readRowFromTableAndIndex(Ndb* pNdb, #if VERBOSE printf("\n"); #endif - + scanTrans->refresh(); check = pTrans1->execute(Commit); if( check == -1 ) { const NdbError err = pTrans1->getNdbError(); @@ -1267,7 +979,7 @@ UtilTransactions::readRowFromTableAndIndex(Ndb* pNdb, */ if(!null_found){ if (pScanOp) { - if (cursor->nextResult() != 0){ + if (pScanOp->nextResult() != 0){ const NdbError err = pTrans1->getNdbError(); ERR(err); ndbout << "Error when comparing records - index op next_result missing" << endl; @@ -1282,7 +994,7 @@ UtilTransactions::readRowFromTableAndIndex(Ndb* pNdb, goto close_all; } if (pScanOp) { - if (cursor->nextResult() == 0){ + if (pScanOp->nextResult() == 0){ ndbout << "Error when comparing records - index op next_result to many" << endl; ndbout << "row: " << row.c_str().c_str() << endl; goto close_all; @@ -1294,8 +1006,6 @@ UtilTransactions::readRowFromTableAndIndex(Ndb* pNdb, } close_all: - if (cursor) - cursor->close(); if (pTrans1) pNdb->closeTransaction(pTrans1); @@ -1311,10 +1021,8 @@ UtilTransactions::verifyOrderedIndex(Ndb* pNdb, int retryAttempt = 0; const int retryMax = 100; int check; - NdbConnection *pTrans; NdbScanOperation *pOp; NdbIndexScanOperation * iop = 0; - NdbResultSet* cursor= 0; NDBT_ResultRow scanRow(tab); NDBT_ResultRow pkRow(tab); @@ -1349,23 +1057,20 @@ UtilTransactions::verifyOrderedIndex(Ndb* pNdb, pOp = pTrans->getNdbScanOperation(tab.getName()); if (pOp == NULL) { ERR(pTrans->getNdbError()); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); return NDBT_FAILED; } - NdbResultSet* - rs = pOp->readTuples(NdbScanOperation::LM_Read, 0, parallelism); - - if( rs == 0 ) { + if( pOp->readTuples(NdbScanOperation::LM_Read, 0, parallelism) ) { ERR(pTrans->getNdbError()); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); return NDBT_FAILED; } check = pOp->interpret_exit_ok(); if( check == -1 ) { ERR(pTrans->getNdbError()); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); return NDBT_FAILED; } @@ -1380,19 +1085,19 @@ UtilTransactions::verifyOrderedIndex(Ndb* pNdb, if (err.status == NdbError::TemporaryError){ ERR(err); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); NdbSleep_MilliSleep(50); retryAttempt++; continue; } ERR(err); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); return NDBT_FAILED; } int eof; int rows = 0; - while(check == 0 && (eof = rs->nextResult()) == 0){ + while(check == 0 && (eof = pOp->nextResult()) == 0){ rows++; bool null_found= false; @@ -1417,10 +1122,11 @@ UtilTransactions::verifyOrderedIndex(Ndb* pNdb, if(!iop && (iop= pTrans->getNdbIndexScanOperation(indexName, tab.getName()))) { - cursor= iop->readTuples(NdbScanOperation::LM_CommittedRead, - parallelism); + if(iop->readTuples(NdbScanOperation::LM_CommittedRead, + parallelism)) + goto error; iop->interpret_exit_ok(); - if(!cursor || get_values(iop, indexRow)) + if(get_values(iop, indexRow)) goto error; } else if(!iop || iop->reset_bounds()) @@ -1440,17 +1146,17 @@ UtilTransactions::verifyOrderedIndex(Ndb* pNdb, g_err << "Error when comapring records" << endl; g_err << " scanRow: \n" << scanRow.c_str().c_str() << endl; g_err << " pkRow: \n" << pkRow.c_str().c_str() << endl; - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); return NDBT_FAILED; } if(!null_found) { - if((res= cursor->nextResult()) != 0){ + if((res= iop->nextResult()) != 0){ g_err << "Failed to find row using index: " << res << endl; ERR(pTrans->getNdbError()); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); return NDBT_FAILED; } @@ -1458,14 +1164,14 @@ UtilTransactions::verifyOrderedIndex(Ndb* pNdb, g_err << "Error when comapring records" << endl; g_err << " scanRow: \n" << scanRow.c_str().c_str() << endl; g_err << " indexRow: \n" << indexRow.c_str().c_str() << endl; - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); return NDBT_FAILED; } - if(cursor->nextResult() == 0){ + if(iop->nextResult() == 0){ g_err << "Found extra row!!" << endl; g_err << " indexRow: \n" << indexRow.c_str().c_str() << endl; - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); return NDBT_FAILED; } } @@ -1478,18 +1184,18 @@ UtilTransactions::verifyOrderedIndex(Ndb* pNdb, if (err.status == NdbError::TemporaryError){ ERR(err); iop = 0; - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); NdbSleep_MilliSleep(50); retryAttempt++; rows--; continue; } ERR(err); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); return NDBT_FAILED; } - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); return NDBT_OK; } @@ -1537,3 +1243,218 @@ UtilTransactions::equal(const NdbDictionary::Table* pTable, } return 0; } + +NdbScanOperation* +UtilTransactions::getScanOperation(NdbConnection* pTrans) +{ + return (NdbScanOperation*) + getOperation(pTrans, NdbOperation::OpenScanRequest); +} + +NdbOperation* +UtilTransactions::getOperation(NdbConnection* pTrans, + NdbOperation::OperationType type) +{ + switch(type){ + case NdbOperation::ReadRequest: + case NdbOperation::ReadExclusive: + if(idx) + { + switch(idx->getType()){ + case NdbDictionary::Index::UniqueHashIndex: + return pTrans->getNdbIndexOperation(idx->getName(), tab.getName()); + case NdbDictionary::Index::OrderedIndex: + return pTrans->getNdbIndexScanOperation(idx->getName(), tab.getName()); + } + } + case NdbOperation::InsertRequest: + case NdbOperation::WriteRequest: + return pTrans->getNdbOperation(tab.getName()); + case NdbOperation::UpdateRequest: + case NdbOperation::DeleteRequest: + if(idx) + { + switch(idx->getType()){ + case NdbDictionary::Index::UniqueHashIndex: + return pTrans->getNdbIndexOperation(idx->getName(), tab.getName()); + } + } + return pTrans->getNdbOperation(tab.getName()); + case NdbOperation::OpenScanRequest: + if(idx) + { + switch(idx->getType()){ + case NdbDictionary::Index::OrderedIndex: + return pTrans->getNdbIndexScanOperation(idx->getName(), tab.getName()); + } + } + return pTrans->getNdbScanOperation(tab.getName()); + case NdbOperation::OpenRangeScanRequest: + if(idx) + { + switch(idx->getType()){ + case NdbDictionary::Index::OrderedIndex: + return pTrans->getNdbIndexScanOperation(idx->getName(), tab.getName()); + } + } + return 0; + } +} + +#include <HugoOperations.hpp> + +int +UtilTransactions::closeTransaction(Ndb* pNdb) +{ + if (pTrans != NULL){ + pNdb->closeTransaction(pTrans); + pTrans = NULL; + } + return 0; +} + +int +UtilTransactions::compare(Ndb* pNdb, const char* tab_name2, int flags){ + + + NdbError err; + int return_code= -1, row_count= 0; + int retryAttempt = 0, retryMax = 10; + + HugoCalculator calc(tab); + NDBT_ResultRow row(tab); + const NdbDictionary::Table* tmp= pNdb->getDictionary()->getTable(tab_name2); + if(tmp == 0) + { + g_err << "Unable to lookup table: " << tab_name2 + << endl << pNdb->getDictionary()->getNdbError() << endl; + return -1; + } + const NdbDictionary::Table& tab2= *tmp; + + HugoOperations cmp(tab2); + UtilTransactions count(tab2); + + while (true){ + + if (retryAttempt++ >= retryMax){ + g_info << "ERROR: has retried this operation " << retryAttempt + << " times, failing!" << endl; + return -1; + } + + NdbScanOperation *pOp= 0; + pTrans = pNdb->startTransaction(); + if (pTrans == NULL) { + err = pNdb->getNdbError(); + goto error; + } + + pOp= pTrans->getNdbScanOperation(tab.getName()); + if (pOp == NULL) { + ERR(err= pTrans->getNdbError()); + goto error; + } + + if( pOp->readTuples(NdbScanOperation::LM_Read) ) { + ERR(err= pTrans->getNdbError()); + goto error; + } + + if( pOp->interpret_exit_ok() == -1 ) { + ERR(err= pTrans->getNdbError()); + goto error; + } + + // Read all attributes + { + for (int a = 0; a < tab.getNoOfColumns(); a++){ + if ((row.attributeStore(a) = + pOp->getValue(tab.getColumn(a)->getName())) == 0) { + ERR(err= pTrans->getNdbError()); + goto error; + } + } + } + + if( pTrans->execute(NoCommit) == -1 ) { + ERR(err= pTrans->getNdbError()); + goto error; + } + + { + int eof; + while((eof = pOp->nextResult(true)) == 0) + { + do { + row_count++; + if(cmp.startTransaction(pNdb) != NDBT_OK) + { + ERR(err= pNdb->getNdbError()); + goto error; + } + int rowNo= calc.getIdValue(&row); + if(cmp.pkReadRecord(pNdb, rowNo, 1) != NDBT_OK) + { + ERR(err= cmp.getTransaction()->getNdbError()); + goto error; + } + if(cmp.execute_Commit(pNdb) != NDBT_OK) + { + ERR(err= cmp.getTransaction()->getNdbError()); + goto error; + } + if(row != cmp.get_row(0)) + { + g_err << "COMPARE FAILED" << endl; + g_err << row << endl; + g_err << cmp.get_row(0) << endl; + return_code= 1; + goto close; + } + retryAttempt= 0; + cmp.closeTransaction(pNdb); + } while((eof = pOp->nextResult(false)) == 0); + } + if (eof == -1) + { + err = pTrans->getNdbError(); + goto error; + } + } + + pTrans->close(); pTrans= 0; + + g_info << row_count << " rows compared" << endl; + { + int row_count2; + if(count.selectCount(pNdb, 0, &row_count2) != NDBT_OK) + { + g_err << "Failed to count rows in tab_name2" << endl; + return -1; + } + + g_info << row_count2 << " rows in tab_name2" << endl; + return (row_count == row_count2 ? 0 : 1); + } +error: + if(err.status == NdbError::TemporaryError) + { + NdbSleep_MilliSleep(50); + if(pTrans != 0) + { + pTrans->close(); + pTrans= 0; + } + if(cmp.getTransaction()) + cmp.closeTransaction(pNdb); + continue; + } + break; + } + +close: + if(pTrans != 0) pTrans->close(); + + return return_code; +} diff --git a/ndb/test/tools/Makefile.am b/ndb/test/tools/Makefile.am index a6a013bb263..873136e254d 100644 --- a/ndb/test/tools/Makefile.am +++ b/ndb/test/tools/Makefile.am @@ -1,9 +1,8 @@ -ndbtest_PROGRAMS = hugoCalculator hugoLoad hugoFill hugoLockRecords hugoPkDelete hugoPkRead hugoPkReadRecord hugoPkUpdate hugoScanRead hugoScanUpdate restart verify_index copy_tab create_index ndb_cpcc +ndbtest_PROGRAMS = hugoLoad hugoFill hugoLockRecords hugoPkDelete hugoPkRead hugoPkReadRecord hugoPkUpdate hugoScanRead hugoScanUpdate restart verify_index copy_tab create_index ndb_cpcc # transproxy -hugoCalculator_SOURCES = hugoCalculator.cpp hugoFill_SOURCES = hugoFill.cpp hugoLoad_SOURCES = hugoLoad.cpp hugoLockRecords_SOURCES = hugoLockRecords.cpp diff --git a/ndb/test/tools/copy_tab.cpp b/ndb/test/tools/copy_tab.cpp index 30141acaa78..97370b170ef 100644 --- a/ndb/test/tools/copy_tab.cpp +++ b/ndb/test/tools/copy_tab.cpp @@ -56,9 +56,12 @@ int main(int argc, const char** argv){ _tabname = argv[optind]; _to_tabname = argv[optind+1]; - if (_connectstr) - Ndb::setConnectString(_connectstr); - Ndb MyNdb(_dbname); + Ndb_cluster_connection con(_connectstr); + if(con.connect(12, 5, 1) != 0) + { + return NDBT_ProgramExit(NDBT_FAILED); + } + Ndb MyNdb(&con,_dbname); if(MyNdb.init() != 0){ ERR(MyNdb.getNdbError()); return NDBT_ProgramExit(NDBT_FAILED); diff --git a/ndb/test/tools/create_index.cpp b/ndb/test/tools/create_index.cpp index 6e4c5377f4a..9f9c26aa0da 100644 --- a/ndb/test/tools/create_index.cpp +++ b/ndb/test/tools/create_index.cpp @@ -53,8 +53,13 @@ main(int argc, const char** argv){ return NDBT_ProgramExit(NDBT_WRONGARGS); } + Ndb_cluster_connection con; + if(con.connect(12, 5, 1) != 0) + { + return NDBT_ProgramExit(NDBT_FAILED); + } - Ndb MyNdb(_dbname); + Ndb MyNdb(&con, _dbname); if(MyNdb.init() != 0){ ERR(MyNdb.getNdbError()); return NDBT_ProgramExit(NDBT_FAILED); diff --git a/ndb/test/tools/hugoFill.cpp b/ndb/test/tools/hugoFill.cpp index 6253bd1bb12..6408b2987f9 100644 --- a/ndb/test/tools/hugoFill.cpp +++ b/ndb/test/tools/hugoFill.cpp @@ -51,7 +51,12 @@ int main(int argc, const char** argv){ _tabname = argv[optind]; // Connect to Ndb - Ndb MyNdb( "TEST_DB" ); + Ndb_cluster_connection con; + if(con.connect(12, 5, 1) != 0) + { + return NDBT_ProgramExit(NDBT_FAILED); + } + Ndb MyNdb(&con, "TEST_DB" ); if(MyNdb.init() != 0){ ERR(MyNdb.getNdbError()); diff --git a/ndb/test/tools/hugoLoad.cpp b/ndb/test/tools/hugoLoad.cpp index 3a0bba07df3..1a229169650 100644 --- a/ndb/test/tools/hugoLoad.cpp +++ b/ndb/test/tools/hugoLoad.cpp @@ -56,7 +56,12 @@ int main(int argc, const char** argv){ _tabname = argv[optind]; // Connect to Ndb - Ndb MyNdb( db ? db : "TEST_DB" ); + Ndb_cluster_connection con; + if(con.connect(12, 5, 1) != 0) + { + return NDBT_ProgramExit(NDBT_FAILED); + } + Ndb MyNdb( &con, db ? db : "TEST_DB" ); if(MyNdb.init() != 0){ ERR(MyNdb.getNdbError()); diff --git a/ndb/test/tools/hugoLockRecords.cpp b/ndb/test/tools/hugoLockRecords.cpp index 629408d401d..c0d0b9f9c5a 100644 --- a/ndb/test/tools/hugoLockRecords.cpp +++ b/ndb/test/tools/hugoLockRecords.cpp @@ -59,7 +59,12 @@ int main(int argc, const char** argv){ _tabname = argv[optind]; // Connect to Ndb - Ndb MyNdb( "TEST_DB" ); + Ndb_cluster_connection con; + if(con.connect(12, 5, 1) != 0) + { + return NDBT_ProgramExit(NDBT_FAILED); + } + Ndb MyNdb(&con, "TEST_DB" ); if(MyNdb.init() != 0){ ERR(MyNdb.getNdbError()); diff --git a/ndb/test/tools/hugoPkDelete.cpp b/ndb/test/tools/hugoPkDelete.cpp index 78a90ebcb46..84e7ded0add 100644 --- a/ndb/test/tools/hugoPkDelete.cpp +++ b/ndb/test/tools/hugoPkDelete.cpp @@ -55,7 +55,12 @@ int main(int argc, const char** argv){ _tabname = argv[optind]; // Connect to Ndb - Ndb MyNdb( "TEST_DB" ); + Ndb_cluster_connection con; + if(con.connect(12, 5, 1) != 0) + { + return NDBT_ProgramExit(NDBT_FAILED); + } + Ndb MyNdb(&con, "TEST_DB" ); if(MyNdb.init() != 0){ ERR(MyNdb.getNdbError()); diff --git a/ndb/test/tools/hugoPkRead.cpp b/ndb/test/tools/hugoPkRead.cpp index cf08b137e8e..e3702dc5ca1 100644 --- a/ndb/test/tools/hugoPkRead.cpp +++ b/ndb/test/tools/hugoPkRead.cpp @@ -60,7 +60,12 @@ int main(int argc, const char** argv){ // Connect to Ndb - Ndb MyNdb( "TEST_DB" ); + Ndb_cluster_connection con; + if(con.connect(12, 5, 1) != 0) + { + return NDBT_ProgramExit(NDBT_FAILED); + } + Ndb MyNdb(&con, "TEST_DB" ); if(MyNdb.init() != 0){ ERR(MyNdb.getNdbError()); diff --git a/ndb/test/tools/hugoPkReadRecord.cpp b/ndb/test/tools/hugoPkReadRecord.cpp index 38b7cae2bf4..c60a994c7d4 100644 --- a/ndb/test/tools/hugoPkReadRecord.cpp +++ b/ndb/test/tools/hugoPkReadRecord.cpp @@ -62,7 +62,12 @@ int main(int argc, const char** argv) << "Row: " << _row << ", PrimaryKey: " << _primaryKey << endl; - Ndb* ndb = new Ndb("TEST_DB"); + Ndb_cluster_connection con; + if(con.connect(12, 5, 1) != 0) + { + return NDBT_ProgramExit(NDBT_FAILED); + } + Ndb* ndb = new Ndb(&con, "TEST_DB"); if (ndb->init() == 0 && ndb->waitUntilReady(30) == 0) { NdbConnection* conn = ndb->startTransaction(); diff --git a/ndb/test/tools/hugoPkUpdate.cpp b/ndb/test/tools/hugoPkUpdate.cpp index ccbbccfc523..7d46ae95c29 100644 --- a/ndb/test/tools/hugoPkUpdate.cpp +++ b/ndb/test/tools/hugoPkUpdate.cpp @@ -58,7 +58,12 @@ int main(int argc, const char** argv){ _tabname = argv[optind]; // Connect to Ndb - Ndb MyNdb( db ? db : "TEST_DB" ); + Ndb_cluster_connection con; + if(con.connect(12, 5, 1) != 0) + { + return NDBT_ProgramExit(NDBT_FAILED); + } + Ndb MyNdb( &con, db ? db : "TEST_DB" ); if(MyNdb.init() != 0){ ERR(MyNdb.getNdbError()); diff --git a/ndb/test/tools/hugoScanRead.cpp b/ndb/test/tools/hugoScanRead.cpp index 4cd428f44c6..a345bb88d0e 100644 --- a/ndb/test/tools/hugoScanRead.cpp +++ b/ndb/test/tools/hugoScanRead.cpp @@ -62,7 +62,12 @@ int main(int argc, const char** argv){ _tabname = argv[optind]; // Connect to Ndb - Ndb MyNdb( db ? db : "TEST_DB" ); + Ndb_cluster_connection con; + if(con.connect(12, 5, 1) != 0) + { + return NDBT_ProgramExit(NDBT_FAILED); + } + Ndb MyNdb( &con, db ? db : "TEST_DB" ); if(MyNdb.init() != 0){ ERR(MyNdb.getNdbError()); @@ -86,8 +91,7 @@ int main(int argc, const char** argv){ if(!pIdx) ndbout << " Index " << argv[optind+1] << " not found" << endl; else - if(pIdx->getType() != NdbDictionary::Index::UniqueOrderedIndex && - pIdx->getType() != NdbDictionary::Index::OrderedIndex) + if(pIdx->getType() != NdbDictionary::Index::OrderedIndex) { ndbout << " Index " << argv[optind+1] << " is not scannable" << endl; pIdx = 0; diff --git a/ndb/test/tools/hugoScanUpdate.cpp b/ndb/test/tools/hugoScanUpdate.cpp index 8fe84779c6b..6960fa44b96 100644 --- a/ndb/test/tools/hugoScanUpdate.cpp +++ b/ndb/test/tools/hugoScanUpdate.cpp @@ -59,7 +59,12 @@ int main(int argc, const char** argv){ _tabname = argv[optind]; // Connect to Ndb - Ndb MyNdb( db ? db : "TEST_DB" ); + Ndb_cluster_connection con; + if(con.connect(12, 5, 1) != 0) + { + return NDBT_ProgramExit(NDBT_FAILED); + } + Ndb MyNdb( &con, db ? db : "TEST_DB" ); if(MyNdb.init() != 0){ ERR(MyNdb.getNdbError()); diff --git a/ndb/test/tools/verify_index.cpp b/ndb/test/tools/verify_index.cpp index 6c8e304e1a1..acc97af883b 100644 --- a/ndb/test/tools/verify_index.cpp +++ b/ndb/test/tools/verify_index.cpp @@ -53,7 +53,12 @@ int main(int argc, const char** argv){ _indexname = argv[optind+1]; // Connect to Ndb - Ndb MyNdb( "TEST_DB" ); + Ndb_cluster_connection con; + if(con.connect(12, 5, 1) != 0) + { + return NDBT_ProgramExit(NDBT_FAILED); + } + Ndb MyNdb(&con, "TEST_DB" ); if(MyNdb.init() != 0){ ERR(MyNdb.getNdbError()); |