diff options
Diffstat (limited to 'ndb')
26 files changed, 380 insertions, 286 deletions
diff --git a/ndb/examples/ndbapi_event_example/ndbapi_event.cpp b/ndb/examples/ndbapi_event_example/ndbapi_event.cpp index f03564744c7..286f6fafbab 100644 --- a/ndb/examples/ndbapi_event_example/ndbapi_event.cpp +++ b/ndb/examples/ndbapi_event_example/ndbapi_event.cpp @@ -70,12 +70,13 @@ * mysql> use TEST_DB; * mysql> create table TAB0 (COL0 int primary key, COL1 int, COL11 int) engine=ndb; * - * In another window start ndbapi_example5, wait until properly started + * In another window start ndbapi_event, wait until properly started * - * mysql> insert into TAB0 values (1,2,3); - * mysql> insert into TAB0 values (2,2,3); - * mysql> insert into TAB0 values (3,2,9); - * mysql> + insert into TAB0 values (1,2,3); + insert into TAB0 values (2,2,3); + insert into TAB0 values (3,2,9); + update TAB0 set COL1=10 where COL0=1; + delete from TAB0 where COL0=1; * * you should see the data popping up in the example window * diff --git a/ndb/include/kernel/AttributeHeader.hpp b/ndb/include/kernel/AttributeHeader.hpp index e3900b63fdc..3af5d01f007 100644 --- a/ndb/include/kernel/AttributeHeader.hpp +++ b/ndb/include/kernel/AttributeHeader.hpp @@ -40,6 +40,7 @@ public: STATIC_CONST( RANGE_NO = 0xFFFB ); // Read range no (when batched ranges) STATIC_CONST( ROW_SIZE = 0xFFFA ); + STATIC_CONST( FRAGMENT_MEMORY= 0xFFF9 ); /** Initialize AttributeHeader at location aHeaderPtr */ static AttributeHeader& init(void* aHeaderPtr, Uint32 anAttributeId, diff --git a/ndb/include/kernel/trigger_definitions.h b/ndb/include/kernel/trigger_definitions.h index 7ce74877de4..11410654a15 100644 --- a/ndb/include/kernel/trigger_definitions.h +++ b/ndb/include/kernel/trigger_definitions.h @@ -56,6 +56,7 @@ struct TriggerActionTime { }; struct TriggerEvent { + /** TableEvent must match 1 << TriggerEvent */ enum Value { TE_INSERT = 0, TE_DELETE = 1, diff --git a/ndb/include/ndbapi/NdbDictionary.hpp b/ndb/include/ndbapi/NdbDictionary.hpp index b4e670dfb89..80c0831f675 100644 --- a/ndb/include/ndbapi/NdbDictionary.hpp +++ b/ndb/include/ndbapi/NdbDictionary.hpp @@ -438,10 +438,13 @@ public: const char* getDefaultValue() const; static const Column * FRAGMENT; + static const Column * FRAGMENT_MEMORY; static const Column * ROW_COUNT; static const Column * COMMIT_COUNT; static const Column * ROW_SIZE; static const Column * RANGE_NO; + + int getSizeInBytes() const; #endif private: @@ -714,6 +717,8 @@ public: int getRowSizeInBytes() const ; int createTableInDb(Ndb*, bool existingEqualIsOk = true) const ; + + int getReplicaCount() const ; #endif private: @@ -914,6 +919,9 @@ public: /** * Specifies the type of database operations an Event listens to */ +#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL + /** TableEvent must match 1 << TriggerEvent */ +#endif enum TableEvent { TE_INSERT=1, ///< Insert event on table TE_DELETE=2, ///< Delete event on table diff --git a/ndb/include/ndbapi/NdbOperation.hpp b/ndb/include/ndbapi/NdbOperation.hpp index 24af18bb507..fca610772cc 100644 --- a/ndb/include/ndbapi/NdbOperation.hpp +++ b/ndb/include/ndbapi/NdbOperation.hpp @@ -709,6 +709,11 @@ public: */ const char* getTableName() const; + /** + * Get table object for this operation + */ + const NdbDictionary::Table * getTable() const; + /** @} *********************************************************************/ #ifndef DOXYGEN_SHOULD_SKIP_INTERNAL diff --git a/ndb/include/ndbapi/NdbTransaction.hpp b/ndb/include/ndbapi/NdbTransaction.hpp index 148f4911ed9..e0b78511ca3 100644 --- a/ndb/include/ndbapi/NdbTransaction.hpp +++ b/ndb/include/ndbapi/NdbTransaction.hpp @@ -560,6 +560,11 @@ public: * ops are used (read, insert, update, delete). */ int executePendingBlobOps(Uint8 flags = 0xFF); + + /** + * Get nodeId of TC for this transaction + */ + Uint32 getConnectedNodeId(); // Get Connected node id #endif private: @@ -593,7 +598,6 @@ private: */ void setConnectedNodeId( Uint32 nodeId, Uint32 sequence); - Uint32 getConnectedNodeId(); // Get Connected node id void setMyBlockReference( int ); // Set my block refrerence void setTC_ConnectPtr( Uint32 ); // Sets TC Connect pointer int getTC_ConnectPtr(); // Gets TC Connect pointer diff --git a/ndb/include/ndbapi/ndb_cluster_connection.hpp b/ndb/include/ndbapi/ndb_cluster_connection.hpp index 2b59ff1a055..97db76563aa 100644 --- a/ndb/include/ndbapi/ndb_cluster_connection.hpp +++ b/ndb/include/ndbapi/ndb_cluster_connection.hpp @@ -86,6 +86,7 @@ public: void set_optimized_node_selection(int val); unsigned no_db_nodes(); + unsigned node_id(); #endif private: diff --git a/ndb/include/util/Base64.hpp b/ndb/include/util/Base64.hpp index 1156636eec8..f4b11ad9214 100644 --- a/ndb/include/util/Base64.hpp +++ b/ndb/include/util/Base64.hpp @@ -21,6 +21,7 @@ #include <BaseString.hpp> int base64_encode(const UtilBuffer &src, BaseString &dst); +int base64_encode(const void * s, size_t src_len, BaseString &dst); int base64_decode(const BaseString &src, UtilBuffer &dst); int base64_decode(const char * s, size_t len, UtilBuffer &dst); diff --git a/ndb/src/common/util/Base64.cpp b/ndb/src/common/util/Base64.cpp index f7a490d427d..3db911f481f 100644 --- a/ndb/src/common/util/Base64.cpp +++ b/ndb/src/common/util/Base64.cpp @@ -22,17 +22,22 @@ static char base64_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "0123456789+/"; int -base64_encode(const UtilBuffer &src, BaseString &dst) { - const unsigned char *s = (const unsigned char *)src.get_data(); +base64_encode(const UtilBuffer &src, BaseString &dst) +{ + return base64_encode(src.get_data(), src.length(), dst); +} + +int +base64_encode(const void * _s, size_t src_len, BaseString &dst) { + const unsigned char * s = (const unsigned char*)_s; size_t i = 0; size_t len = 0; - size_t src_len = src.length(); while(i < src_len) { if(len == 76){ len = 0; dst.append('\n'); } - + unsigned c; c = s[i++]; c <<= 8; diff --git a/ndb/src/kernel/blocks/ERROR_codes.txt b/ndb/src/kernel/blocks/ERROR_codes.txt index 5193d3eae9d..a30021607cc 100644 --- a/ndb/src/kernel/blocks/ERROR_codes.txt +++ b/ndb/src/kernel/blocks/ERROR_codes.txt @@ -196,6 +196,8 @@ Delay execution of ABORTREQ signal 2 seconds to generate time-out. 8048: Make TC not choose own node for simple/dirty read 5041: Crash is receiving simple read from other TC on different node +8050: Send TCKEYREF is operation is non local + ERROR CODES FOR TESTING TIME-OUT HANDLING IN DBTC ------------------------------------------------- 8040: @@ -409,6 +411,8 @@ Drop Table/Index: 8033: Fail next trigger create in TC 8034: Fail next index create in TC + + System Restart: --------------- diff --git a/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp b/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp index adae429e65d..b579c37c842 100644 --- a/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp +++ b/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp @@ -7475,6 +7475,22 @@ void Dbdih::execDIHNDBTAMPER(Signal* signal) #ifdef ERROR_INSERT case 5: jam(); + if(tuserpointer == 0) + { + jam(); + signal->theData[0] = 0; + sendSignal(QMGR_REF, GSN_NDB_TAMPER, signal, 1, JBB); + sendSignal(NDBCNTR_REF, GSN_NDB_TAMPER, signal, 1, JBB); + sendSignal(NDBFS_REF, GSN_NDB_TAMPER, signal, 1, JBB); + sendSignal(DBACC_REF, GSN_NDB_TAMPER, signal, 1, JBB); + sendSignal(DBTUP_REF, GSN_NDB_TAMPER, signal, 1, JBB); + sendSignal(DBLQH_REF, GSN_NDB_TAMPER, signal, 1, JBB); + sendSignal(DBDICT_REF, GSN_NDB_TAMPER, signal, 1, JBB); + sendSignal(DBDIH_REF, GSN_NDB_TAMPER, signal, 1, JBB); + sendSignal(DBTC_REF, GSN_NDB_TAMPER, signal, 1, JBB); + sendSignal(CMVMI_REF, GSN_NDB_TAMPER, signal, 1, JBB); + return; + } /*----------------------------------------------------------------------*/ // Insert errors. /*----------------------------------------------------------------------*/ diff --git a/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp b/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp index cf4bdaeebbc..ce38c355c91 100644 --- a/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp +++ b/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp @@ -3081,6 +3081,15 @@ void Dbtc::tckeyreq050Lab(Signal* signal) execDIGETNODESREF(signal); return; } + + if(ERROR_INSERTED(8050) && signal->theData[3] != getOwnNodeId()) + { + ndbassert(false); + signal->theData[1] = 626; + execDIGETNODESREF(signal); + return; + } + /****************>>*/ /* DIGETNODESCONF >*/ /* ***************>*/ diff --git a/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp b/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp index 06b2b3f4cb4..c3f85cdebd5 100644 --- a/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp +++ b/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp @@ -1001,6 +1001,13 @@ Dbtup::read_psuedo(Uint32 attrId, Uint32* outBuffer){ case AttributeHeader::FRAGMENT: * outBuffer = operPtr.p->fragId >> 1; // remove "hash" bit return 1; + case AttributeHeader::FRAGMENT_MEMORY: + { + Uint64 tmp= fragptr.p->noOfPages; + tmp*= 32768; + memcpy(outBuffer,&tmp,8); + } + return 2; case AttributeHeader::ROW_SIZE: * outBuffer = tabptr.p->tupheadsize << 2; return 1; diff --git a/ndb/src/ndbapi/NdbDictionary.cpp b/ndb/src/ndbapi/NdbDictionary.cpp index 4221c22121d..93a82e4bc83 100644 --- a/ndb/src/ndbapi/NdbDictionary.cpp +++ b/ndb/src/ndbapi/NdbDictionary.cpp @@ -231,6 +231,12 @@ NdbDictionary::Column::equal(const NdbDictionary::Column & col) const { return m_impl.equal(col.m_impl); } +int +NdbDictionary::Column::getSizeInBytes() const +{ + return m_impl.m_attrSize * m_impl.m_arraySize; +} + /***************************************************************** * Table facade */ @@ -426,13 +432,17 @@ NdbDictionary::Table::getRowSizeInBytes() const { int sz = 0; for(int i = 0; i<getNoOfColumns(); i++){ const NdbDictionary::Column * c = getColumn(i); - const NdbColumnImpl & col = NdbColumnImpl::getImpl(* c); - sz += (((col.m_attrSize * col.m_arraySize) + 3) / 4); + sz += (c->getSizeInBytes()+ 3) / 4; } return sz * 4; } int +NdbDictionary::Table::getReplicaCount() const { + return m_impl.m_replicaCount; +} + +int NdbDictionary::Table::createTableInDb(Ndb* pNdb, bool equalOk) const { const NdbDictionary::Table * pTab = pNdb->getDictionary()->getTable(getName()); @@ -1000,6 +1010,7 @@ operator<<(NdbOut& out, const NdbDictionary::Column& col) } const NdbDictionary::Column * NdbDictionary::Column::FRAGMENT = 0; +const NdbDictionary::Column * NdbDictionary::Column::FRAGMENT_MEMORY = 0; const NdbDictionary::Column * NdbDictionary::Column::ROW_COUNT = 0; const NdbDictionary::Column * NdbDictionary::Column::COMMIT_COUNT = 0; const NdbDictionary::Column * NdbDictionary::Column::ROW_SIZE = 0; diff --git a/ndb/src/ndbapi/NdbDictionaryImpl.cpp b/ndb/src/ndbapi/NdbDictionaryImpl.cpp index 4c53ac89461..1ae4263545e 100644 --- a/ndb/src/ndbapi/NdbDictionaryImpl.cpp +++ b/ndb/src/ndbapi/NdbDictionaryImpl.cpp @@ -232,6 +232,11 @@ NdbColumnImpl::create_psuedo(const char * name){ col->m_impl.m_attrId = AttributeHeader::FRAGMENT; col->m_impl.m_attrSize = 4; col->m_impl.m_arraySize = 1; + } else if(!strcmp(name, "NDB$FRAGMENT_MEMORY")){ + col->setType(NdbDictionary::Column::Bigunsigned); + col->m_impl.m_attrId = AttributeHeader::FRAGMENT_MEMORY; + col->m_impl.m_attrSize = 8; + col->m_impl.m_arraySize = 1; } else if(!strcmp(name, "NDB$ROW_COUNT")){ col->setType(NdbDictionary::Column::Bigunsigned); col->m_impl.m_attrId = AttributeHeader::ROW_COUNT; @@ -685,10 +690,12 @@ NdbDictionaryImpl::~NdbDictionaryImpl() m_globalHash->lock(); if(--f_dictionary_count == 0){ delete NdbDictionary::Column::FRAGMENT; + delete NdbDictionary::Column::FRAGMENT_MEMORY; delete NdbDictionary::Column::ROW_COUNT; delete NdbDictionary::Column::COMMIT_COUNT; delete NdbDictionary::Column::ROW_SIZE; NdbDictionary::Column::FRAGMENT= 0; + NdbDictionary::Column::FRAGMENT_MEMORY= 0; NdbDictionary::Column::ROW_COUNT= 0; NdbDictionary::Column::COMMIT_COUNT= 0; NdbDictionary::Column::ROW_SIZE= 0; @@ -754,6 +761,8 @@ NdbDictionaryImpl::setTransporter(class Ndb* ndb, if(f_dictionary_count++ == 0){ NdbDictionary::Column::FRAGMENT= NdbColumnImpl::create_psuedo("NDB$FRAGMENT"); + NdbDictionary::Column::FRAGMENT_MEMORY= + NdbColumnImpl::create_psuedo("NDB$FRAGMENT_MEMORY"); NdbDictionary::Column::ROW_COUNT= NdbColumnImpl::create_psuedo("NDB$ROW_COUNT"); NdbDictionary::Column::COMMIT_COUNT= @@ -1264,7 +1273,8 @@ NdbDictInterface::parseTableInfo(NdbTableImpl ** ret, Uint32 blobCount = 0; Uint32 distKeys = 0; - for(Uint32 i = 0; i < tableDesc.NoOfAttributes; i++) { + Uint32 i; + for(i = 0; i < tableDesc.NoOfAttributes; i++) { DictTabInfo::Attribute attrDesc; attrDesc.init(); s = SimpleProperties::unpack(it, &attrDesc, @@ -1348,7 +1358,6 @@ NdbDictInterface::parseTableInfo(NdbTableImpl ** ret, if(tableDesc.FragmentDataLen > 0) { - unsigned i; Uint32 replicaCount = tableDesc.FragmentData[0]; Uint32 fragCount = tableDesc.FragmentData[1]; @@ -1377,6 +1386,15 @@ NdbDictInterface::parseTableInfo(NdbTableImpl ** ret, impl->m_hashpointerValue = 0; } + if(distKeys == 0) + { + for(i = 0; i < tableDesc.NoOfAttributes; i++) + { + if(impl->m_columns[i]->getPrimaryKey()) + impl->m_columns[i]->m_distributionKey = true; + } + } + * ret = impl; DBUG_RETURN(0); @@ -1468,7 +1486,6 @@ int NdbDictionaryImpl::alterTable(NdbTableImpl &impl) BaseString internalName = impl.m_internalName; const char * originalInternalName = internalName.c_str(); BaseString externalName = impl.m_externalName; - const char * originalExternalName = externalName.c_str(); DBUG_ENTER("NdbDictionaryImpl::alterTable"); if(!get_local_table_info(originalInternalName, false)){ @@ -1705,11 +1722,12 @@ void NdbDictInterface::execCREATE_TABLE_CONF(NdbApiSignal * signal, LinearSectionPtr ptr[3]) { +#if 0 const CreateTableConf* const conf= CAST_CONSTPTR(CreateTableConf, signal->getDataPtr()); Uint32 tableId= conf->tableId; Uint32 tableVersion= conf->tableVersion; - +#endif m_waiter.signal(NO_WAIT); } diff --git a/ndb/src/ndbapi/NdbEventOperationImpl.cpp b/ndb/src/ndbapi/NdbEventOperationImpl.cpp index 44af495df51..9cea3ec83cd 100644 --- a/ndb/src/ndbapi/NdbEventOperationImpl.cpp +++ b/ndb/src/ndbapi/NdbEventOperationImpl.cpp @@ -224,9 +224,8 @@ NdbEventOperationImpl::execute() int hasSubscriber; - int r= - m_bufferHandle->prepareAddSubscribeEvent(m_eventImpl->m_eventId, - hasSubscriber /* return value */); + int r= m_bufferHandle->prepareAddSubscribeEvent(this, + hasSubscriber /*return value*/); m_error.code= 4709; if (r < 0) @@ -697,10 +696,11 @@ NdbGlobalEventBufferHandle::drop(NdbGlobalEventBufferHandle *handle) } */ int -NdbGlobalEventBufferHandle::prepareAddSubscribeEvent(Uint32 eventId, - int& hasSubscriber) +NdbGlobalEventBufferHandle::prepareAddSubscribeEvent +(NdbEventOperationImpl *eventOp, int& hasSubscriber) { - ADD_DROP_LOCK_GUARDR(int,real_prepareAddSubscribeEvent(this, eventId, hasSubscriber)); + ADD_DROP_LOCK_GUARDR(int,real_prepareAddSubscribeEvent(this, eventOp, + hasSubscriber)); } void NdbGlobalEventBufferHandle::addSubscribeEvent @@ -891,13 +891,15 @@ NdbGlobalEventBuffer::real_remove(NdbGlobalEventBufferHandle *h) exit(-1); } -int +int NdbGlobalEventBuffer::real_prepareAddSubscribeEvent -(NdbGlobalEventBufferHandle *aHandle, Uint32 eventId, int& hasSubscriber) +(NdbGlobalEventBufferHandle *aHandle, NdbEventOperationImpl *eventOp, + int& hasSubscriber) { DBUG_ENTER("NdbGlobalEventBuffer::real_prepareAddSubscribeEvent"); int i; int bufferId= -1; + Uint32 eventId= eventOp->m_eventId; // add_drop_lock(); // only one thread can do add or drop at a time @@ -939,6 +941,7 @@ found_bufferId: bufferId= NO_ID(0, bufferId); b.gId= eventId; + b.eventType= (Uint32)eventOp->m_eventImpl->mi_type; if ((b.p_buf_mutex= NdbMutex_Create()) == NULL) { ndbout_c("NdbGlobalEventBuffer: NdbMutex_Create() failed"); @@ -1137,6 +1140,8 @@ NdbGlobalEventBuffer::real_insertDataL(int bufferId, #ifdef EVENT_DEBUG int n = NO(bufferId); #endif + + if ( b.eventType & (1 << (Uint32)sdata->operation) ) { if (b.subs) { #ifdef EVENT_DEBUG @@ -1175,6 +1180,13 @@ NdbGlobalEventBuffer::real_insertDataL(int bufferId, #endif } } + else + { +#ifdef EVENT_DEBUG + ndbout_c("skipped"); +#endif + } + DBUG_RETURN(0); } diff --git a/ndb/src/ndbapi/NdbEventOperationImpl.hpp b/ndb/src/ndbapi/NdbEventOperationImpl.hpp index fae9dda45e4..3fcbfd8fe7c 100644 --- a/ndb/src/ndbapi/NdbEventOperationImpl.hpp +++ b/ndb/src/ndbapi/NdbEventOperationImpl.hpp @@ -79,7 +79,7 @@ public: //static NdbGlobalEventBufferHandle *init(int MAX_NUMBER_ACTIVE_EVENTS); // returns bufferId 0-N if ok otherwise -1 - int prepareAddSubscribeEvent(Uint32 eventId, int& hasSubscriber); + int prepareAddSubscribeEvent(NdbEventOperationImpl *, int& hasSubscriber); void unprepareAddSubscribeEvent(int bufferId); void addSubscribeEvent(int bufferId, NdbEventOperationImpl *ndbEventOperationImpl); @@ -133,7 +133,8 @@ private: int MAX_NUMBER_ACTIVE_EVENTS); int real_prepareAddSubscribeEvent(NdbGlobalEventBufferHandle *h, - Uint32 eventId, int& hasSubscriber); + NdbEventOperationImpl *, + int& hasSubscriber); void real_unprepareAddSubscribeEvent(int bufferId); void real_addSubscribeEvent(int bufferId, void *ndbEventOperation); @@ -177,6 +178,7 @@ private: // local mutex for each event/buffer NdbMutex *p_buf_mutex; Uint32 gId; + Uint32 eventType; struct Data { SubTableData *sdata; LinearSectionPtr ptr[3]; diff --git a/ndb/src/ndbapi/NdbOperation.cpp b/ndb/src/ndbapi/NdbOperation.cpp index 58147f2654e..c9143444908 100644 --- a/ndb/src/ndbapi/NdbOperation.cpp +++ b/ndb/src/ndbapi/NdbOperation.cpp @@ -392,3 +392,9 @@ NdbOperation::getTableName() const { return m_currentTable->m_externalName.c_str(); } + +const NdbDictionary::Table* +NdbOperation::getTable() const +{ + return m_currentTable; +} diff --git a/ndb/src/ndbapi/NdbOperationSearch.cpp b/ndb/src/ndbapi/NdbOperationSearch.cpp index 6e76287eef0..06d8ddd412b 100644 --- a/ndb/src/ndbapi/NdbOperationSearch.cpp +++ b/ndb/src/ndbapi/NdbOperationSearch.cpp @@ -229,9 +229,6 @@ NdbOperation::equal_impl(const NdbColumnImpl* tAttrInfo, theNoOfTupKeyLeft = tNoKeysDef; tErrorLine++; theErrorLine = tErrorLine; - - if(tDistrKey) - handle_distribution_key((Uint64*)aValue, totalSizeInWords); if (tNoKeysDef == 0) { if (tOpType == UpdateRequest) { diff --git a/ndb/src/ndbapi/ndb_cluster_connection.cpp b/ndb/src/ndbapi/ndb_cluster_connection.cpp index 2b3743e013a..aefcb0d97d0 100644 --- a/ndb/src/ndbapi/ndb_cluster_connection.cpp +++ b/ndb/src/ndbapi/ndb_cluster_connection.cpp @@ -183,6 +183,12 @@ Ndb_cluster_connection::no_db_nodes() return m_impl.m_all_nodes.size(); } +unsigned +Ndb_cluster_connection::node_id() +{ + return m_impl.m_transporter_facade->ownId(); +} + int Ndb_cluster_connection::wait_until_ready(int timeout, diff --git a/ndb/test/include/HugoCalculator.hpp b/ndb/test/include/HugoCalculator.hpp index 108af0d1358..03de46cd7ea 100644 --- a/ndb/test/include/HugoCalculator.hpp +++ b/ndb/test/include/HugoCalculator.hpp @@ -31,13 +31,6 @@ 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, int len) const; int verifyRowValues(NDBT_ResultRow* const pRow) const; diff --git a/ndb/test/include/HugoOperations.hpp b/ndb/test/include/HugoOperations.hpp index d7f336a117d..38e53d765ec 100644 --- a/ndb/test/include/HugoOperations.hpp +++ b/ndb/test/include/HugoOperations.hpp @@ -29,8 +29,9 @@ public: ~HugoOperations(); int startTransaction(Ndb*); + int setTransaction(NdbTransaction*); int closeTransaction(Ndb*); - NdbConnection* getTransaction(); + NdbTransaction* getTransaction(); void refresh(); int pkInsertRecord(Ndb*, @@ -68,10 +69,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, diff --git a/ndb/test/ndbapi/testPartitioning.cpp b/ndb/test/ndbapi/testPartitioning.cpp index c50921b85fc..9d67c27354b 100644 --- a/ndb/test/ndbapi/testPartitioning.cpp +++ b/ndb/test/ndbapi/testPartitioning.cpp @@ -318,8 +318,51 @@ run_startHint(NDBT_Context* ctx, NDBT_Step* step) { return NDBT_FAILED; } + + NdbRestarter restarter; + if(restarter.insertErrorInAllNodes(8050) != 0) + return NDBT_FAILED; - return NDBT_OK; + 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; } @@ -358,9 +401,18 @@ TESTCASE("ordered_index_dk", INITIALIZER(run_drop_table); } TESTCASE("startTransactionHint", - "Test startTransactionHint") + "Test startTransactionHint wo/ distribution key") { - TC_PROPERTY("distributionkey", ~0); + 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); diff --git a/ndb/test/run-test/atrt-mysql-test-run b/ndb/test/run-test/atrt-mysql-test-run index dd7b709bd06..c30a4defc7f 100755 --- a/ndb/test/run-test/atrt-mysql-test-run +++ b/ndb/test/run-test/atrt-mysql-test-run @@ -5,8 +5,8 @@ p=`pwd` cd $MYSQL_BASE_DIR/mysql-test ./mysql-test-run --with-ndbcluster --ndb-connectstring=$NDB_CONNECTSTRING $* | tee $p/output.txt -f=`grep -c fail $p/output.txt` -o=`grep -c pass $p/output.txt` +f=`grep -c '[ fail ]' $p/output.txt` +o=`grep -c '[ pass ]' $p/output.txt` if [ $o -gt 0 -a $f -eq 0 ] then diff --git a/ndb/test/src/HugoCalculator.cpp b/ndb/test/src/HugoCalculator.cpp index 675d0ac786a..8493388efbd 100644 --- a/ndb/test/src/HugoCalculator.cpp +++ b/ndb/test/src/HugoCalculator.cpp @@ -16,6 +16,7 @@ #include "HugoCalculator.hpp" #include <NDBT.hpp> +#include <Base64.hpp> /* ************************************************************* * HugoCalculator @@ -58,22 +59,11 @@ 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; @@ -82,58 +72,106 @@ 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, int len) const { - const char a[26] = {"UAWBORCTDPEFQGNYHISJMKXLZ"}; + unsigned seed; const NdbDictionary::Column* attr = m_tab.getColumn(attrib); - int val = calcValue(record, attrib, updates); - - 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 - BaseString::snprintf(buf, len, "%d", val); - for(int i=strlen(buf); i < len; i++) - buf[i] = a[((val^i)%25)]; - } else{ - - // 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<len; i++) - buf[i] = ((i+2) % 255); + Uint32 val; + do + { + if (attrib == m_idCol) + { + *((Uint32*)buf)= record; + return buf; + } - // Calculate length of the string to create. We want the string - // length to be varied between max and min of this attribute. - if(attr->getType() == NdbDictionary::Column::Varchar) - len = val % (len + 1); - else - if((val % (len + 1)) == 0) - len = 0; + // If this is the update column + if (attrib == m_updatesCol) + { + *((Uint32*)buf)= updates; + return buf; + } - // If len == 0 return NULL if this is a nullable attribute - if (len == 0){ - if(attr->getNullable() == true) - return NULL; - else - len++; + if (attr->getPrimaryKey()) + { + seed = record + attrib; } - for(i=0; i < len; i++) - buf[i] = a[((val^i)%25)]; - buf[len] = 0; - - if(attr->getType() == NdbDictionary::Column::Bit) + else { - Uint32 bits= attr->getLength(); - Uint32 pos = bits >> 5; - Uint32 size = bits & 31; - ((Uint32*)buf)[pos] &= ((1 << size) - 1); + seed = record + attrib + updates; } + } while (0); + val = rand_r(&seed); + + if(attr->getNullable() && (((val >> 16) & 255) > 220)) + return NULL; + + memcpy(buf, &val, (len > 4 ? 4 : len)); + int pos= 4; + while(pos + 4 < len) + { + val= rand_r(&seed); + memcpy(buf+pos, &val, 4); + pos++; + } + + if(pos < len) + { + val= rand_r(&seed); + memcpy(buf+pos, &val, (len - pos)); + } + + 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::Decimal: + case NdbDictionary::Column::Binary: + case NdbDictionary::Column::Datetime: + case NdbDictionary::Column::Time: + case NdbDictionary::Column::Date: + break; + case NdbDictionary::Column::Bit: + { + Uint32 bits= attr->getLength(); + Uint32 tmp = bits >> 5; + Uint32 size = bits & 31; + ((Uint32*)buf)[tmp] &= ((1 << size) - 1); + 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: + { + BaseString tmp; + base64_encode(buf, len, tmp); + memcpy(buf, tmp.c_str(), len); + break; + } + case NdbDictionary::Column::Blob: + case NdbDictionary::Column::Undefined: + abort(); + break; + } + + return buf; } @@ -148,93 +186,39 @@ HugoCalculator::verifyRowValues(NDBT_ResultRow* const pRow) const{ // 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); - Uint32 len = attr->getLength(); - switch (attr->getType()){ - case NdbDictionary::Column::Bit: - len = 4 * ((len + 31) >> 5); - case NdbDictionary::Column::Char: - case NdbDictionary::Column::Varchar: - case NdbDictionary::Column::Binary: - case NdbDictionary::Column::Varbinary:{ - char* buf = new char[len+1]; - 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){ - // if (memcmp(res, pRow->attributeStore(i)->aRef(), pRow->attributeStore(i)->getLength()) != 0){ - g_err << "Column: " << attr->getName() << endl; - const char* buf2 = pRow->attributeStore(i)->aRef(); - for (Uint32 j = 0; j < len; 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 << ":" << hex << (int)buf[j] << "[" << hex << (int)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; - } - 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 << 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; } - 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 << "|- The row: \"" << (* pRow) << "\"" << endl; - 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; - result = -1; - } - } - break; - case NdbDictionary::Column::Undefined: - default: - assert(0); - result = -1; - break; } } } diff --git a/ndb/test/src/HugoOperations.cpp b/ndb/test/src/HugoOperations.cpp index f670591fe9c..bdb4013600a 100644 --- a/ndb/test/src/HugoOperations.cpp +++ b/ndb/test/src/HugoOperations.cpp @@ -32,6 +32,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; +} + int HugoOperations::closeTransaction(Ndb* pNdb){ if (pTrans != NULL){ @@ -145,26 +158,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; } @@ -187,25 +211,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; } @@ -373,38 +382,11 @@ int HugoOperations::equalForAttr(NdbOperation* pOp, return NDBT_FAILED; } - int len = attr->getLength(); - switch (attr->getType()){ - case NdbDictionary::Column::Bit: - len = 4 * ((len + 31) >> 5); - 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, len)); - 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; - } - 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, @@ -414,47 +396,11 @@ int HugoOperations::setValueForAttr(NdbOperation* pOp, int check = -1; const NdbDictionary::Column* attr = tab.getColumn(attrId); - int len = attr->getLength(); - switch (attr->getType()){ - case NdbDictionary::Column::Bit: - len = 4 * ((len + 31) >> 5); - 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, len)); - 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; - } - 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 @@ -470,7 +416,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 @@ -480,7 +426,7 @@ HugoOperations::verifyUpdatesValue(int updatesValue, int _numRows){ continue; } } - + if(_numRows == 0){ g_err << "No rows -> Invalid updates value" << endl; return NDBT_FAILED; |