From da0ce3628b71fd937aade4cd7ae1c17574bc8d24 Mon Sep 17 00:00:00 2001 From: "lzhou/zhl@ts3-34.ts.cn.tlan" <> Date: Fri, 1 Dec 2006 20:57:07 +0000 Subject: [PATCH 01/40] BUG#22025 Return correct error message when transporter error occored --- .../ndb/src/common/debugger/EventLogger.cpp | 97 ++++++++++++++++++- 1 file changed, 93 insertions(+), 4 deletions(-) diff --git a/storage/ndb/src/common/debugger/EventLogger.cpp b/storage/ndb/src/common/debugger/EventLogger.cpp index db9b8417c0d..4f38c4ed681 100644 --- a/storage/ndb/src/common/debugger/EventLogger.cpp +++ b/storage/ndb/src/common/debugger/EventLogger.cpp @@ -527,11 +527,100 @@ void getTextUndoLogBlocked(QQQQ) { theData[1], theData[2]); } + void getTextTransporterError(QQQQ) { - BaseString::snprintf(m_text, m_text_len, - "Transporter to node %d reported error 0x%x", - theData[1], - theData[2]); + struct myTransporterError{ + int errorNum; + char errorString[256]; + }; + int i = 0; + int lenth = 0; + static const struct myTransporterError TransporterErrorString[]= + { + //TE_NO_ERROR = 0 + {0,"No error"}, + //TE_ERROR_CLOSING_SOCKET = 0x1 + {0x1,"Error found during closing of socket"}, + //TE_ERROR_IN_SELECT_BEFORE_ACCEPT = 0x2 + {0x2,"Error found before accept. The transporter will retry"}, + //TE_INVALID_MESSAGE_LENGTH = 0x3 | TE_DO_DISCONNECT + {0x3 | 0x8000,"Error found in message (invalid message length)"}, + //TE_INVALID_CHECKSUM = 0x4 | TE_DO_DISCONNECT + {0x4 | 0x8000,"Error found in message (checksum)"}, + //TE_COULD_NOT_CREATE_SOCKET = 0x5 + {0x5,"Error found while creating socket(can't create socket)"}, + //TE_COULD_NOT_BIND_SOCKET = 0x6 + {0x6,"Error found while binding server socket"}, + //TE_LISTEN_FAILED = 0x7 + {0x7,"Error found while listening to server socket"}, + //TE_ACCEPT_RETURN_ERROR = 0x8 + {0x8,"Error found during accept(accept return error)"}, + //TE_SHM_DISCONNECT = 0xb | TE_DO_DISCONNECT + {0xb | 0x8000,"The remote node has disconnected"}, + //TE_SHM_IPC_STAT = 0xc | TE_DO_DISCONNECT + {0xc | 0x8000,"Unable to check shm segment"}, + //TE_SHM_UNABLE_TO_CREATE_SEGMENT = 0xd + {0xd,"Unable to create shm segment"}, + //TE_SHM_UNABLE_TO_ATTACH_SEGMENT = 0xe + {0xe,"Unable to attach shm segment"}, + //TE_SHM_UNABLE_TO_REMOVE_SEGMENT = 0xf + {0xf,"Unable to remove shm segment"}, + //TE_TOO_SMALL_SIGID = 0x10 + {0x10,"Sig ID too small"}, + //TE_TOO_LARGE_SIGID = 0x11 + {0x11,"Sig ID too large"}, + //TE_WAIT_STACK_FULL = 0x12 | TE_DO_DISCONNECT + {0x12 | 0x8000,"Wait stack was full"}, + //TE_RECEIVE_BUFFER_FULL = 0x13 | TE_DO_DISCONNECT + {0x13 | 0x8000,"Receive buffer was full"}, + //TE_SIGNAL_LOST_SEND_BUFFER_FULL = 0x14 | TE_DO_DISCONNECT + {0x14 | 0x8000,"Send buffer was full,and trying to force send fails"}, + //TE_SIGNAL_LOST = 0x15 + {0x15,"Send failed for unknown reason(signal lost)"}, + //TE_SEND_BUFFER_FULL = 0x16 + {0x16,"The send buffer was full, but sleeping for a while solved"}, + //TE_SCI_LINK_ERROR = 0x0017 + {0x0017,"There is no link from this node to the switch"}, + //TE_SCI_UNABLE_TO_START_SEQUENCE = 0x18 | TE_DO_DISCONNECT + {0x18 | 0x8000,"Could not start a sequence, because system resources are exumed or no sequence has been created"}, + //TE_SCI_UNABLE_TO_REMOVE_SEQUENCE = 0x19 | TE_DO_DISCONNECT + {0x19 | 0x8000,"Could not remove a sequence"}, + //TE_SCI_UNABLE_TO_CREATE_SEQUENCE = 0x1a | TE_DO_DISCONNECT + {0x1a | 0x8000,"Could not create a sequence, because system resources are exempted. Must reboot"}, + //TE_SCI_UNRECOVERABLE_DATA_TFX_ERROR = 0x1b | TE_DO_DISCONNECT + {0x1b | 0x8000,"Tried to send data on redundant link but failed"}, + //TE_SCI_CANNOT_INIT_LOCALSEGMENT = 0x1c | TE_DO_DISCONNECT + {0x1c | 0x8000,"Cannot initialize local segment"}, + //TE_SCI_CANNOT_MAP_REMOTESEGMENT = 0x1d | TE_DO_DISCONNEC + {0x1d | 0x8000,"Cannot map remote segment"}, + //TE_SCI_UNABLE_TO_UNMAP_SEGMENT = 0x1e | TE_DO_DISCONNECT + {0x1e | 0x8000,"Cannot free the resources used by this segment (step 1)"}, + //TE_SCI_UNABLE_TO_REMOVE_SEGMENT = 0x1f | TE_DO_DISCONNEC + {0x1f | 0x8000,"Cannot free the resources used by this segment (step 2)"}, + //TE_SCI_UNABLE_TO_DISCONNECT_SEGMENT = 0x20 | TE_DO_DISCONNECT + {0x20 | 0x8000,"Cannot disconnect from a remote segment"}, + //TE_SHM_IPC_PERMANENT = 0x21 + {0x21,"Shm ipc Permanent error"}, + //TE_SCI_UNABLE_TO_CLOSE_CHANNEL = 0x22 + {0x22,"Unable to close the sci channel and the resources allocated"} + }; + + lenth = sizeof(TransporterErrorString)/sizeof(struct myTransporterError); + for(i=0; i Date: Wed, 6 Dec 2006 12:01:19 +0800 Subject: [PATCH 02/40] BUG#21715 mgm client command STATUS returns "not connected" for non-data nodes --- ndb/src/mgmclient/CommandInterpreter.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/ndb/src/mgmclient/CommandInterpreter.cpp b/ndb/src/mgmclient/CommandInterpreter.cpp index 65d5b038707..ea5dc218898 100644 --- a/ndb/src/mgmclient/CommandInterpreter.cpp +++ b/ndb/src/mgmclient/CommandInterpreter.cpp @@ -1627,6 +1627,18 @@ CommandInterpreter::executeStatus(int processId, ndbout << processId << ": Node not found" << endl; return -1; } + if (cl->node_states[i].node_type != NDB_MGM_NODE_TYPE_NDB){ + if (cl->node_states[i].version != 0){ + ndbout << "Node "<< cl->node_states[i].node_id <<": connected" ; + ndbout_c(" (Version %d.%d.%d)", + getMajor(version) , + getMinor(version), + getBuild(version)); + + }else + ndbout << "Node "<< cl->node_states[i].node_id <<": not connected" << endl; + return 0; + } status = cl->node_states[i].node_status; startPhase = cl->node_states[i].start_phase; version = cl->node_states[i].version; From 975908c1fb424c42aa558935a936dbf4b58ad0e4 Mon Sep 17 00:00:00 2001 From: "gni/root@dev3-221.dev.cn.tlan" <> Date: Thu, 14 Dec 2006 18:10:18 +0800 Subject: [PATCH 03/40] BUG #19146 If Backup parameters incorrectly set, the data nodes can't start. --- .../ndb/src/kernel/blocks/backup/Backup.cpp | 12 +++++++++++ .../ndb/src/kernel/blocks/dblqh/DblqhMain.cpp | 20 +++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/storage/ndb/src/kernel/blocks/backup/Backup.cpp b/storage/ndb/src/kernel/blocks/backup/Backup.cpp index 819255a79f5..a4117127789 100644 --- a/storage/ndb/src/kernel/blocks/backup/Backup.cpp +++ b/storage/ndb/src/kernel/blocks/backup/Backup.cpp @@ -2387,6 +2387,18 @@ Backup::defineBackupRef(Signal* signal, BackupRecordPtr ptr, Uint32 errCode) if(ptr.p->is_lcp()) { jam(); + if (ptr.p->ctlFilePtr == RNIL) { + ptr.p->m_gsn = GSN_DEFINE_BACKUP_REF; + ndbrequire(ptr.p->errorCode != 0); + DefineBackupRef* ref = (DefineBackupRef*)signal->getDataPtrSend(); + ref->backupId = ptr.p->backupId; + ref->backupPtr = ptr.i; + ref->errorCode = ptr.p->errorCode; + ref->nodeId = getOwnNodeId(); + sendSignal(ptr.p->masterRef, GSN_DEFINE_BACKUP_REF, signal, + DefineBackupRef::SignalLength, JBB); + return; + } BackupFilePtr filePtr LINT_SET_PTR; ptr.p->files.getPtr(filePtr, ptr.p->ctlFilePtr); diff --git a/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp b/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp index 53d7d98ae84..1527b0c499b 100644 --- a/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp +++ b/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp @@ -566,6 +566,26 @@ Dblqh::execDEFINE_BACKUP_REF(Signal* signal) { jamEntry(); m_backup_ptr = RNIL; + DefineBackupRef* ref = (DefineBackupRef*)signal->getDataPtrSend(); + int err_code = 0; + char * extra_msg = NULL; + + switch(ref->errorCode){ + case DefineBackupRef::Undefined: + case DefineBackupRef::FailedToSetupFsBuffers: + case DefineBackupRef::FailedToAllocateBuffers: + case DefineBackupRef::FailedToAllocateTables: + case DefineBackupRef::FailedAllocateTableMem: + case DefineBackupRef::FailedToAllocateFileRecord: + case DefineBackupRef::FailedToAllocateAttributeRecord: + case DefineBackupRef::FailedInsertFileHeader: + case DefineBackupRef::FailedInsertTableList: + jam(); + err_code = NDBD_EXIT_INVALID_CONFIG; + extra_msg = "Probably Backup parameters configuration error, Please consult the manual"; + progError(__LINE__, err_code, extra_msg); + } + sendsttorryLab(signal); } From 328a8ccaf6ad88fb6b5b5e5227ac24a039d406d3 Mon Sep 17 00:00:00 2001 From: "lzhou/zhl@dev3-63.dev.cn.tlan" <> Date: Fri, 15 Dec 2006 17:49:13 +0000 Subject: [PATCH 04/40] BUG#22261 remove global variable global_mgmt_server_check from ClusterMgr --- storage/ndb/src/mgmsrv/main.cpp | 4 ---- storage/ndb/src/ndbapi/ClusterMgr.cpp | 4 +--- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/storage/ndb/src/mgmsrv/main.cpp b/storage/ndb/src/mgmsrv/main.cpp index dd7f4680dff..3c843b52567 100644 --- a/storage/ndb/src/mgmsrv/main.cpp +++ b/storage/ndb/src/mgmsrv/main.cpp @@ -132,8 +132,6 @@ bool g_StopServer; bool g_RestartServer; extern EventLogger g_eventLogger; -extern int global_mgmt_server_check; - enum ndb_mgmd_options { OPT_INTERACTIVE = NDB_STD_OPTIONS_LAST, OPT_NO_NODEID_CHECKS, @@ -208,8 +206,6 @@ int main(int argc, char** argv) start: glob= new MgmGlobals; - global_mgmt_server_check = 1; - if (opt_interactive || opt_non_interactive || g_print_full_config) { diff --git a/storage/ndb/src/ndbapi/ClusterMgr.cpp b/storage/ndb/src/ndbapi/ClusterMgr.cpp index ef0bf51cc2b..47ef41043bd 100644 --- a/storage/ndb/src/ndbapi/ClusterMgr.cpp +++ b/storage/ndb/src/ndbapi/ClusterMgr.cpp @@ -361,8 +361,6 @@ ClusterMgr::execAPI_REGREQ(const Uint32 * theData){ theFacade.sendSignalUnCond(&signal, nodeId); } -int global_mgmt_server_check = 0; // set to one in mgmtsrvr main; - void ClusterMgr::execAPI_REGCONF(const Uint32 * theData){ const ApiRegConf * const apiRegConf = (ApiRegConf *)&theData[0]; @@ -380,7 +378,7 @@ ClusterMgr::execAPI_REGCONF(const Uint32 * theData){ if(node.m_info.m_version != apiRegConf->version){ node.m_info.m_version = apiRegConf->version; - if (global_mgmt_server_check == 1) + if(theNodes[theFacade.ownId()].m_info.m_type == NodeInfo::MGM) node.compatible = ndbCompatible_mgmt_ndb(NDB_VERSION, node.m_info.m_version); else From fcb0e53b758c13893fe110b57e4d026cf92acab2 Mon Sep 17 00:00:00 2001 From: "dli@dev3-164.dev.cn.tlan" <> Date: Fri, 22 Dec 2006 09:59:27 +0800 Subject: [PATCH 05/40] ndb - fixed for BUG#19896 Last_Errno: 4294967295, Error in Write_rows event: (error number 4 billion ?) fixed to use int instead of uint32 type to return last_slave_errno. --- sql/log_event.cc | 23 ++++++++++++++++++++--- sql/protocol.h | 2 ++ sql/slave.cc | 2 +- 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/sql/log_event.cc b/sql/log_event.cc index faff2cae48e..8813b243788 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -5485,9 +5485,26 @@ int Rows_log_event::exec_event(st_relay_log_info *rli) { if (!need_reopen) { - slave_print_msg(ERROR_LEVEL, rli, error, - "Error in %s event: when locking tables", - get_type_str()); + if (thd->query_error || thd->is_fatal_error) + { + /* + Error reporting borrowed from Query_log_event with many excessive + simplifications (we don't honour --slave-skip-errors) + */ + uint actual_error= thd->net.last_errno; + slave_print_msg(ERROR_LEVEL, rli, actual_error, + "Error '%s' in %s event: when locking tables", + (actual_error ? thd->net.last_error : + "unexpected success or fatal error"), + get_type_str()); + thd->is_fatal_error= 1; + } + else + { + slave_print_msg(ERROR_LEVEL, rli, error, + "Error in %s event: when locking tables", + get_type_str()); + } rli->clear_tables_to_lock(); DBUG_RETURN(error); } diff --git a/sql/protocol.h b/sql/protocol.h index 85c22724b74..f9305c2c896 100644 --- a/sql/protocol.h +++ b/sql/protocol.h @@ -59,6 +59,8 @@ public: String *storage_packet() { return packet; } inline void free() { packet->free(); } virtual bool write(); + inline bool store(int from) + { return store_long((longlong) from); } inline bool store(uint32 from) { return store_long((longlong) from); } inline bool store(longlong from) diff --git a/sql/slave.cc b/sql/slave.cc index 5d871a64347..5b338747397 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -2237,7 +2237,7 @@ bool show_master_info(THD* thd, MASTER_INFO* mi) rpl_filter->get_wild_ignore_table(&tmp); protocol->store(&tmp); - protocol->store((uint32) mi->rli.last_slave_errno); + protocol->store(mi->rli.last_slave_errno); protocol->store(mi->rli.last_slave_error, &my_charset_bin); protocol->store((uint32) mi->rli.slave_skip_counter); protocol->store((ulonglong) mi->rli.group_master_log_pos); From b5fa32f0c056c3afadb1ebb4d9b0445a504ce4f1 Mon Sep 17 00:00:00 2001 From: "jonas@eel.(none)" <> Date: Mon, 22 Jan 2007 22:05:56 +0100 Subject: [PATCH 06/40] ndb - bug#25286 - add some sanity check to marker/hash code to see that element isnt inserted twice into hashtable (if defined VM_TRACE or ERROR_INSERT) - allow REMOVE_MARKER_ORD to fail(dont find record) in release --- .../ndb/src/kernel/blocks/dblqh/DblqhMain.cpp | 14 +++++++++++--- .../ndb/src/kernel/blocks/dbtc/DbtcMain.cpp | 19 +++++++++++++++++++ 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp b/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp index 43961533ed9..20fb910e78a 100644 --- a/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp +++ b/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp @@ -2480,8 +2480,16 @@ Dblqh::execREMOVE_MARKER_ORD(Signal* signal) CommitAckMarkerPtr removedPtr; m_commitAckMarkerHash.remove(removedPtr, key); +#if defined VM_TRACE || defined ERROR_INSERT ndbrequire(removedPtr.i != RNIL); m_commitAckMarkerPool.release(removedPtr); +#else + if (removedPtr.i != RNIL) + { + jam(); + m_commitAckMarkerPool.release(removedPtr); + } +#endif #ifdef MARKER_TRACE ndbout_c("Rem marker[%.8x %.8x]", key.transid1, key.transid2); #endif @@ -3406,7 +3414,7 @@ void Dblqh::execLQHKEYREQ(Signal* signal) markerPtr.p->tcNodeId = tcNodeId; CommitAckMarkerPtr tmp; -#ifdef VM_TRACE +#if defined VM_TRACE || defined ERROR_INSERT #ifdef MARKER_TRACE ndbout_c("Add marker[%.8x %.8x]", markerPtr.p->transid1, markerPtr.p->transid2); #endif @@ -9630,7 +9638,7 @@ Uint32 Dblqh::initScanrec(const ScanFragReq* scanFragReq) active.add(scanptr); if(scanptr.p->scanKeyinfoFlag){ jam(); -#ifdef VM_TRACE +#if defined VM_TRACE || defined ERROR_INSERT ScanRecordPtr tmp; ndbrequire(!c_scanTakeOverHash.find(tmp, * scanptr.p)); #endif @@ -9754,7 +9762,7 @@ void Dblqh::finishScanrec(Signal* signal) scans.add(restart); if(restart.p->scanKeyinfoFlag){ jam(); -#ifdef VM_TRACE +#if defined VM_TRACE || defined ERROR_INSERT ScanRecordPtr tmp; ndbrequire(!c_scanTakeOverHash.find(tmp, * restart.p)); #endif diff --git a/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp b/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp index 7003f74b16f..11fc6681529 100644 --- a/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp +++ b/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp @@ -2825,6 +2825,12 @@ void Dbtc::execTCKEYREQ(Signal* signal) tmp.p->apiNodeId = refToNode(regApiPtr->ndbapiBlockref); tmp.p->apiConnectPtr = TapiIndex; tmp.p->noOfLqhs = 0; +#if defined VM_TRACE || defined ERROR_INSERT + { + CommitAckMarkerPtr check; + ndbrequire(!m_commitAckMarkerHash.find(check, *tmp.p)); + } +#endif m_commitAckMarkerHash.add(tmp); } } @@ -8115,6 +8121,13 @@ void Dbtc::initApiConnectFail(Signal* signal) tmp.p->noOfLqhs = 1; tmp.p->lqhNodeId[0] = tnodeid; tmp.p->apiConnectPtr = apiConnectptr.i; + +#if defined VM_TRACE || defined ERROR_INSERT + { + CommitAckMarkerPtr check; + ndbrequire(!m_commitAckMarkerHash.find(check, *tmp.p)); + } +#endif m_commitAckMarkerHash.add(tmp); } }//Dbtc::initApiConnectFail() @@ -8271,6 +8284,12 @@ void Dbtc::updateApiStateFail(Signal* signal) tmp.p->noOfLqhs = 1; tmp.p->lqhNodeId[0] = tnodeid; tmp.p->apiConnectPtr = apiConnectptr.i; +#if defined VM_TRACE || defined ERROR_INSERT + { + CommitAckMarkerPtr check; + ndbrequire(!m_commitAckMarkerHash.find(check, *tmp.p)); + } +#endif m_commitAckMarkerHash.add(tmp); } else { jam(); From 1e0418cfa2229e48a866c9583d4462943c92fca0 Mon Sep 17 00:00:00 2001 From: "jonas@eel.(none)" <> Date: Tue, 23 Jan 2007 19:27:55 +0100 Subject: [PATCH 07/40] ndb - bug#25794 Fix read after delete (in same op) - lqh, handling of attrinfo - tup, setup read for disk/varchar --- .../ndb/src/kernel/blocks/dblqh/DblqhMain.cpp | 19 ++++--- storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp | 3 +- .../kernel/blocks/dbtup/DbtupExecQuery.cpp | 14 +++-- storage/ndb/test/ndbapi/testBasic.cpp | 52 +++++++++++++++++++ .../ndb/test/run-test/daily-basic-tests.txt | 6 ++- 5 files changed, 80 insertions(+), 14 deletions(-) diff --git a/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp b/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp index 20fb910e78a..f59e858dd4d 100644 --- a/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp +++ b/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp @@ -3147,20 +3147,23 @@ void Dblqh::lqhAttrinfoLab(Signal* signal, Uint32* dataPtr, Uint32 length) { TcConnectionrec * const regTcPtr = tcConnectptr.p; if (regTcPtr->operation != ZREAD) { - if (regTcPtr->opExec != 1) { - if (saveTupattrbuf(signal, dataPtr, length) == ZOK) { - ; - } else { - jam(); + if (regTcPtr->operation != ZDELETE) + { + if (regTcPtr->opExec != 1) { + if (saveTupattrbuf(signal, dataPtr, length) == ZOK) { + ; + } else { + jam(); /* ------------------------------------------------------------------------- */ /* WE MIGHT BE WAITING FOR RESPONSE FROM SOME BLOCK HERE. THUS WE NEED TO */ /* GO THROUGH THE STATE MACHINE FOR THE OPERATION. */ /* ------------------------------------------------------------------------- */ - localAbortStateHandlerLab(signal); - return; + localAbortStateHandlerLab(signal); + return; + }//if }//if }//if - }//if + } c_tup->receive_attrinfo(signal, regTcPtr->tupConnectrec, dataPtr, length); }//Dblqh::lqhAttrinfoLab() diff --git a/storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp b/storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp index 02fa4e71d08..824338e4d03 100644 --- a/storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp +++ b/storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp @@ -1736,7 +1736,8 @@ private: Operationrec* regOperPtr, Fragrecord* regFragPtr, Tablerec* regTabPtr, - KeyReqStruct* req_struct); + KeyReqStruct* req_struct, + bool disk); //------------------------------------------------------------------ //------------------------------------------------------------------ diff --git a/storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp index 47f61132699..22338899aa8 100644 --- a/storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp +++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp @@ -815,7 +815,9 @@ void Dbtup::execTUPKEYREQ(Signal* signal) { jam(); if (handleDeleteReq(signal, regOperPtr, - regFragPtr, regTabPtr, &req_struct) == -1) { + regFragPtr, regTabPtr, + &req_struct, + disk_page != RNIL) == -1) { return; } /* @@ -1459,7 +1461,8 @@ int Dbtup::handleDeleteReq(Signal* signal, Operationrec* regOperPtr, Fragrecord* regFragPtr, Tablerec* regTabPtr, - KeyReqStruct *req_struct) + KeyReqStruct *req_struct, + bool disk) { // delete must set but not increment tupVersion if (!regOperPtr->is_first_operation()) @@ -1511,8 +1514,11 @@ int Dbtup::handleDeleteReq(Signal* signal, { return 0; } - - return handleReadReq(signal, regOperPtr, regTabPtr, req_struct); + + if (setup_read(req_struct, regOperPtr, regFragPtr, regTabPtr, disk)) + { + return handleReadReq(signal, regOperPtr, regTabPtr, req_struct); + } error: tupkeyErrorLab(signal); diff --git a/storage/ndb/test/ndbapi/testBasic.cpp b/storage/ndb/test/ndbapi/testBasic.cpp index 3c6ce7b7583..9c327118ceb 100644 --- a/storage/ndb/test/ndbapi/testBasic.cpp +++ b/storage/ndb/test/ndbapi/testBasic.cpp @@ -1273,6 +1273,52 @@ runBug25090(NDBT_Context* ctx, NDBT_Step* step){ return NDBT_OK; } +int +runDeleteRead(NDBT_Context* ctx, NDBT_Step* step){ + + Ndb* pNdb = GETNDB(step); + + const NdbDictionary::Table* tab = ctx->getTab(); + NDBT_ResultRow row(*ctx->getTab()); + HugoTransactions tmp(*ctx->getTab()); + + int a; + int loops = ctx->getNumLoops(); + const int rows = ctx->getNumRecords(); + + while (loops--) + { + NdbTransaction* pTrans = pNdb->startTransaction(); + NdbOperation* pOp = pTrans->getNdbOperation(tab->getName()); + pOp->deleteTuple(); + for(a = 0; agetNoOfColumns(); a++) + { + if (tab->getColumn(a)->getPrimaryKey() == true) + { + if(tmp.equalForAttr(pOp, a, 0) != 0) + { + ERR(pTrans->getNdbError()); + return NDBT_FAILED; + } + } + } + + // Define attributes to read + for(a = 0; agetNoOfColumns(); a++) + { + if((row.attributeStore(a) = pOp->getValue(tab->getColumn(a)->getName())) == 0) { + ERR(pTrans->getNdbError()); + return NDBT_FAILED; + } + } + + pTrans->execute(Commit); + pTrans->close(); + } + + return NDBT_OK; +} + NDBT_TESTSUITE(testBasic); TESTCASE("PkInsert", "Verify that we can insert and delete from this table using PK" @@ -1543,6 +1589,12 @@ TESTCASE("Bug25090", "Verify what happens when we fill the db" ){ STEP(runBug25090); } +TESTCASE("DeleteRead", + "Verify Delete+Read" ){ + INITIALIZER(runLoadTable); + INITIALIZER(runDeleteRead); + FINALIZER(runClearTable2); +} NDBT_TESTSUITE_END(testBasic); #if 0 diff --git a/storage/ndb/test/run-test/daily-basic-tests.txt b/storage/ndb/test/run-test/daily-basic-tests.txt index 8b69353d42d..8d2bf6704d7 100644 --- a/storage/ndb/test/run-test/daily-basic-tests.txt +++ b/storage/ndb/test/run-test/daily-basic-tests.txt @@ -79,6 +79,10 @@ max-time: 660 cmd: testBasic args: -n UpdateAndRead +max-time: 500 +cmd: testBasic +args: -n DeleteRead + max-time: 500 cmd: testBasic args: -n PkReadAndLocker T6 D1 D2 @@ -461,7 +465,7 @@ max-time: 500 cmd: testScan args: -n Bug24447 T1 -max-time: 500 +max-time: 1000 cmd: testScan args: -n ScanVariants From 6b738220d9b5a45154c4ae74a9c3e3ce3f67b628 Mon Sep 17 00:00:00 2001 From: "jonas@perch.ndb.mysql.com" <> Date: Sun, 28 Jan 2007 21:56:17 +0100 Subject: [PATCH 08/40] ndb - Fix so that node version is recomputed at node failure --- storage/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/storage/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp b/storage/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp index 81679d3e16a..77099533ecc 100644 --- a/storage/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp +++ b/storage/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp @@ -3526,8 +3526,10 @@ void Qmgr::execCOMMIT_FAILREQ(Signal* signal) nodePtr.p->phase = ZFAIL_CLOSING; nodePtr.p->failState = WAITING_FOR_NDB_FAILCONF; setNodeInfo(nodePtr.i).m_heartbeat_cnt= 0; + setNodeInfo(nodePtr.i).m_version = 0; c_clusterNodes.clear(nodePtr.i); }//for + recompute_version_info(NodeInfo::DB); /*----------------------------------------------------------------------*/ /* WE INFORM THE API'S WE HAVE CONNECTED ABOUT THE FAILED NODES. */ /*----------------------------------------------------------------------*/ From 0d1f39202dd32a7024bbc4071255c59dba7f57a0 Mon Sep 17 00:00:00 2001 From: "jonas@perch.ndb.mysql.com" <> Date: Tue, 30 Jan 2007 04:14:07 +0100 Subject: [PATCH 09/40] ndb - two small fixes for TC 1) use static syntax 2) fix attlen handling in unique index --- .../ndb/src/kernel/blocks/dbtc/DbtcMain.cpp | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp b/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp index 11fc6681529..bf8d97d27c1 100644 --- a/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp +++ b/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp @@ -2523,7 +2523,7 @@ void Dbtc::execTCKEYREQ(Signal* signal) ApiConnectRecord * const regApiPtr = &localApiConnectRecord[TapiIndex]; apiConnectptr.p = regApiPtr; - Uint32 TstartFlag = tcKeyReq->getStartFlag(Treqinfo); + Uint32 TstartFlag = TcKeyReq::getStartFlag(Treqinfo); Uint32 TexecFlag = TcKeyReq::getExecuteFlag(Treqinfo); Uint8 isIndexOp = regApiPtr->isIndexOp; @@ -2693,14 +2693,14 @@ void Dbtc::execTCKEYREQ(Signal* signal) /* */ /* ---------------------------------------------------------------------- */ - UintR TapiVersionNo = tcKeyReq->getAPIVersion(tcKeyReq->attrLen); + UintR TapiVersionNo = TcKeyReq::getAPIVersion(tcKeyReq->attrLen); UintR Tlqhkeyreqrec = regApiPtr->lqhkeyreqrec; regApiPtr->lqhkeyreqrec = Tlqhkeyreqrec + 1; regCachePtr->apiVersionNo = TapiVersionNo; UintR TapiConnectptrIndex = apiConnectptr.i; UintR TsenderData = tcKeyReq->senderData; - UintR TattrLen = tcKeyReq->getAttrinfoLen(tcKeyReq->attrLen); + UintR TattrLen = TcKeyReq::getAttrinfoLen(tcKeyReq->attrLen); UintR TattrinfoCount = c_counters.cattrinfoCount; regTcPtr->apiConnect = TapiConnectptrIndex; @@ -2726,15 +2726,15 @@ void Dbtc::execTCKEYREQ(Signal* signal) UintR TtabptrIndex = localTabptr.i; UintR TtableSchemaVersion = tcKeyReq->tableSchemaVersion; - Uint8 TOperationType = tcKeyReq->getOperationType(Treqinfo); + Uint8 TOperationType = TcKeyReq::getOperationType(Treqinfo); regCachePtr->tableref = TtabptrIndex; regCachePtr->schemaVersion = TtableSchemaVersion; regTcPtr->operation = TOperationType; - Uint8 TSimpleFlag = tcKeyReq->getSimpleFlag(Treqinfo); - Uint8 TDirtyFlag = tcKeyReq->getDirtyFlag(Treqinfo); - Uint8 TInterpretedFlag = tcKeyReq->getInterpretedFlag(Treqinfo); - Uint8 TDistrKeyFlag = tcKeyReq->getDistributionKeyFlag(Treqinfo); + Uint8 TSimpleFlag = TcKeyReq::getSimpleFlag(Treqinfo); + Uint8 TDirtyFlag = TcKeyReq::getDirtyFlag(Treqinfo); + Uint8 TInterpretedFlag = TcKeyReq::getInterpretedFlag(Treqinfo); + Uint8 TDistrKeyFlag = TcKeyReq::getDistributionKeyFlag(Treqinfo); Uint8 TNoDiskFlag = TcKeyReq::getNoDiskFlag(Treqinfo); Uint8 TexecuteFlag = TexecFlag; @@ -2750,10 +2750,10 @@ void Dbtc::execTCKEYREQ(Signal* signal) Uint32 TkeyIndex; Uint32* TOptionalDataPtr = (Uint32*)&tcKeyReq->scanInfo; { - Uint32 TDistrGHIndex = tcKeyReq->getScanIndFlag(Treqinfo); + Uint32 TDistrGHIndex = TcKeyReq::getScanIndFlag(Treqinfo); Uint32 TDistrKeyIndex = TDistrGHIndex; - Uint32 TscanInfo = tcKeyReq->getTakeOverScanInfo(TOptionalDataPtr[0]); + Uint32 TscanInfo = TcKeyReq::getTakeOverScanInfo(TOptionalDataPtr[0]); regCachePtr->scanTakeOverInd = TDistrGHIndex; regCachePtr->scanInfo = TscanInfo; @@ -2775,7 +2775,7 @@ void Dbtc::execTCKEYREQ(Signal* signal) regCachePtr->keydata[2] = Tdata3; regCachePtr->keydata[3] = Tdata4; - TkeyLength = tcKeyReq->getKeyLength(Treqinfo); + TkeyLength = TcKeyReq::getKeyLength(Treqinfo); Uint32 TAIDataIndex; if (TkeyLength > 8) { TAIDataIndex = TkeyIndex + 8; @@ -2788,7 +2788,7 @@ void Dbtc::execTCKEYREQ(Signal* signal) }//if Uint32* TAIDataPtr = &TOptionalDataPtr[TAIDataIndex]; - titcLenAiInTckeyreq = tcKeyReq->getAIInTcKeyReq(Treqinfo); + titcLenAiInTckeyreq = TcKeyReq::getAIInTcKeyReq(Treqinfo); regCachePtr->keylen = TkeyLength; regCachePtr->lenAiInTckeyreq = titcLenAiInTckeyreq; regCachePtr->currReclenAi = titcLenAiInTckeyreq; @@ -2859,14 +2859,14 @@ void Dbtc::execTCKEYREQ(Signal* signal) }//switch }//if - Uint32 TabortOption = tcKeyReq->getAbortOption(Treqinfo); + Uint32 TabortOption = TcKeyReq::getAbortOption(Treqinfo); regTcPtr->m_execAbortOption = TabortOption; /*------------------------------------------------------------------------- * Check error handling per operation * If CommitFlag is set state accordingly and check for early abort *------------------------------------------------------------------------*/ - if (tcKeyReq->getCommitFlag(Treqinfo) == 1) { + if (TcKeyReq::getCommitFlag(Treqinfo) == 1) { ndbrequire(TexecuteFlag); regApiPtr->apiConnectstate = CS_REC_COMMITTING; } else { @@ -11492,7 +11492,7 @@ void Dbtc::execTCINDXREQ(Signal* signal) // If operation is readTupleExclusive or updateTuple then read index // table with exclusive lock Uint32 indexLength = TcKeyReq::getKeyLength(tcIndxRequestInfo); - Uint32 attrLength = tcIndxReq->attrLen; + Uint32 attrLength = TcKeyReq::getAttrinfoLen(tcIndxReq->attrLen); indexOp->expectedKeyInfo = indexLength; Uint32 includedIndexLength = MIN(indexLength, indexBufSize); indexOp->expectedAttrInfo = attrLength; From 5f50de1ad0e1d3ed6c11a7f8169de66afffe6df2 Mon Sep 17 00:00:00 2001 From: "tomas@poseidon.mysql.com" <> Date: Tue, 30 Jan 2007 11:52:37 +0700 Subject: [PATCH 10/40] ndb - added extra valgrind memleak checks to try to track leak --- sql/ha_ndbcluster_binlog.cc | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/sql/ha_ndbcluster_binlog.cc b/sql/ha_ndbcluster_binlog.cc index 38b640d5f55..cab1a7850ee 100644 --- a/sql/ha_ndbcluster_binlog.cc +++ b/sql/ha_ndbcluster_binlog.cc @@ -19,6 +19,10 @@ #ifdef WITH_NDBCLUSTER_STORAGE_ENGINE #include "ha_ndbcluster.h" +#ifdef HAVE_purify +#include +#endif + #ifdef HAVE_NDB_BINLOG #include "rpl_injector.h" #include "rpl_filter.h" @@ -3488,6 +3492,9 @@ pthread_handler_t ndb_binlog_thread_func(void *arg) pthread_cond_signal(&injector_cond); restart: +#ifdef HAVE_purify + VALGRIND_DO_LEAK_CHECK; +#endif /* Main NDB Injector loop */ @@ -3580,6 +3587,9 @@ restart: } } } +#ifdef HAVE_purify + VALGRIND_DO_LEAK_CHECK; +#endif { static char db[]= ""; thd->db= db; @@ -3946,6 +3956,9 @@ restart: goto restart; } err: +#ifdef HAVE_purify + VALGRIND_DO_LEAK_CHECK; +#endif sql_print_information("Stopping Cluster Binlog"); DBUG_PRINT("info",("Shutting down cluster binlog thread")); thd->proc_info= "Shutting down"; From 9755609b7b61644be723d256ccd69a3347b62946 Mon Sep 17 00:00:00 2001 From: "Justin.He/justin.he@dev3-240.dev.cn.tlan" <> Date: Tue, 30 Jan 2007 13:05:40 +0800 Subject: [PATCH 11/40] Bug#23546, Cluster configured without any arbitration --- storage/ndb/src/mgmsrv/ConfigInfo.cpp | 148 ++++++++++++++------------ 1 file changed, 78 insertions(+), 70 deletions(-) diff --git a/storage/ndb/src/mgmsrv/ConfigInfo.cpp b/storage/ndb/src/mgmsrv/ConfigInfo.cpp index def349cf744..9321028b3f8 100644 --- a/storage/ndb/src/mgmsrv/ConfigInfo.cpp +++ b/storage/ndb/src/mgmsrv/ConfigInfo.cpp @@ -3604,6 +3604,7 @@ check_node_vs_replicas(Vector§ions, Uint32 db_nodes= 0; Uint32 replicas= 0; Uint32 db_host_count= 0; + bool with_arbitration_rank= false; ctx.m_userProperties.get(DB_TOKEN, &db_nodes); ctx.m_userProperties.get("NoOfReplicas", &replicas); if((db_nodes % replicas) != 0){ @@ -3639,83 +3640,90 @@ check_node_vs_replicas(Vector§ions, tmp->get("HostName", &host); if (strcmp(type,DB_TOKEN) == 0) - { - { - Uint32 ii; - if (!p_db_hosts.get(host,&ii)) - db_host_count++; - p_db_hosts.put(host,i); - if (p_arbitrators.get(host,&ii)) - { - arbitration_warning.appfmt(arbit_warn_fmt, ii, i, host); - p_arbitrators.remove(host); // only one warning per db node - } - } - { - unsigned j; - BaseString str, str2; - str.assfmt("#group%d_",group); - p_db_hosts.put(str.c_str(),i_group,host); - str2.assfmt("##group%d_",group); - p_db_hosts.put(str2.c_str(),i_group,i); - for (j= 0; j < i_group; j++) - { - const char *other_host; - p_db_hosts.get(str.c_str(),j,&other_host); - if (strcmp(host,other_host) == 0) { - unsigned int other_i, c= 0; - p_db_hosts.get(str2.c_str(),j,&other_i); - p_db_hosts.get(str.c_str(),&c); - if (c == 0) // first warning in this node group - node_group_warning.appfmt(" Node group %d", group); - c|= 1 << j; - p_db_hosts.put(str.c_str(),c); - - node_group_warning.appfmt(",\n db node with id %d and id %d " - "on same host %s", other_i, i, host); - } - } - i_group++; - DBUG_ASSERT(i_group <= replicas); - if (i_group == replicas) - { - unsigned c= 0; - p_db_hosts.get(str.c_str(),&c); - if (c+1 == (1u << (replicas-1))) // all nodes on same machine - node_group_warning.append(".\n Host failure will " - "cause complete cluster shutdown."); - else if (c > 0) - node_group_warning.append(".\n Host failure may " - "cause complete cluster shutdown."); - group++; - i_group= 0; - } - } + { + { + Uint32 ii; + if (!p_db_hosts.get(host,&ii)) + db_host_count++; + p_db_hosts.put(host,i); + if (p_arbitrators.get(host,&ii)) + { + arbitration_warning.appfmt(arbit_warn_fmt, ii, i, host); + p_arbitrators.remove(host); // only one warning per db node + } + } + { + unsigned j; + BaseString str, str2; + str.assfmt("#group%d_",group); + p_db_hosts.put(str.c_str(),i_group,host); + str2.assfmt("##group%d_",group); + p_db_hosts.put(str2.c_str(),i_group,i); + for (j= 0; j < i_group; j++) + { + const char *other_host; + p_db_hosts.get(str.c_str(),j,&other_host); + if (strcmp(host,other_host) == 0) { + unsigned int other_i, c= 0; + p_db_hosts.get(str2.c_str(),j,&other_i); + p_db_hosts.get(str.c_str(),&c); + if (c == 0) // first warning in this node group + node_group_warning.appfmt(" Node group %d", group); + c|= 1 << j; + p_db_hosts.put(str.c_str(),c); + node_group_warning.appfmt(",\n db node with id %d and id %d " + "on same host %s", other_i, i, host); + } + } + i_group++; + DBUG_ASSERT(i_group <= replicas); + if (i_group == replicas) + { + unsigned c= 0; + p_db_hosts.get(str.c_str(),&c); + if (c+1 == (1u << (replicas-1))) // all nodes on same machine + node_group_warning.append(".\n Host failure will " + "cause complete cluster shutdown."); + else if (c > 0) + node_group_warning.append(".\n Host failure may " + "cause complete cluster shutdown."); + group++; + i_group= 0; + } + } } else if (strcmp(type,API_TOKEN) == 0 || strcmp(type,MGM_TOKEN) == 0) - { - Uint32 rank; - if(tmp->get("ArbitrationRank", &rank) && rank > 0) - { - if(host && host[0] != 0) - { - Uint32 ii; - p_arbitrators.put(host,i); - if (p_db_hosts.get(host,&ii)) - { - arbitration_warning.appfmt(arbit_warn_fmt, i, ii, host); - } - } - else - { - arbitration_warning.appfmt(arbit_warn_fmt2, i); - } - } + { + Uint32 rank; + if(tmp->get("ArbitrationRank", &rank) && rank > 0) + { + with_arbitration_rank = true; //check whether MGM or API node configured with rank >0 + if(host && host[0] != 0) + { + Uint32 ii; + p_arbitrators.put(host,i); + if (p_db_hosts.get(host,&ii)) + { + arbitration_warning.appfmt(arbit_warn_fmt, i, ii, host); + } + } + else + { + arbitration_warning.appfmt(arbit_warn_fmt2, i); + } + } } } if (db_host_count > 1 && node_group_warning.length() > 0) ndbout_c("Cluster configuration warning:\n%s",node_group_warning.c_str()); + if (!with_arbitration_rank) + { + ndbout_c("Cluster configuration warning:" + "\n Neither %s nor %s nodes are configured with arbitrator," + "\n may cause complete cluster shutdown in case of host failure.", + MGM_TOKEN, API_TOKEN); + } if (db_host_count > 1 && arbitration_warning.length() > 0) ndbout_c("Cluster configuration warning:%s%s",arbitration_warning.c_str(), "\n Running arbitrator on the same host as a database node may" From bfb0614175f6a02341ce3c811d2423e85ce38ed3 Mon Sep 17 00:00:00 2001 From: "tomas@poseidon.mysql.com" <> Date: Tue, 30 Jan 2007 15:43:55 +0700 Subject: [PATCH 12/40] valgrind leak - no injected events if operation is not connected - remove extra valgrind checks --- sql/ha_ndbcluster_binlog.cc | 13 ----- .../ndb/src/ndbapi/NdbEventOperationImpl.cpp | 54 ++++++++++--------- 2 files changed, 28 insertions(+), 39 deletions(-) diff --git a/sql/ha_ndbcluster_binlog.cc b/sql/ha_ndbcluster_binlog.cc index cab1a7850ee..38b640d5f55 100644 --- a/sql/ha_ndbcluster_binlog.cc +++ b/sql/ha_ndbcluster_binlog.cc @@ -19,10 +19,6 @@ #ifdef WITH_NDBCLUSTER_STORAGE_ENGINE #include "ha_ndbcluster.h" -#ifdef HAVE_purify -#include -#endif - #ifdef HAVE_NDB_BINLOG #include "rpl_injector.h" #include "rpl_filter.h" @@ -3492,9 +3488,6 @@ pthread_handler_t ndb_binlog_thread_func(void *arg) pthread_cond_signal(&injector_cond); restart: -#ifdef HAVE_purify - VALGRIND_DO_LEAK_CHECK; -#endif /* Main NDB Injector loop */ @@ -3587,9 +3580,6 @@ restart: } } } -#ifdef HAVE_purify - VALGRIND_DO_LEAK_CHECK; -#endif { static char db[]= ""; thd->db= db; @@ -3956,9 +3946,6 @@ restart: goto restart; } err: -#ifdef HAVE_purify - VALGRIND_DO_LEAK_CHECK; -#endif sql_print_information("Stopping Cluster Binlog"); DBUG_PRINT("info",("Shutting down cluster binlog thread")); thd->proc_info= "Shutting down"; diff --git a/storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp b/storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp index 828ba51bc21..7a0ceebe54a 100644 --- a/storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp +++ b/storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp @@ -1611,17 +1611,24 @@ NdbEventBuffer::insert_event(NdbEventOperationImpl* impl, Uint32 &oid_ref) { NdbEventOperationImpl *dropped_ev_op = m_dropped_ev_op; + DBUG_PRINT("info", ("gci: %u", data.gci)); do { do { - oid_ref = impl->m_oid; - insertDataL(impl, &data, ptr); + if (impl->m_node_bit_mask.get(0u)) + { + oid_ref = impl->m_oid; + insertDataL(impl, &data, ptr); + } NdbEventOperationImpl* blob_op = impl->theBlobOpList; while (blob_op != NULL) { - oid_ref = blob_op->m_oid; - insertDataL(blob_op, &data, ptr); + if (blob_op->m_node_bit_mask.get(0u)) + { + oid_ref = blob_op->m_oid; + insertDataL(blob_op, &data, ptr); + } blob_op = blob_op->m_next; } } while((impl = impl->m_next)); @@ -1806,6 +1813,7 @@ NdbEventBuffer::insertDataL(NdbEventOperationImpl *op, switch (operation) { case NdbDictionary::Event::_TE_NODE_FAILURE: + DBUG_ASSERT(op->m_node_bit_mask.get(0u) != 0); op->m_node_bit_mask.clear(SubTableData::getNdbdNodeId(ri)); DBUG_PRINT("info", ("_TE_NODE_FAILURE: m_ref_count: %u for op: %p id: %u", @@ -1821,29 +1829,23 @@ NdbEventBuffer::insertDataL(NdbEventOperationImpl *op, DBUG_RETURN_EVENT(0); break; case NdbDictionary::Event::_TE_CLUSTER_FAILURE: - if (op->m_node_bit_mask.get(0)) + DBUG_ASSERT(op->m_node_bit_mask.get(0u) != 0); + op->m_node_bit_mask.clear(); + DBUG_ASSERT(op->m_ref_count > 0); + // remove kernel reference + // added in execute_nolock + op->m_ref_count--; + DBUG_PRINT("info", ("_TE_CLUSTER_FAILURE: m_ref_count: %u for op: %p", + op->m_ref_count, op)); + if (op->theMainOp) { - op->m_node_bit_mask.clear(); - DBUG_ASSERT(op->m_ref_count > 0); - // remove kernel reference - // added in execute_nolock - op->m_ref_count--; - DBUG_PRINT("info", ("_TE_CLUSTER_FAILURE: m_ref_count: %u for op: %p", - op->m_ref_count, op)); - if (op->theMainOp) - { - DBUG_ASSERT(op->m_ref_count == 0); - DBUG_ASSERT(op->theMainOp->m_ref_count > 0); - // remove blob reference in main op - // added in execute_no_lock - op->theMainOp->m_ref_count--; - DBUG_PRINT("info", ("m_ref_count: %u for op: %p", - op->theMainOp->m_ref_count, op->theMainOp)); - } - } - else - { - DBUG_ASSERT(op->m_node_bit_mask.isclear() != 0); + DBUG_ASSERT(op->m_ref_count == 0); + DBUG_ASSERT(op->theMainOp->m_ref_count > 0); + // remove blob reference in main op + // added in execute_no_lock + op->theMainOp->m_ref_count--; + DBUG_PRINT("info", ("m_ref_count: %u for op: %p", + op->theMainOp->m_ref_count, op->theMainOp)); } break; case NdbDictionary::Event::_TE_STOP: From 3a3ed7565577c745ccee4751c6b309a7680e6dfd Mon Sep 17 00:00:00 2001 From: "jonas@perch.ndb.mysql.com" <> Date: Tue, 30 Jan 2007 19:26:40 +0100 Subject: [PATCH 13/40] ndb - minor style fixes --- storage/ndb/src/ndbapi/Ndb.cpp | 8 ++++---- storage/ndb/test/ndbapi/testBlobs.cpp | 7 ++++--- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/storage/ndb/src/ndbapi/Ndb.cpp b/storage/ndb/src/ndbapi/Ndb.cpp index ca5fd07d724..86007137adf 100644 --- a/storage/ndb/src/ndbapi/Ndb.cpp +++ b/storage/ndb/src/ndbapi/Ndb.cpp @@ -1078,7 +1078,7 @@ Ndb::opTupleIdOnNdb(const NdbTableImpl* table, tOperation->incValue("NEXTID", opValue); tRecAttrResult = tOperation->getValue("NEXTID"); - if (tConnection->execute( Commit ) == -1 ) + if (tConnection->execute( NdbTransaction::Commit ) == -1 ) goto error_handler; tValue = tRecAttrResult->u_64_value(); @@ -1093,7 +1093,7 @@ Ndb::opTupleIdOnNdb(const NdbTableImpl* table, tOperation->equal("SYSKEY_0", aTableId ); tOperation->setValue("NEXTID", opValue); - if (tConnection->execute( Commit ) == -1 ) + if (tConnection->execute( NdbTransaction::Commit ) == -1 ) goto error_handler; range.reset(); @@ -1110,7 +1110,7 @@ Ndb::opTupleIdOnNdb(const NdbTableImpl* table, tOperation->def_label(0); tOperation->interpret_exit_nok(9999); - if (tConnection->execute( Commit ) == -1) + if (tConnection->execute( NdbTransaction::Commit ) == -1) { if (tConnection->theError.code != 9999) goto error_handler; @@ -1127,7 +1127,7 @@ Ndb::opTupleIdOnNdb(const NdbTableImpl* table, tOperation->readTuple(); tOperation->equal("SYSKEY_0", aTableId ); tRecAttrResult = tOperation->getValue("NEXTID"); - if (tConnection->execute( Commit ) == -1 ) + if (tConnection->execute( NdbTransaction::Commit ) == -1 ) goto error_handler; opValue = tRecAttrResult->u_64_value(); // out break; diff --git a/storage/ndb/test/ndbapi/testBlobs.cpp b/storage/ndb/test/ndbapi/testBlobs.cpp index fae3a662ff9..189d69fd3ec 100644 --- a/storage/ndb/test/ndbapi/testBlobs.cpp +++ b/storage/ndb/test/ndbapi/testBlobs.cpp @@ -735,7 +735,7 @@ verifyHeadInline(const Tup& tup) if (! g_opt.m_oneblob) CHK((ra2 = g_opr->getValue("BL2")) != 0); if (tup.m_exists) { - CHK(g_con->execute(Commit) == 0); + CHK(g_con->execute(Commit, AbortOnError) == 0); DBG("verifyHeadInline BL1"); CHK(verifyHeadInline(g_opt.m_blob1, tup.m_blob1, ra1) == 0); if (! g_opt.m_oneblob) { @@ -743,7 +743,8 @@ verifyHeadInline(const Tup& tup) CHK(verifyHeadInline(g_opt.m_blob2, tup.m_blob2, ra2) == 0); } } else { - CHK(g_con->execute(Commit) == -1 && g_con->getNdbError().code == 626); + CHK(g_con->execute(Commit, AbortOnError) == -1 && + g_con->getNdbError().code == 626); } g_ndb->closeTransaction(g_con); g_opr = 0; @@ -1535,7 +1536,7 @@ testperf() g_dic = g_ndb->getDictionary(); NdbDictionary::Table tab(g_opt.m_tnameperf); if (g_dic->getTable(tab.getName()) != 0) - CHK(g_dic->dropTable(tab) == 0); + CHK(g_dic->dropTable(tab.getName()) == 0); // col A - pk { NdbDictionary::Column col("A"); col.setType(NdbDictionary::Column::Unsigned); From 7d54ea6b498c2b981095f2b4f574f0e737fcc5fd Mon Sep 17 00:00:00 2001 From: "jonas@perch.ndb.mysql.com" <> Date: Tue, 30 Jan 2007 19:28:32 +0100 Subject: [PATCH 14/40] ndb - remove copy/paste method in NdbIndexOperation --- .../ndb/include/ndbapi/NdbIndexOperation.hpp | 2 - storage/ndb/src/ndbapi/NdbIndexOperation.cpp | 233 ------------------ 2 files changed, 235 deletions(-) diff --git a/storage/ndb/include/ndbapi/NdbIndexOperation.hpp b/storage/ndb/include/ndbapi/NdbIndexOperation.hpp index d16cd071f77..fbc2b7f5d9d 100644 --- a/storage/ndb/include/ndbapi/NdbIndexOperation.hpp +++ b/storage/ndb/include/ndbapi/NdbIndexOperation.hpp @@ -182,8 +182,6 @@ private: const class NdbTableImpl* aTable, NdbTransaction*); - int prepareSend(Uint32 TC_ConnectPtr, Uint64 TransactionId); - // Private attributes const NdbIndexImpl* m_theIndex; friend struct Ndb_free_list_t; diff --git a/storage/ndb/src/ndbapi/NdbIndexOperation.cpp b/storage/ndb/src/ndbapi/NdbIndexOperation.cpp index 9faf66a1e98..e6332a28dd9 100644 --- a/storage/ndb/src/ndbapi/NdbIndexOperation.cpp +++ b/storage/ndb/src/ndbapi/NdbIndexOperation.cpp @@ -173,239 +173,6 @@ NdbIndexOperation::getIndex() const return m_theIndex; } -int -NdbIndexOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64 aTransactionId) -{ - Uint32 tTransId1, tTransId2; - Uint32 tReqInfo; - Uint32 tSignalCount = 0; - Uint32 tInterpretInd = theInterpretIndicator; - - theErrorLine = 0; - - if (tInterpretInd != 1) { - OperationType tOpType = theOperationType; - OperationStatus tStatus = theStatus; - if ((tOpType == UpdateRequest) || - (tOpType == InsertRequest) || - (tOpType == WriteRequest)) { - if (tStatus != SetValue) { - setErrorCodeAbort(4506); - return -1; - }//if - } else if ((tOpType == ReadRequest) || (tOpType == ReadExclusive) || - (tOpType == DeleteRequest)) { - if (tStatus != GetValue) { - setErrorCodeAbort(4506); - return -1; - }//if - } else { - setErrorCodeAbort(4507); - return -1; - }//if - } else { - if (prepareSendInterpreted() == -1) { - return -1; - }//if - }//if - -//------------------------------------------------------------- -// We start by filling in the first 8 unconditional words of the -// TCINDXREQ signal. -//------------------------------------------------------------- - TcKeyReq * tcKeyReq = - CAST_PTR(TcKeyReq, theTCREQ->getDataPtrSend()); - - Uint32 tTotalCurrAI_Len = theTotalCurrAI_Len; - Uint32 tIndexId = m_theIndex->m_id; - Uint32 tSchemaVersion = m_theIndex->m_version; - - tcKeyReq->apiConnectPtr = aTC_ConnectPtr; - tcKeyReq->senderData = ptr2int(); - tcKeyReq->attrLen = tTotalCurrAI_Len; - tcKeyReq->tableId = tIndexId; - tcKeyReq->tableSchemaVersion = tSchemaVersion; - - tTransId1 = (Uint32) aTransactionId; - tTransId2 = (Uint32) (aTransactionId >> 32); - -//------------------------------------------------------------- -// Simple is simple if simple or both start and commit is set. -//------------------------------------------------------------- -// Temporarily disable simple stuff - Uint8 tSimpleIndicator = 0; -// Uint8 tSimpleIndicator = theSimpleIndicator; - Uint8 tCommitIndicator = theCommitIndicator; - Uint8 tStartIndicator = theStartIndicator; -// if ((theNdbCon->theLastOpInList == this) && (theCommitIndicator == 0)) -// abort(); -// Temporarily disable simple stuff - Uint8 tSimpleAlt = 0; -// Uint8 tSimpleAlt = tStartIndicator & tCommitIndicator; - tSimpleIndicator = tSimpleIndicator | tSimpleAlt; - -//------------------------------------------------------------- -// Simple state is set if start and commit is set and it is -// a read request. Otherwise it is set to zero. -//------------------------------------------------------------- - Uint8 tReadInd = (theOperationType == ReadRequest); - Uint8 tSimpleState = tReadInd & tSimpleAlt; - //theNdbCon->theSimpleState = tSimpleState; - - tcKeyReq->transId1 = tTransId1; - tcKeyReq->transId2 = tTransId2; - - tReqInfo = 0; - - if (tTotalCurrAI_Len <= TcKeyReq::MaxAttrInfo) { - tcKeyReq->setAIInTcKeyReq(tReqInfo, tTotalCurrAI_Len); - } else { - tcKeyReq->setAIInTcKeyReq(tReqInfo, TcKeyReq::MaxAttrInfo); - }//if - - tcKeyReq->setSimpleFlag(tReqInfo, tSimpleIndicator); - tcKeyReq->setCommitFlag(tReqInfo, tCommitIndicator); - tcKeyReq->setStartFlag(tReqInfo, tStartIndicator); - const Uint8 tInterpretIndicator = theInterpretIndicator; - tcKeyReq->setInterpretedFlag(tReqInfo, tInterpretIndicator); - - Uint8 tDirtyIndicator = theDirtyIndicator; - OperationType tOperationType = theOperationType; - Uint32 tIndexLen = theTupKeyLen; - Uint8 abortOption = theNdbCon->m_abortOption; - - tcKeyReq->setDirtyFlag(tReqInfo, tDirtyIndicator); - tcKeyReq->setOperationType(tReqInfo, tOperationType); - tcKeyReq->setKeyLength(tReqInfo, tIndexLen); - tcKeyReq->setAbortOption(tReqInfo, abortOption); - - Uint8 tDistrKeyIndicator = theDistrKeyIndicator_; - Uint8 tScanIndicator = theScanInfo & 1; - - tcKeyReq->setDistributionKeyFlag(tReqInfo, tDistrKeyIndicator); - tcKeyReq->setScanIndFlag(tReqInfo, tScanIndicator); - - tcKeyReq->requestInfo = tReqInfo; - -//------------------------------------------------------------- -// The next step is to fill in the upto three conditional words. -//------------------------------------------------------------- - Uint32* tOptionalDataPtr = &tcKeyReq->scanInfo; - Uint32 tDistrGHIndex = tScanIndicator; - Uint32 tDistrKeyIndex = tDistrGHIndex; - - Uint32 tScanInfo = theScanInfo; - Uint32 tDistrKey = theDistributionKey; - - tOptionalDataPtr[0] = tScanInfo; - tOptionalDataPtr[tDistrKeyIndex] = tDistrKey; - -//------------------------------------------------------------- -// The next is step is to compress the key data part of the -// TCKEYREQ signal. -//------------------------------------------------------------- - Uint32 tKeyIndex = tDistrKeyIndex + tDistrKeyIndicator; - Uint32* tKeyDataPtr = &tOptionalDataPtr[tKeyIndex]; - Uint32 Tdata1 = tcKeyReq->keyInfo[0]; - Uint32 Tdata2 = tcKeyReq->keyInfo[1]; - Uint32 Tdata3 = tcKeyReq->keyInfo[2]; - Uint32 Tdata4 = tcKeyReq->keyInfo[3]; - Uint32 Tdata5; - - tKeyDataPtr[0] = Tdata1; - tKeyDataPtr[1] = Tdata2; - tKeyDataPtr[2] = Tdata3; - tKeyDataPtr[3] = Tdata4; - if (tIndexLen > 4) { - Tdata1 = tcKeyReq->keyInfo[4]; - Tdata2 = tcKeyReq->keyInfo[5]; - Tdata3 = tcKeyReq->keyInfo[6]; - Tdata4 = tcKeyReq->keyInfo[7]; - - tKeyDataPtr[4] = Tdata1; - tKeyDataPtr[5] = Tdata2; - tKeyDataPtr[6] = Tdata3; - tKeyDataPtr[7] = Tdata4; - }//if -//------------------------------------------------------------- -// Finally we also compress the INDXATTRINFO part of the signal. -// We optimise by using the if-statement for sending INDXKEYINFO -// signals to calculating the new Attrinfo Index. -//------------------------------------------------------------- - Uint32 tAttrInfoIndex; - - if (tIndexLen > TcKeyReq::MaxKeyInfo) { - /** - * Set transid and TC connect ptr in the INDXKEYINFO signals - */ - NdbApiSignal* tSignal = theTCREQ->next(); - Uint32 remainingKey = tIndexLen - TcKeyReq::MaxKeyInfo; - - do { - Uint32* tSigDataPtr = tSignal->getDataPtrSend(); - NdbApiSignal* tnextSignal = tSignal->next(); - tSignalCount++; - tSigDataPtr[0] = aTC_ConnectPtr; - tSigDataPtr[1] = tTransId1; - tSigDataPtr[2] = tTransId2; - if (remainingKey > IndxKeyInfo::DataLength) { - // The signal is full - tSignal->setLength(IndxKeyInfo::MaxSignalLength); - remainingKey -= IndxKeyInfo::DataLength; - } - else { - // Last signal - tSignal->setLength(IndxKeyInfo::HeaderLength + remainingKey); - remainingKey = 0; - } - tSignal = tnextSignal; - } while (tSignal != NULL); - tAttrInfoIndex = tKeyIndex + TcKeyReq::MaxKeyInfo; - } else { - tAttrInfoIndex = tKeyIndex + tIndexLen; - }//if - -//------------------------------------------------------------- -// Perform the Attrinfo packing in the TCKEYREQ signal started -// above. -//------------------------------------------------------------- - Uint32* tAIDataPtr = &tOptionalDataPtr[tAttrInfoIndex]; - Tdata1 = tcKeyReq->attrInfo[0]; - Tdata2 = tcKeyReq->attrInfo[1]; - Tdata3 = tcKeyReq->attrInfo[2]; - Tdata4 = tcKeyReq->attrInfo[3]; - Tdata5 = tcKeyReq->attrInfo[4]; - - theTCREQ->setLength(tcKeyReq->getAIInTcKeyReq(tReqInfo) + - tAttrInfoIndex + TcKeyReq::StaticLength); - tAIDataPtr[0] = Tdata1; - tAIDataPtr[1] = Tdata2; - tAIDataPtr[2] = Tdata3; - tAIDataPtr[3] = Tdata4; - tAIDataPtr[4] = Tdata5; - -/*************************************************** -* Send the INDXATTRINFO signals. -***************************************************/ - if (tTotalCurrAI_Len > 5) { - // Set the last signal's length. - NdbApiSignal* tSignal = theFirstATTRINFO; - theCurrentATTRINFO->setLength(theAI_LenInCurrAI); - do { - Uint32* tSigDataPtr = tSignal->getDataPtrSend(); - NdbApiSignal* tnextSignal = tSignal->next(); - tSignalCount++; - tSigDataPtr[0] = aTC_ConnectPtr; - tSigDataPtr[1] = tTransId1; - tSigDataPtr[2] = tTransId2; - tSignal = tnextSignal; - } while (tSignal != NULL); - }//if - theStatus = WaitResponse; - theReceiver.prepareSend(); - return 0; -} - /*************************************************************************** int receiveTCINDXREF( NdbApiSignal* aSignal) From 08d5217056118288b70c9433a38716a5c322bcf6 Mon Sep 17 00:00:00 2001 From: "jonas@perch.ndb.mysql.com" <> Date: Tue, 30 Jan 2007 19:45:14 +0100 Subject: [PATCH 15/40] ndb - interface change of handling of abort option 1) move AbortOption from NdbTransaction to NdbOperation 2) let each operation have a "default" abort option dependant on operation type - read - AO_IgnoreError - dml - AbortOnError - scan take over - AbortOnError 3) Changed default value to execute() from AbortOnError to DefaultAbortOption, which does not change the operations abort-option. Another value to execute(AO) is equivalent to setting AO on each operation before calling execute 4) execute() does _only_ return -1 if transaction has been aborted otherwise, you need to check each operation for error code --- sql/ha_ndbcluster.cc | 29 +- storage/ndb/include/ndbapi/NdbOperation.hpp | 23 +- storage/ndb/include/ndbapi/NdbTransaction.hpp | 56 ++-- storage/ndb/src/ndbapi/NdbBlob.cpp | 18 +- storage/ndb/src/ndbapi/NdbIndexStat.cpp | 2 +- storage/ndb/src/ndbapi/NdbOperationDefine.cpp | 53 ++-- storage/ndb/src/ndbapi/NdbOperationExec.cpp | 48 +-- storage/ndb/src/ndbapi/NdbScanOperation.cpp | 1 + storage/ndb/src/ndbapi/NdbTransaction.cpp | 140 ++------- storage/ndb/test/include/HugoOperations.hpp | 4 +- storage/ndb/test/ndbapi/testNdbApi.cpp | 274 ++++++++++++++++++ storage/ndb/test/src/HugoOperations.cpp | 4 +- 12 files changed, 413 insertions(+), 239 deletions(-) diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index 402dbd7c188..745d86f4a13 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -260,13 +260,14 @@ static int ndb_to_mysql_error(const NdbError *ndberr) int execute_no_commit_ignore_no_key(ha_ndbcluster *h, NdbTransaction *trans) { int res= trans->execute(NdbTransaction::NoCommit, - NdbTransaction::AO_IgnoreError, + NdbOperation::AO_IgnoreError, h->m_force_send); - if (res == 0) - return 0; + if (res == -1) + return -1; const NdbError &err= trans->getNdbError(); - if (err.classification != NdbError::ConstraintViolation && + if (err.classification != NdbError::NoError && + err.classification != NdbError::ConstraintViolation && err.classification != NdbError::NoDataFound) return res; @@ -286,7 +287,7 @@ int execute_no_commit(ha_ndbcluster *h, NdbTransaction *trans, return h->m_ignore_no_key ? execute_no_commit_ignore_no_key(h,trans) : trans->execute(NdbTransaction::NoCommit, - NdbTransaction::AbortOnError, + NdbOperation::AbortOnError, h->m_force_send); } @@ -299,7 +300,7 @@ int execute_commit(ha_ndbcluster *h, NdbTransaction *trans) return 0; #endif return trans->execute(NdbTransaction::Commit, - NdbTransaction::AbortOnError, + NdbOperation::AbortOnError, h->m_force_send); } @@ -312,7 +313,7 @@ int execute_commit(THD *thd, NdbTransaction *trans) return 0; #endif return trans->execute(NdbTransaction::Commit, - NdbTransaction::AbortOnError, + NdbOperation::AbortOnError, thd->variables.ndb_force_send); } @@ -327,7 +328,7 @@ int execute_no_commit_ie(ha_ndbcluster *h, NdbTransaction *trans, #endif h->release_completed_operations(trans, force_release); return trans->execute(NdbTransaction::NoCommit, - NdbTransaction::AO_IgnoreError, + NdbOperation::AO_IgnoreError, h->m_force_send); } @@ -1731,7 +1732,8 @@ int ha_ndbcluster::pk_read(const byte *key, uint key_len, byte *buf, ERR_RETURN(trans->getNdbError()); } - if (execute_no_commit_ie(this,trans,false) != 0) + if ((res = execute_no_commit_ie(this,trans,false)) != 0 || + op->getNdbError().code) { table->status= STATUS_NOT_FOUND; DBUG_RETURN(ndb_err(trans)); @@ -2003,7 +2005,8 @@ int ha_ndbcluster::unique_index_read(const byte *key, if ((res= define_read_attrs(buf, op))) DBUG_RETURN(res); - if (execute_no_commit_ie(this,trans,false) != 0) + if (execute_no_commit_ie(this,trans,false) != 0 || + op->getNdbError().code) { table->status= STATUS_NOT_FOUND; DBUG_RETURN(ndb_err(trans)); @@ -7742,7 +7745,7 @@ ndb_get_table_statistics(ha_ndbcluster* file, bool report_error, Ndb* ndb, const (char*)&var_mem); if (pTrans->execute(NdbTransaction::NoCommit, - NdbTransaction::AbortOnError, + NdbOperation::AbortOnError, TRUE) == -1) { error= pTrans->getNdbError(); @@ -8000,7 +8003,6 @@ ha_ndbcluster::read_multi_range_first(KEY_MULTI_RANGE **found_range_p, !op->readTuple(lm) && !set_primary_key(op, multi_range_curr->start_key.key) && !define_read_attrs(curr, op) && - (op->setAbortOption(AO_IgnoreError), TRUE) && (!m_use_partition_function || (op->setPartitionId(part_spec.start_part), true))) curr += reclength; @@ -8022,8 +8024,7 @@ ha_ndbcluster::read_multi_range_first(KEY_MULTI_RANGE **found_range_p, if ((op= m_active_trans->getNdbIndexOperation(unique_idx, tab)) && !op->readTuple(lm) && !set_index_key(op, key_info, multi_range_curr->start_key.key) && - !define_read_attrs(curr, op) && - (op->setAbortOption(AO_IgnoreError), TRUE)) + !define_read_attrs(curr, op)) curr += reclength; else ERR_RETURN(op ? op->getNdbError() : m_active_trans->getNdbError()); diff --git a/storage/ndb/include/ndbapi/NdbOperation.hpp b/storage/ndb/include/ndbapi/NdbOperation.hpp index 7f026e29578..390ab1e0d18 100644 --- a/storage/ndb/include/ndbapi/NdbOperation.hpp +++ b/storage/ndb/include/ndbapi/NdbOperation.hpp @@ -98,6 +98,19 @@ public: #endif }; + /** + * How should transaction be handled if operation fails + * + * For READ, default is AO_IgnoreError + * DML, default is AbortOnError + * CommittedRead does _only_ support AO_IgnoreError + */ + enum AbortOption { + DefaultAbortOption = -1,///< Use default as specified by op-type + AbortOnError = 0, ///< Abort transaction on failed operation + AO_IgnoreError = 2 ///< Transaction continues on failed operation + }; + /** * Define the NdbOperation to be a standard operation of type insertTuple. * When calling NdbTransaction::execute, this operation @@ -777,8 +790,13 @@ public: */ LockMode getLockMode() const { return theLockMode; } + /** + * Get/set abort option + */ + AbortOption getAbortOption() const; + int setAbortOption(AbortOption); + #ifndef DOXYGEN_SHOULD_SKIP_INTERNAL - void setAbortOption(Int8 ao) { m_abortOption = ao; } /** * Set/get partition key @@ -857,7 +875,8 @@ protected: int doSend(int ProcessorId, Uint32 lastFlag); virtual int prepareSend(Uint32 TC_ConnectPtr, - Uint64 TransactionId); + Uint64 TransactionId, + AbortOption); virtual void setLastFlag(NdbApiSignal* signal, Uint32 lastFlag); int prepareSendInterpreted(); // Help routine to prepare* diff --git a/storage/ndb/include/ndbapi/NdbTransaction.hpp b/storage/ndb/include/ndbapi/NdbTransaction.hpp index 8d367f1620a..a0520678a24 100644 --- a/storage/ndb/include/ndbapi/NdbTransaction.hpp +++ b/storage/ndb/include/ndbapi/NdbTransaction.hpp @@ -21,6 +21,7 @@ #include "NdbError.hpp" #include "NdbDictionary.hpp" #include "Ndb.hpp" +#include "NdbOperation.hpp" class NdbTransaction; class NdbOperation; @@ -45,11 +46,12 @@ typedef void (* NdbAsynchCallback)(int, NdbTransaction*, void*); #ifndef DOXYGEN_SHOULD_SKIP_INTERNAL enum AbortOption { - CommitIfFailFree= 0, - TryCommit= 0, - AbortOnError= 0, - CommitAsMuchAsPossible= 2, - AO_IgnoreError= 2 + DefaultAbortOption = NdbOperation::DefaultAbortOption, + CommitIfFailFree = NdbOperation::AbortOnError, + TryCommit = NdbOperation::AbortOnError, + AbortOnError= NdbOperation::AbortOnError, + CommitAsMuchAsPossible = NdbOperation::AO_IgnoreError, + AO_IgnoreError= NdbOperation::AO_IgnoreError }; enum ExecType { NoExecTypeDef = -1, @@ -145,20 +147,6 @@ class NdbTransaction public: - /** - * Commit type of transaction - */ - enum AbortOption { - AbortOnError= ///< Abort transaction on failed operation -#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL - ::AbortOnError -#endif - ,AO_IgnoreError= ///< Transaction continues on failed operation -#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL - ::AO_IgnoreError -#endif - }; - /** * Execution type of transaction */ @@ -317,13 +305,15 @@ public: * @return 0 if successful otherwise -1. */ int execute(ExecType execType, - AbortOption abortOption = AbortOnError, + NdbOperation::AbortOption = NdbOperation::DefaultAbortOption, int force = 0 ); #ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED int execute(::ExecType execType, - ::AbortOption abortOption = ::AbortOnError, - int force = 0 ) - { return execute ((ExecType)execType,(AbortOption)abortOption,force); } + ::AbortOption abortOption = ::DefaultAbortOption, + int force = 0 ) { + return execute ((ExecType)execType, + (NdbOperation::AbortOption)abortOption, + force); } #endif #ifndef DOXYGEN_SHOULD_SKIP_INTERNAL @@ -354,14 +344,14 @@ public: void executeAsynchPrepare(ExecType execType, NdbAsynchCallback callback, void* anyObject, - AbortOption abortOption = AbortOnError); + NdbOperation::AbortOption = NdbOperation::DefaultAbortOption); #ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED void executeAsynchPrepare(::ExecType execType, NdbAsynchCallback callback, void* anyObject, - ::AbortOption abortOption = ::AbortOnError) - { executeAsynchPrepare((ExecType)execType, callback, anyObject, - (AbortOption)abortOption); } + ::AbortOption ao = ::DefaultAbortOption) { + executeAsynchPrepare((ExecType)execType, callback, anyObject, + (NdbOperation::AbortOption)ao); } #endif /** @@ -380,14 +370,14 @@ public: void executeAsynch(ExecType aTypeOfExec, NdbAsynchCallback aCallback, void* anyObject, - AbortOption abortOption = AbortOnError); + NdbOperation::AbortOption = NdbOperation::DefaultAbortOption); #ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED void executeAsynch(::ExecType aTypeOfExec, NdbAsynchCallback aCallback, void* anyObject, - ::AbortOption abortOption= ::AbortOnError) + ::AbortOption abortOption= ::DefaultAbortOption) { executeAsynch((ExecType)aTypeOfExec, aCallback, anyObject, - (AbortOption)abortOption); } + (NdbOperation::AbortOption)abortOption); } #endif #endif /** @@ -589,7 +579,7 @@ private: void init(); // Initialize connection object for new transaction int executeNoBlobs(ExecType execType, - AbortOption abortOption = AbortOnError, + NdbOperation::AbortOption = NdbOperation::DefaultAbortOption, int force = 0 ); /** @@ -643,7 +633,7 @@ private: int sendCOMMIT(); // Send a TC_COMMITREQ signal; void setGCI(int GCI); // Set the global checkpoint identity - int OpCompleteFailure(Uint8 abortoption, bool setFailure = true); + int OpCompleteFailure(NdbOperation*); int OpCompleteSuccess(); void CompletedOperations(); // Move active ops to list of completed @@ -733,7 +723,6 @@ private: Uint32 theNoOfOpSent; // How many operations have been sent Uint32 theNoOfOpCompleted; // How many operations have completed - Uint32 theNoOfOpFetched; // How many operations was actually fetched Uint32 theMyRef; // Our block reference Uint32 theTCConPtr; // Transaction Co-ordinator connection pointer. Uint64 theTransactionId; // theTransactionId of the transaction @@ -757,7 +746,6 @@ private: bool theTransactionIsStarted; bool theInUseState; bool theSimpleState; - Uint8 m_abortOption; // Type of commi enum ListState { NotInList, diff --git a/storage/ndb/src/ndbapi/NdbBlob.cpp b/storage/ndb/src/ndbapi/NdbBlob.cpp index 4c4e9328894..d97958fd072 100644 --- a/storage/ndb/src/ndbapi/NdbBlob.cpp +++ b/storage/ndb/src/ndbapi/NdbBlob.cpp @@ -1134,7 +1134,7 @@ NdbBlob::readTableParts(char* buf, Uint32 part, Uint32 count) setErrorCode(tOp); DBUG_RETURN(-1); } - tOp->m_abortOption = NdbTransaction::AbortOnError; + tOp->m_abortOption = NdbOperation::AbortOnError; buf += thePartSize; n++; thePendingBlobOps |= (1 << NdbOperation::ReadRequest); @@ -1170,7 +1170,7 @@ NdbBlob::insertParts(const char* buf, Uint32 part, Uint32 count) setErrorCode(tOp); DBUG_RETURN(-1); } - tOp->m_abortOption = NdbTransaction::AbortOnError; + tOp->m_abortOption = NdbOperation::AbortOnError; buf += thePartSize; n++; thePendingBlobOps |= (1 << NdbOperation::InsertRequest); @@ -1194,7 +1194,7 @@ NdbBlob::updateParts(const char* buf, Uint32 part, Uint32 count) setErrorCode(tOp); DBUG_RETURN(-1); } - tOp->m_abortOption = NdbTransaction::AbortOnError; + tOp->m_abortOption = NdbOperation::AbortOnError; buf += thePartSize; n++; thePendingBlobOps |= (1 << NdbOperation::UpdateRequest); @@ -1217,7 +1217,7 @@ NdbBlob::deleteParts(Uint32 part, Uint32 count) setErrorCode(tOp); DBUG_RETURN(-1); } - tOp->m_abortOption = NdbTransaction::AbortOnError; + tOp->m_abortOption = NdbOperation::AbortOnError; n++; thePendingBlobOps |= (1 << NdbOperation::DeleteRequest); theNdbCon->thePendingBlobOps |= (1 << NdbOperation::DeleteRequest); @@ -1253,7 +1253,7 @@ NdbBlob::deletePartsUnknown(Uint32 part) setErrorCode(tOp); DBUG_RETURN(-1); } - tOp->m_abortOption= NdbTransaction::AO_IgnoreError; + tOp->m_abortOption= NdbOperation::AO_IgnoreError; n++; } DBUG_PRINT("info", ("bat=%u", bat)); @@ -1589,7 +1589,7 @@ NdbBlob::preExecute(NdbTransaction::ExecType anExecType, bool& batch) DBUG_RETURN(-1); } if (isWriteOp()) { - tOp->m_abortOption = NdbTransaction::AO_IgnoreError; + tOp->m_abortOption = NdbOperation::AO_IgnoreError; } theHeadInlineReadOp = tOp; // execute immediately @@ -1635,7 +1635,7 @@ NdbBlob::preExecute(NdbTransaction::ExecType anExecType, bool& batch) DBUG_RETURN(-1); } if (isWriteOp()) { - tOp->m_abortOption = NdbTransaction::AO_IgnoreError; + tOp->m_abortOption = NdbOperation::AO_IgnoreError; } theHeadInlineReadOp = tOp; // execute immediately @@ -1808,7 +1808,7 @@ NdbBlob::postExecute(NdbTransaction::ExecType anExecType) setErrorCode(NdbBlobImpl::ErrAbort); DBUG_RETURN(-1); } - tOp->m_abortOption = NdbTransaction::AbortOnError; + tOp->m_abortOption = NdbOperation::AbortOnError; DBUG_PRINT("info", ("added op to update head+inline")); } DBUG_RETURN(0); @@ -1838,7 +1838,7 @@ NdbBlob::preCommit() setErrorCode(NdbBlobImpl::ErrAbort); DBUG_RETURN(-1); } - tOp->m_abortOption = NdbTransaction::AbortOnError; + tOp->m_abortOption = NdbOperation::AbortOnError; DBUG_PRINT("info", ("added op to update head+inline")); } } diff --git a/storage/ndb/src/ndbapi/NdbIndexStat.cpp b/storage/ndb/src/ndbapi/NdbIndexStat.cpp index 4ae00348606..7c4051a49c3 100644 --- a/storage/ndb/src/ndbapi/NdbIndexStat.cpp +++ b/storage/ndb/src/ndbapi/NdbIndexStat.cpp @@ -428,7 +428,7 @@ NdbIndexStat::records_in_range(const NdbDictionary::Index* index, NdbIndexScanOp DBUG_RETURN(-1); } if (trans->execute(NdbTransaction::NoCommit, - NdbTransaction::AbortOnError, forceSend) == -1) { + NdbOperation::AbortOnError, forceSend) == -1) { m_error = trans->getNdbError(); DBUG_PRINT("error", ("trans:%d op:%d", trans->getNdbError().code, op->getNdbError().code)); diff --git a/storage/ndb/src/ndbapi/NdbOperationDefine.cpp b/storage/ndb/src/ndbapi/NdbOperationDefine.cpp index d14fcf60ec4..52b517a1168 100644 --- a/storage/ndb/src/ndbapi/NdbOperationDefine.cpp +++ b/storage/ndb/src/ndbapi/NdbOperationDefine.cpp @@ -45,6 +45,7 @@ NdbOperation::insertTuple() tNdbCon->theSimpleState = 0; theErrorLine = tErrorLine++; theLockMode = LM_Exclusive; + m_abortOption = AbortOnError; return 0; } else { setErrorCode(4200); @@ -65,6 +66,7 @@ NdbOperation::updateTuple() theOperationType = UpdateRequest; theErrorLine = tErrorLine++; theLockMode = LM_Exclusive; + m_abortOption = AbortOnError; return 0; } else { setErrorCode(4200); @@ -85,12 +87,35 @@ NdbOperation::writeTuple() theOperationType = WriteRequest; theErrorLine = tErrorLine++; theLockMode = LM_Exclusive; + m_abortOption = AbortOnError; return 0; } else { setErrorCode(4200); return -1; }//if }//NdbOperation::writeTuple() +/***************************************************************************** + * int deleteTuple(); + *****************************************************************************/ +int +NdbOperation::deleteTuple() +{ + NdbTransaction* tNdbCon = theNdbCon; + int tErrorLine = theErrorLine; + if (theStatus == Init) { + theStatus = OperationDefined; + tNdbCon->theSimpleState = 0; + theOperationType = DeleteRequest; + theErrorLine = tErrorLine++; + theLockMode = LM_Exclusive; + m_abortOption = AbortOnError; + return 0; + } else { + setErrorCode(4200); + return -1; + }//if +}//NdbOperation::deleteTuple() + /****************************************************************************** * int readTuple(); *****************************************************************************/ @@ -125,6 +150,7 @@ NdbOperation::readTuple() theOperationType = ReadRequest; theErrorLine = tErrorLine++; theLockMode = LM_Read; + m_abortOption = AO_IgnoreError; return 0; } else { setErrorCode(4200); @@ -132,27 +158,6 @@ NdbOperation::readTuple() }//if }//NdbOperation::readTuple() -/***************************************************************************** - * int deleteTuple(); - *****************************************************************************/ -int -NdbOperation::deleteTuple() -{ - NdbTransaction* tNdbCon = theNdbCon; - int tErrorLine = theErrorLine; - if (theStatus == Init) { - theStatus = OperationDefined; - tNdbCon->theSimpleState = 0; - theOperationType = DeleteRequest; - theErrorLine = tErrorLine++; - theLockMode = LM_Exclusive; - return 0; - } else { - setErrorCode(4200); - return -1; - }//if -}//NdbOperation::deleteTuple() - /****************************************************************************** * int readTupleExclusive(); *****************************************************************************/ @@ -167,6 +172,7 @@ NdbOperation::readTupleExclusive() theOperationType = ReadExclusive; theErrorLine = tErrorLine++; theLockMode = LM_Exclusive; + m_abortOption = AO_IgnoreError; return 0; } else { setErrorCode(4200); @@ -223,6 +229,7 @@ NdbOperation::committedRead() theDirtyIndicator = 1; theErrorLine = tErrorLine++; theLockMode = LM_CommittedRead; + m_abortOption = AO_IgnoreError; return 0; } else { setErrorCode(4200); @@ -246,6 +253,7 @@ NdbOperation::dirtyUpdate() theDirtyIndicator = 1; theErrorLine = tErrorLine++; theLockMode = LM_CommittedRead; + m_abortOption = AbortOnError; return 0; } else { setErrorCode(4200); @@ -269,6 +277,7 @@ NdbOperation::dirtyWrite() theDirtyIndicator = 1; theErrorLine = tErrorLine++; theLockMode = LM_CommittedRead; + m_abortOption = AbortOnError; return 0; } else { setErrorCode(4200); @@ -291,6 +300,7 @@ NdbOperation::interpretedUpdateTuple() theAI_LenInCurrAI = 25; theLockMode = LM_Exclusive; theErrorLine = tErrorLine++; + m_abortOption = AbortOnError; initInterpreter(); return 0; } else { @@ -315,6 +325,7 @@ NdbOperation::interpretedDeleteTuple() theErrorLine = tErrorLine++; theAI_LenInCurrAI = 25; theLockMode = LM_Exclusive; + m_abortOption = AbortOnError; initInterpreter(); return 0; } else { diff --git a/storage/ndb/src/ndbapi/NdbOperationExec.cpp b/storage/ndb/src/ndbapi/NdbOperationExec.cpp index 38e0b441346..b2c87a91dd9 100644 --- a/storage/ndb/src/ndbapi/NdbOperationExec.cpp +++ b/storage/ndb/src/ndbapi/NdbOperationExec.cpp @@ -100,7 +100,9 @@ Parameters: aTC_ConnectPtr: the Connect pointer to TC. Remark: Puts the the data into TCKEYREQ signal and optional KEYINFO and ATTRINFO signals. ***************************************************************************/ int -NdbOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64 aTransId) +NdbOperation::prepareSend(Uint32 aTC_ConnectPtr, + Uint64 aTransId, + AbortOption ao) { Uint32 tTransId1, tTransId2; Uint32 tReqInfo; @@ -148,8 +150,8 @@ NdbOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64 aTransId) //------------------------------------------------------------- TcKeyReq * const tcKeyReq = CAST_PTR(TcKeyReq, theTCREQ->getDataPtrSend()); - Uint32 tTableId = m_currentTable->m_id; - Uint32 tSchemaVersion = m_currentTable->m_version; + Uint32 tTableId = m_accessTable->m_id; + Uint32 tSchemaVersion = m_accessTable->m_version; tcKeyReq->apiConnectPtr = aTC_ConnectPtr; tcKeyReq->apiOperationPtr = ptr2int(); @@ -199,16 +201,16 @@ NdbOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64 aTransId) OperationType tOperationType = theOperationType; Uint32 tTupKeyLen = theTupKeyLen; - Uint8 abortOption = - m_abortOption != -1 ? m_abortOption : theNdbCon->m_abortOption; + Uint8 abortOption = (ao == DefaultAbortOption) ? m_abortOption : ao; tcKeyReq->setDirtyFlag(tReqInfo, tDirtyIndicator); tcKeyReq->setOperationType(tReqInfo, tOperationType); tcKeyReq->setKeyLength(tReqInfo, tTupKeyLen); // A simple read is always ignore error - abortOption = tSimpleIndicator ? (Uint8) AO_IgnoreError : abortOption; + abortOption = tSimpleState ? AO_IgnoreError : abortOption; tcKeyReq->setAbortOption(tReqInfo, abortOption); + m_abortOption = abortOption; Uint8 tDistrKeyIndicator = theDistrKeyIndicator_; Uint8 tScanIndicator = theScanInfo & 1; @@ -544,21 +546,16 @@ NdbOperation::receiveTCKEYREF( NdbApiSignal* aSignal) return -1; }//if - AbortOption ao = (AbortOption) - (m_abortOption != -1 ? m_abortOption : theNdbCon->m_abortOption); + setErrorCode(aSignal->readData(4)); + theStatus = Finished; theReceiver.m_received_result_length = ~0; - theStatus = Finished; - // blobs want this - if (m_abortOption != AO_IgnoreError) + // not simple read + if(! (theOperationType == ReadRequest && theSimpleIndicator)) { - theNdbCon->theReturnStatus = NdbTransaction::ReturnFailure; + theNdbCon->OpCompleteFailure(this); + return -1; } - theError.code = aSignal->readData(4); - theNdbCon->setOperationErrorCodeAbort(aSignal->readData(4), ao); - - if(theOperationType != ReadRequest || !theSimpleIndicator) // not simple read - return theNdbCon->OpCompleteFailure(ao, m_abortOption != AO_IgnoreError); /** * If TCKEYCONF has arrived @@ -566,23 +563,8 @@ NdbOperation::receiveTCKEYREF( NdbApiSignal* aSignal) */ if(theReceiver.m_expected_result_length) { - return theNdbCon->OpCompleteFailure(AbortOnError); + return theNdbCon->OpCompleteFailure(this); } return -1; } - - -void -NdbOperation::handleFailedAI_ElemLen() -{ - NdbRecAttr* tRecAttr = theReceiver.theFirstRecAttr; - while (tRecAttr != NULL) { - tRecAttr->setNULL(); - tRecAttr = tRecAttr->next(); - }//while -}//NdbOperation::handleFailedAI_ElemLen() - - - - diff --git a/storage/ndb/src/ndbapi/NdbScanOperation.cpp b/storage/ndb/src/ndbapi/NdbScanOperation.cpp index 75ad6306c69..5115e79e6c4 100644 --- a/storage/ndb/src/ndbapi/NdbScanOperation.cpp +++ b/storage/ndb/src/ndbapi/NdbScanOperation.cpp @@ -996,6 +996,7 @@ NdbScanOperation::takeOverScanOp(OperationType opType, NdbTransaction* pTrans) newOp->theTupKeyLen = len; newOp->theOperationType = opType; + newOp->m_abortOption = AbortOnError; switch (opType) { case (ReadRequest): newOp->theLockMode = theLockMode; diff --git a/storage/ndb/src/ndbapi/NdbTransaction.cpp b/storage/ndb/src/ndbapi/NdbTransaction.cpp index f1de82ab880..5ce03911c03 100644 --- a/storage/ndb/src/ndbapi/NdbTransaction.cpp +++ b/storage/ndb/src/ndbapi/NdbTransaction.cpp @@ -57,7 +57,6 @@ NdbTransaction::NdbTransaction( Ndb* aNdb ) : theCompletedLastOp(NULL), theNoOfOpSent(0), theNoOfOpCompleted(0), - theNoOfOpFetched(0), theMyRef(0), theTCConPtr(0), theTransactionId(0), @@ -132,7 +131,6 @@ NdbTransaction::init() theNdb->theImpl->m_ndb_cluster_connection.get_latest_trans_gci(); theCommitStatus = Started; theCompletionStatus = NotCompleted; - m_abortOption = AbortOnError; theError.code = 0; theErrorLine = 0; @@ -177,12 +175,9 @@ void NdbTransaction::setOperationErrorCodeAbort(int error, int abortOption) { DBUG_ENTER("NdbTransaction::setOperationErrorCodeAbort"); - if (abortOption == -1) - abortOption = m_abortOption; if (theTransactionIsStarted == false) { theCommitStatus = Aborted; - } else if ((abortOption == AbortOnError) && - (theCommitStatus != Committed) && + } else if ((theCommitStatus != Committed) && (theCommitStatus != Aborted)) { theCommitStatus = NeedAbort; }//if @@ -264,8 +259,8 @@ Remark: Initialise connection object for new transaction. *****************************************************************************/ int NdbTransaction::execute(ExecType aTypeOfExec, - AbortOption abortOption, - int forceSend) + NdbOperation::AbortOption abortOption, + int forceSend) { NdbError savedError= theError; DBUG_ENTER("NdbTransaction::execute"); @@ -355,40 +350,14 @@ NdbTransaction::execute(ExecType aTypeOfExec, theCompletedLastOp = NULL; } - if (executeNoBlobs(tExecType, abortOption, forceSend) == -1) + if (executeNoBlobs(tExecType, + NdbOperation::DefaultAbortOption, + forceSend) == -1) { - ret = -1; if(savedError.code==0) savedError= theError; - /** - * If AO_IgnoreError, error codes arent always set on individual - * operations, making postExecute impossible - */ - if (abortOption == AO_IgnoreError) - { - if (theCompletedFirstOp != NULL) - { - if (tCompletedFirstOp != NULL) - { - tCompletedLastOp->next(theCompletedFirstOp); - theCompletedFirstOp = tCompletedFirstOp; - } - } - else - { - theCompletedFirstOp = tCompletedFirstOp; - theCompletedLastOp = tCompletedLastOp; - } - if (tPrepOp != NULL && tRestOp != NULL) { - if (theFirstOpInList == NULL) - theFirstOpInList = tRestOp; - else - theLastOpInList->next(tRestOp); - theLastOpInList = tLastOp; - } - DBUG_RETURN(-1); - } + DBUG_RETURN(-1); } #ifdef ndb_api_crash_on_complex_blob_abort @@ -448,9 +417,9 @@ NdbTransaction::execute(ExecType aTypeOfExec, } int -NdbTransaction::executeNoBlobs(ExecType aTypeOfExec, - AbortOption abortOption, - int forceSend) +NdbTransaction::executeNoBlobs(NdbTransaction::ExecType aTypeOfExec, + NdbOperation::AbortOption abortOption, + int forceSend) { DBUG_ENTER("NdbTransaction::executeNoBlobs"); DBUG_PRINT("enter", ("aTypeOfExec: %d, abortOption: %d", @@ -528,10 +497,10 @@ Parameters : aTypeOfExec: Type of execute. Remark: Prepare a part of a transaction in an asynchronous manner. *****************************************************************************/ void -NdbTransaction::executeAsynchPrepare( ExecType aTypeOfExec, +NdbTransaction::executeAsynchPrepare(NdbTransaction::ExecType aTypeOfExec, NdbAsynchCallback aCallback, void* anyObject, - AbortOption abortOption) + NdbOperation::AbortOption abortOption) { DBUG_ENTER("NdbTransaction::executeAsynchPrepare"); DBUG_PRINT("enter", ("aTypeOfExec: %d, aCallback: 0x%lx, anyObject: Ox%lx", @@ -571,7 +540,6 @@ NdbTransaction::executeAsynchPrepare( ExecType aTypeOfExec, theReturnStatus = ReturnSuccess; theCallbackFunction = aCallback; theCallbackObject = anyObject; - m_abortOption = abortOption; m_waitForReply = true; tNdb->thePreparedTransactionsArray[tnoOfPreparedTransactions] = this; theTransArrayIndex = tnoOfPreparedTransactions; @@ -666,8 +634,7 @@ NdbTransaction::executeAsynchPrepare( ExecType aTypeOfExec, while (tOp) { int tReturnCode; NdbOperation* tNextOp = tOp->next(); - - tReturnCode = tOp->prepareSend(theTCConPtr, theTransactionId); + tReturnCode = tOp->prepareSend(theTCConPtr, theTransactionId, abortOption); if (tReturnCode == -1) { theSendStatus = sendABORTfail; DBUG_VOID_RETURN; @@ -1800,14 +1767,8 @@ from other transactions. } } else if ((tNoComp >= tNoSent) && (theLastExecOpInList->theCommitIndicator == 1)){ - - - if (m_abortOption == AO_IgnoreError && theError.code != 0){ - /** - * There's always a TCKEYCONF when using IgnoreError - */ - return -1; - } + + /**********************************************************************/ // We sent the transaction with Commit flag set and received a CONF with // no Commit flag set. This is clearly an anomaly. @@ -1981,13 +1942,6 @@ NdbTransaction::receiveTCINDXCONF(const TcIndxConf * indxConf, } else if ((tNoComp >= tNoSent) && (theLastExecOpInList->theCommitIndicator == 1)){ - if (m_abortOption == AO_IgnoreError && theError.code != 0){ - /** - * There's always a TCKEYCONF when using IgnoreError - */ - return -1; - } - /**********************************************************************/ // We sent the transaction with Commit flag set and received a CONF with // no Commit flag set. This is clearly an anomaly. @@ -2011,41 +1965,6 @@ NdbTransaction::receiveTCINDXCONF(const TcIndxConf * indxConf, return -1; }//NdbTransaction::receiveTCINDXCONF() -/***************************************************************************** -int receiveTCINDXREF( NdbApiSignal* aSignal) - -Return Value: Return 0 : send was succesful. - Return -1: In all other case. -Parameters: aSignal: the signal object that contains the - TCINDXREF signal from TC. -Remark: Handles the reception of the TCINDXREF signal. -*****************************************************************************/ -int -NdbTransaction::receiveTCINDXREF( NdbApiSignal* aSignal) -{ - if(checkState_TransId(aSignal->getDataPtr()+1)){ - theError.code = aSignal->readData(4); // Override any previous errors - - /**********************************************************************/ - /* A serious error has occured. This could be due to deadlock or */ - /* lack of resources or simply a programming error in NDB. This */ - /* transaction will be aborted. Actually it has already been */ - /* and we only need to report completion and return with the */ - /* error code to the application. */ - /**********************************************************************/ - theCompletionStatus = NdbTransaction::CompletedFailure; - theCommitStatus = NdbTransaction::Aborted; - theReturnStatus = NdbTransaction::ReturnFailure; - return 0; - } else { -#ifdef NDB_NO_DROPPED_SIGNAL - abort(); -#endif - } - - return -1; -}//NdbTransaction::receiveTCINDXREF() - /******************************************************************************* int OpCompletedFailure(); @@ -2055,36 +1974,15 @@ Parameters: aErrorCode: The error code. Remark: An operation was completed with failure. *******************************************************************************/ int -NdbTransaction::OpCompleteFailure(Uint8 abortOption, bool setFailure) +NdbTransaction::OpCompleteFailure(NdbOperation* op) { Uint32 tNoComp = theNoOfOpCompleted; Uint32 tNoSent = theNoOfOpSent; - if (setFailure) - theCompletionStatus = NdbTransaction::CompletedFailure; + tNoComp++; theNoOfOpCompleted = tNoComp; - if (tNoComp == tNoSent) { - //------------------------------------------------------------------------ - //If the transaction consists of only simple reads we can set - //Commit state Aborted. Otherwise this simple operation cannot - //decide the success of the whole transaction since a simple - //operation is not really part of that transaction. - //------------------------------------------------------------------------ - if (abortOption == AO_IgnoreError){ - /** - * There's always a TCKEYCONF when using IgnoreError - */ - return -1; - } - - return 0; // Last operation received - } else if (tNoComp > tNoSent) { - setOperationErrorCodeAbort(4113); // Too many operations, - // stop waiting for more - return 0; - } else { - return -1; // Continue waiting for more signals - }//if + + return (tNoComp == tNoSent) ? 0 : -1; }//NdbTransaction::OpCompleteFailure() /****************************************************************************** diff --git a/storage/ndb/test/include/HugoOperations.hpp b/storage/ndb/test/include/HugoOperations.hpp index 995463e5056..2edc7b16922 100644 --- a/storage/ndb/test/include/HugoOperations.hpp +++ b/storage/ndb/test/include/HugoOperations.hpp @@ -107,8 +107,8 @@ public: NDBT_ResultRow& get_row(Uint32 idx) { return *rows[idx];} - int execute_async(Ndb*, NdbTransaction::ExecType, NdbTransaction::AbortOption = NdbTransaction::AbortOnError); - int execute_async_prepare(Ndb*, NdbTransaction::ExecType, NdbTransaction::AbortOption = NdbTransaction::AbortOnError); + int execute_async(Ndb*, NdbTransaction::ExecType, NdbOperation::AbortOption = NdbOperation::AbortOnError); + int execute_async_prepare(Ndb*, NdbTransaction::ExecType, NdbOperation::AbortOption = NdbOperation::AbortOnError); int wait_async(Ndb*, int timeout = -1); diff --git a/storage/ndb/test/ndbapi/testNdbApi.cpp b/storage/ndb/test/ndbapi/testNdbApi.cpp index cfedfbd9ac0..0372da74031 100644 --- a/storage/ndb/test/ndbapi/testNdbApi.cpp +++ b/storage/ndb/test/ndbapi/testNdbApi.cpp @@ -1250,6 +1250,274 @@ int runScan_4006(NDBT_Context* ctx, NDBT_Step* step){ return result; } +char pkIdxName[255]; + +int createPkIndex(NDBT_Context* ctx, NDBT_Step* step){ + bool orderedIndex = ctx->getProperty("OrderedIndex", (unsigned)0); + + const NdbDictionary::Table* pTab = ctx->getTab(); + Ndb* pNdb = GETNDB(step); + + bool logged = ctx->getProperty("LoggedIndexes", 1); + + // Create index + BaseString::snprintf(pkIdxName, 255, "IDC_PK_%s", pTab->getName()); + if (orderedIndex) + ndbout << "Creating " << ((logged)?"logged ": "temporary ") << "ordered index " + << pkIdxName << " ("; + else + ndbout << "Creating " << ((logged)?"logged ": "temporary ") << "unique index " + << pkIdxName << " ("; + + NdbDictionary::Index pIdx(pkIdxName); + 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; +} + +int createPkIndex_Drop(NDBT_Context* ctx, NDBT_Step* step){ + const NdbDictionary::Table* pTab = ctx->getTab(); + Ndb* pNdb = GETNDB(step); + + // Drop index + ndbout << "Dropping index " << pkIdxName << " "; + if (pNdb->getDictionary()->dropIndex(pkIdxName, + pTab->getName()) != 0){ + ndbout << "FAILED!" << endl; + ERR(pNdb->getDictionary()->getNdbError()); + return NDBT_FAILED; + } else { + ndbout << "OK!" << endl; + } + + return NDBT_OK; +} + +static +int +op_row(NdbTransaction* pTrans, HugoOperations& hugoOps, + const NdbDictionary::Table* pTab, int op, int row) +{ + NdbOperation * pOp = 0; + switch(op){ + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + pOp = pTrans->getNdbOperation(pTab->getName()); + break; + case 9: + return 0; + case 6: + case 7: + case 8: + case 10: + case 11: + pOp = pTrans->getNdbIndexOperation(pkIdxName, pTab->getName()); + default: + break; + } + + switch(op){ + case 0: + case 6: + pOp->readTuple(); + break; + case 1: + case 7: + pOp->committedRead(); + break; + case 2: + case 8: + pOp->readTupleExclusive(); + break; + case 3: + case 9: + pOp->insertTuple(); + break; + case 4: + case 10: + pOp->updateTuple(); + break; + case 5: + case 11: + pOp->deleteTuple(); + break; + default: + abort(); + } + + for(int a = 0; agetNoOfColumns(); a++){ + if (pTab->getColumn(a)->getPrimaryKey() == true){ + if(hugoOps.equalForAttr(pOp, a, row) != 0){ + return NDBT_FAILED; + } + } + } + + switch(op){ + case 0: + case 1: + case 2: + case 6: + case 7: + case 8: + for(int a = 0; agetNoOfColumns(); a++){ + pOp->getValue(a); + } + break; + case 3: + case 4: + case 10: + for(int a = 0; agetNoOfColumns(); a++){ + if (pTab->getColumn(a)->getPrimaryKey() == false){ + if(hugoOps.setValueForAttr(pOp, a, row, 2) != 0){ + return NDBT_FAILED; + } + } + } + break; + case 5: + case 11: + pOp->deleteTuple(); + break; + case 9: + default: + abort(); + } + + return NDBT_OK; +} + +static void print(int op) +{ + const char * str = 0; + switch(op){ + case 0: str = "pk read-sh"; break; + case 1: str = "pk read-nl"; break; + case 2: str = "pk read-ex"; break; + case 3: str = "pk insert "; break; + case 4: str = "pk update "; break; + case 5: str = "pk delete "; break; + case 6: str = "uk read-sh"; break; + case 7: str = "uk read-nl"; break; + case 8: str = "uk read-ex"; break; + case 9: str = "noop "; break; + case 10: str = "uk update "; break; + case 11: str = "uk delete "; break; + default: + abort(); + } + printf("%s ", str); +} + +int +runTestIgnoreError(NDBT_Context* ctx, NDBT_Step* step) +{ + int result = NDBT_OK; + Uint32 loops = ctx->getNumRecords(); + const NdbDictionary::Table* pTab = ctx->getTab(); + + HugoOperations hugoOps(*pTab); + HugoTransactions hugoTrans(*pTab); + + Ndb* pNdb = GETNDB(step); + + struct { + ExecType et; + AbortOption ao; + } tests[] = { + { Commit, AbortOnError }, + { Commit, AO_IgnoreError }, + { NoCommit, AbortOnError }, + { NoCommit, AO_IgnoreError }, + }; + + printf("case: c/nc ao/ie\n"); + Uint32 tno = 0; + for (Uint32 op1 = 0; op1 < 12; op1++) + { + for (Uint32 op2 = op1; op2 < 12; op2++) + { + int ret; + NdbTransaction* pTrans = 0; + + for (Uint32 i = 0; i<4; i++, tno++) + { + if (loops != 1000 && loops != tno) + continue; + ExecType et = tests[i].et; + AbortOption ao = tests[i].ao; + + printf("%.3d : ", tno); + print(op1); + print(op2); + switch(et){ + case Commit: printf("c "); break; + case NoCommit: printf("nc "); break; + } + switch(ao){ + case AbortOnError: printf("aoe "); break; + case AO_IgnoreError: printf("ie "); break; + } + printf(": "); + + + hugoTrans.loadTable(pNdb, 1); + pTrans = pNdb->startTransaction(); + op_row(pTrans, hugoOps, pTab, op1, 0); + ret = pTrans->execute(et, ao); + pTrans->close(); + printf("%d ", ret); + hugoTrans.clearTable(pNdb); + + hugoTrans.loadTable(pNdb, 1); + pTrans = pNdb->startTransaction(); + op_row(pTrans, hugoOps, pTab, op1, 1); + ret = pTrans->execute(et, ao); + pTrans->close(); + printf("%d ", ret); + hugoTrans.clearTable(pNdb); + + hugoTrans.loadTable(pNdb, 1); + pTrans = pNdb->startTransaction(); + op_row(pTrans, hugoOps, pTab, op1, 0); + op_row(pTrans, hugoOps, pTab, op2, 1); + ret = pTrans->execute(et, ao); + pTrans->close(); + printf("%d\n", ret); + hugoTrans.clearTable(pNdb); + + hugoTrans.clearTable(pNdb); + } + } + } + return NDBT_OK; +} + template class Vector; @@ -1343,6 +1611,12 @@ TESTCASE("Scan_4006", INITIALIZER(runScan_4006); FINALIZER(runClearTable); } +TESTCASE("IgnoreError", ""){ + INITIALIZER(createPkIndex); + STEP(runTestIgnoreError); + FINALIZER(runClearTable); + FINALIZER(createPkIndex_Drop); +} NDBT_TESTSUITE_END(testNdbApi); int main(int argc, const char** argv){ diff --git a/storage/ndb/test/src/HugoOperations.cpp b/storage/ndb/test/src/HugoOperations.cpp index 2903cb8810e..4abcaba60d5 100644 --- a/storage/ndb/test/src/HugoOperations.cpp +++ b/storage/ndb/test/src/HugoOperations.cpp @@ -458,7 +458,7 @@ HugoOperations::callback(int res, NdbTransaction* pCon) int HugoOperations::execute_async(Ndb* pNdb, NdbTransaction::ExecType et, - NdbTransaction::AbortOption eao){ + NdbOperation::AbortOption eao){ m_async_reply= 0; pTrans->executeAsynchPrepare(et, @@ -473,7 +473,7 @@ HugoOperations::execute_async(Ndb* pNdb, NdbTransaction::ExecType et, int HugoOperations::execute_async_prepare(Ndb* pNdb, NdbTransaction::ExecType et, - NdbTransaction::AbortOption eao){ + NdbOperation::AbortOption eao){ m_async_reply= 0; pTrans->executeAsynchPrepare(et, From 1ce3dc9636761e201998d5c3e81e6262d6cb0a48 Mon Sep 17 00:00:00 2001 From: "tomas@poseidon.mysql.com" <> Date: Wed, 31 Jan 2007 13:01:03 +0700 Subject: [PATCH 16/40] Bug#25239 Out of memory problem can cause crash in SUMA --- storage/ndb/src/kernel/blocks/suma/Suma.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/storage/ndb/src/kernel/blocks/suma/Suma.cpp b/storage/ndb/src/kernel/blocks/suma/Suma.cpp index b201d05726d..7afedfbde71 100644 --- a/storage/ndb/src/kernel/blocks/suma/Suma.cpp +++ b/storage/ndb/src/kernel/blocks/suma/Suma.cpp @@ -4668,9 +4668,7 @@ Suma::out_of_buffer(Signal* signal) m_out_of_buffer_gci = m_last_complete_gci - 1; infoEvent("Out of event buffer: nodefailure will cause event failures"); - signal->theData[0] = SumaContinueB::OUT_OF_BUFFER_RELEASE; - signal->theData[1] = 0; - sendSignal(SUMA_REF, GSN_CONTINUEB, signal, 2, JBB); + out_of_buffer_release(signal, 0); } void @@ -4738,7 +4736,8 @@ loop: Uint32 count; m_tup->allocConsPages(16, count, ref); - ndbrequire(count > 0); + if (count == 0) + return RNIL; ndbout_c("alloc_chunk(%d %d) - ", ref, count); From 5cd40ad30b8d340bed6b80e1b05dac7e452f8132 Mon Sep 17 00:00:00 2001 From: "mskold/marty@mysql.com/linux.site" <> Date: Wed, 31 Jan 2007 22:38:06 +0100 Subject: [PATCH 17/40] Bug #25522 Update with IN syntax Clustertable + Trigger leads to mysqld segfault: in start_stmt, only change query_state if starting a new transactions, in read_multi_range_next, change query state when end is reached --- mysql-test/r/ndb_read_multi_range.result | 17 ++++++++++++++ mysql-test/t/ndb_read_multi_range.test | 29 ++++++++++++++++++++++++ sql/ha_ndbcluster.cc | 8 +++++-- 3 files changed, 52 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/ndb_read_multi_range.result b/mysql-test/r/ndb_read_multi_range.result index e2a076ef99f..d279485e48e 100644 --- a/mysql-test/r/ndb_read_multi_range.result +++ b/mysql-test/r/ndb_read_multi_range.result @@ -381,3 +381,20 @@ SELECT id, tag, doc, type FROM t1 WHERE id IN ('flipper','sakila'); id tag doc type sakila 1 Some text goes here text DROP TABLE t1; +CREATE TABLE t1 ( +var1 int(2) NOT NULL, +var2 int(2) NOT NULL, +PRIMARY KEY (var1) +) ENGINE=ndbcluster DEFAULT CHARSET=ascii CHECKSUM=1; +CREATE TABLE t2 ( +var1 int(2) NOT NULL, +var2 int(2) NOT NULL, +PRIMARY KEY (var1) +) ENGINE=MyISAM DEFAULT CHARSET=ascii CHECKSUM=1; +CREATE TRIGGER testtrigger +AFTER UPDATE ON t1 FOR EACH ROW BEGIN +REPLACE INTO t2 SELECT * FROM t1 WHERE t1.var1 = NEW.var1;END| +INSERT INTO t1 VALUES (1,1),(2,2),(3,3); +UPDATE t1 SET var2 = 9 WHERE var1 IN(1,2,3); +DROP TRIGGER testtrigger; +DROP TABLE t1, t2; diff --git a/mysql-test/t/ndb_read_multi_range.test b/mysql-test/t/ndb_read_multi_range.test index 99edab5d23c..cfbf0561d1e 100644 --- a/mysql-test/t/ndb_read_multi_range.test +++ b/mysql-test/t/ndb_read_multi_range.test @@ -253,3 +253,32 @@ SELECT id, tag, doc, type FROM t1 WHERE id IN ('flipper','orka'); SELECT id, tag, doc, type FROM t1 WHERE id IN ('flipper','sakila'); DROP TABLE t1; + +#bug#25522 +CREATE TABLE t1 ( + var1 int(2) NOT NULL, + var2 int(2) NOT NULL, + PRIMARY KEY (var1) + ) ENGINE=ndbcluster DEFAULT CHARSET=ascii CHECKSUM=1; + + +CREATE TABLE t2 ( + var1 int(2) NOT NULL, + var2 int(2) NOT NULL, + PRIMARY KEY (var1) + ) ENGINE=MyISAM DEFAULT CHARSET=ascii CHECKSUM=1; + + +DELIMITER |; +CREATE TRIGGER testtrigger + AFTER UPDATE ON t1 FOR EACH ROW BEGIN + REPLACE INTO t2 SELECT * FROM t1 WHERE t1.var1 = NEW.var1;END| +DELIMITER ;| + +INSERT INTO t1 VALUES (1,1),(2,2),(3,3); + +UPDATE t1 SET var2 = 9 WHERE var1 IN(1,2,3); + +DROP TRIGGER testtrigger; + +DROP TABLE t1, t2; diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index 34a3a001b21..029cebb34b3 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -3877,10 +3877,10 @@ int ha_ndbcluster::start_stmt(THD *thd, thr_lock_type lock_type) ERR_RETURN(ndb->getNdbError()); no_uncommitted_rows_reset(thd); thd_ndb->stmt= trans; + thd_ndb->query_state&= NDB_QUERY_NORMAL; + m_active_trans= trans; trans_register_ha(thd, FALSE, &ndbcluster_hton); } - thd_ndb->query_state&= NDB_QUERY_NORMAL; - m_active_trans= trans; // Start of statement m_retrieve_all_fields= FALSE; @@ -6512,7 +6512,11 @@ close_scan: } if (multi_range_curr == multi_range_end) + { + Thd_ndb *thd_ndb= get_thd_ndb(current_thd); + thd_ndb->query_state&= NDB_QUERY_NORMAL; DBUG_RETURN(HA_ERR_END_OF_FILE); + } /** * Read remaining ranges From 71097eff4599b6446d2c2ebdacc9a041ce5d9102 Mon Sep 17 00:00:00 2001 From: "stewart@willster.(none)" <> Date: Thu, 1 Feb 2007 17:19:19 +1100 Subject: [PATCH 18/40] BUG#23571 missing jamEntry() after EXECUTE_DIRECT in lqh add the jamEntry() --- storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp b/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp index 725219ca006..1c7afe4d725 100644 --- a/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp +++ b/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp @@ -7208,7 +7208,8 @@ void Dblqh::execACC_ABORTCONF(Signal* signal) TRACE_OP(regTcPtr, "ACC_ABORTCONF"); signal->theData[0] = regTcPtr->tupConnectrec; EXECUTE_DIRECT(DBTUP, GSN_TUP_ABORTREQ, signal, 1); - + + jamEntry(); continueAbortLab(signal); return; }//Dblqh::execACC_ABORTCONF() From 48649030cbf3b4d3cc132a4f16dec565fa70b48e Mon Sep 17 00:00:00 2001 From: "stewart@willster.(none)" <> Date: Thu, 1 Feb 2007 17:28:41 +1100 Subject: [PATCH 19/40] BUG#25323 NDB binlog timer prints incorrect stats fix time period calculation --- sql/ha_ndbcluster_binlog.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sql/ha_ndbcluster_binlog.cc b/sql/ha_ndbcluster_binlog.cc index 38b640d5f55..0c691e61a37 100644 --- a/sql/ha_ndbcluster_binlog.cc +++ b/sql/ha_ndbcluster_binlog.cc @@ -3924,9 +3924,9 @@ restart: "%ld(%d e/s), total time %ld(%d e/s)", (ulong)gci, event_count, write_timer.elapsed_ms(), - event_count / write_timer.elapsed_ms(), + (1000*event_count) / write_timer.elapsed_ms(), gci_timer.elapsed_ms(), - event_count / gci_timer.elapsed_ms()); + (1000*event_count) / gci_timer.elapsed_ms()); #endif } } From c16251ad7c87cdab668ef48f8b57e271180b9da8 Mon Sep 17 00:00:00 2001 From: "mskold/marty@mysql.com/linux.site" <> Date: Thu, 1 Feb 2007 09:48:45 +0100 Subject: [PATCH 20/40] Bug #25522 Update with IN syntax Clustertable + Trigger leads to mysqld segfault: moved back assignment --- sql/ha_ndbcluster.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index 029cebb34b3..080abf2ce54 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -3878,10 +3878,9 @@ int ha_ndbcluster::start_stmt(THD *thd, thr_lock_type lock_type) no_uncommitted_rows_reset(thd); thd_ndb->stmt= trans; thd_ndb->query_state&= NDB_QUERY_NORMAL; - m_active_trans= trans; trans_register_ha(thd, FALSE, &ndbcluster_hton); } - + m_active_trans= trans; // Start of statement m_retrieve_all_fields= FALSE; m_retrieve_primary_key= FALSE; From 956636767e7ae963e2131f93d78181cf3ac3f9ea Mon Sep 17 00:00:00 2001 From: "lzhou/zhl@dev3-63.(none)" <> Date: Thu, 1 Feb 2007 14:37:43 +0000 Subject: [PATCH 21/40] BUG#22025 Return correct error message when transporter error occured. Modify content of message structure of last patch. --- .../ndb/src/common/debugger/EventLogger.cpp | 67 ++++++++++--------- 1 file changed, 34 insertions(+), 33 deletions(-) diff --git a/storage/ndb/src/common/debugger/EventLogger.cpp b/storage/ndb/src/common/debugger/EventLogger.cpp index d393c1d5535..3aa83937f1d 100644 --- a/storage/ndb/src/common/debugger/EventLogger.cpp +++ b/storage/ndb/src/common/debugger/EventLogger.cpp @@ -17,6 +17,7 @@ #include #include +#include #include #include @@ -537,71 +538,71 @@ void getTextTransporterError(QQQQ) { static const struct myTransporterError TransporterErrorString[]= { //TE_NO_ERROR = 0 - {0,"No error"}, + {TE_NO_ERROR,"No error"}, //TE_ERROR_CLOSING_SOCKET = 0x1 - {0x1,"Error found during closing of socket"}, + {TE_ERROR_CLOSING_SOCKET,"Error found during closing of socket"}, //TE_ERROR_IN_SELECT_BEFORE_ACCEPT = 0x2 - {0x2,"Error found before accept. The transporter will retry"}, + {TE_ERROR_IN_SELECT_BEFORE_ACCEPT,"Error found before accept. The transporter will retry"}, //TE_INVALID_MESSAGE_LENGTH = 0x3 | TE_DO_DISCONNECT - {0x3 | 0x8000,"Error found in message (invalid message length)"}, + {TE_INVALID_MESSAGE_LENGTH,"Error found in message (invalid message length)"}, //TE_INVALID_CHECKSUM = 0x4 | TE_DO_DISCONNECT - {0x4 | 0x8000,"Error found in message (checksum)"}, + {TE_INVALID_CHECKSUM,"Error found in message (checksum)"}, //TE_COULD_NOT_CREATE_SOCKET = 0x5 - {0x5,"Error found while creating socket(can't create socket)"}, + {TE_COULD_NOT_CREATE_SOCKET,"Error found while creating socket(can't create socket)"}, //TE_COULD_NOT_BIND_SOCKET = 0x6 - {0x6,"Error found while binding server socket"}, + {TE_COULD_NOT_BIND_SOCKET,"Error found while binding server socket"}, //TE_LISTEN_FAILED = 0x7 - {0x7,"Error found while listening to server socket"}, + {TE_LISTEN_FAILED,"Error found while listening to server socket"}, //TE_ACCEPT_RETURN_ERROR = 0x8 - {0x8,"Error found during accept(accept return error)"}, + {TE_ACCEPT_RETURN_ERROR,"Error found during accept(accept return error)"}, //TE_SHM_DISCONNECT = 0xb | TE_DO_DISCONNECT - {0xb | 0x8000,"The remote node has disconnected"}, + {TE_SHM_DISCONNECT,"The remote node has disconnected"}, //TE_SHM_IPC_STAT = 0xc | TE_DO_DISCONNECT - {0xc | 0x8000,"Unable to check shm segment"}, + {TE_SHM_IPC_STAT,"Unable to check shm segment"}, //TE_SHM_UNABLE_TO_CREATE_SEGMENT = 0xd - {0xd,"Unable to create shm segment"}, + {TE_SHM_UNABLE_TO_CREATE_SEGMENT,"Unable to create shm segment"}, //TE_SHM_UNABLE_TO_ATTACH_SEGMENT = 0xe - {0xe,"Unable to attach shm segment"}, + {TE_SHM_UNABLE_TO_ATTACH_SEGMENT,"Unable to attach shm segment"}, //TE_SHM_UNABLE_TO_REMOVE_SEGMENT = 0xf - {0xf,"Unable to remove shm segment"}, + {TE_SHM_UNABLE_TO_REMOVE_SEGMENT,"Unable to remove shm segment"}, //TE_TOO_SMALL_SIGID = 0x10 - {0x10,"Sig ID too small"}, + {TE_TOO_SMALL_SIGID,"Sig ID too small"}, //TE_TOO_LARGE_SIGID = 0x11 - {0x11,"Sig ID too large"}, + {TE_TOO_LARGE_SIGID,"Sig ID too large"}, //TE_WAIT_STACK_FULL = 0x12 | TE_DO_DISCONNECT - {0x12 | 0x8000,"Wait stack was full"}, + {TE_WAIT_STACK_FULL,"Wait stack was full"}, //TE_RECEIVE_BUFFER_FULL = 0x13 | TE_DO_DISCONNECT - {0x13 | 0x8000,"Receive buffer was full"}, + {TE_RECEIVE_BUFFER_FULL,"Receive buffer was full"}, //TE_SIGNAL_LOST_SEND_BUFFER_FULL = 0x14 | TE_DO_DISCONNECT - {0x14 | 0x8000,"Send buffer was full,and trying to force send fails"}, + {TE_SIGNAL_LOST_SEND_BUFFER_FULL,"Send buffer was full,and trying to force send fails"}, //TE_SIGNAL_LOST = 0x15 - {0x15,"Send failed for unknown reason(signal lost)"}, + {TE_SIGNAL_LOST,"Send failed for unknown reason(signal lost)"}, //TE_SEND_BUFFER_FULL = 0x16 - {0x16,"The send buffer was full, but sleeping for a while solved"}, + {TE_SEND_BUFFER_FULL,"The send buffer was full, but sleeping for a while solved"}, //TE_SCI_LINK_ERROR = 0x0017 - {0x0017,"There is no link from this node to the switch"}, + {TE_SCI_LINK_ERROR,"There is no link from this node to the switch"}, //TE_SCI_UNABLE_TO_START_SEQUENCE = 0x18 | TE_DO_DISCONNECT - {0x18 | 0x8000,"Could not start a sequence, because system resources are exumed or no sequence has been created"}, + {TE_SCI_UNABLE_TO_START_SEQUENCE,"Could not start a sequence, because system resources are exumed or no sequence has been created"}, //TE_SCI_UNABLE_TO_REMOVE_SEQUENCE = 0x19 | TE_DO_DISCONNECT - {0x19 | 0x8000,"Could not remove a sequence"}, + {TE_SCI_UNABLE_TO_REMOVE_SEQUENCE,"Could not remove a sequence"}, //TE_SCI_UNABLE_TO_CREATE_SEQUENCE = 0x1a | TE_DO_DISCONNECT - {0x1a | 0x8000,"Could not create a sequence, because system resources are exempted. Must reboot"}, + {TE_SCI_UNABLE_TO_CREATE_SEQUENCE,"Could not create a sequence, because system resources are exempted. Must reboot"}, //TE_SCI_UNRECOVERABLE_DATA_TFX_ERROR = 0x1b | TE_DO_DISCONNECT - {0x1b | 0x8000,"Tried to send data on redundant link but failed"}, + {TE_SCI_UNRECOVERABLE_DATA_TFX_ERROR,"Tried to send data on redundant link but failed"}, //TE_SCI_CANNOT_INIT_LOCALSEGMENT = 0x1c | TE_DO_DISCONNECT - {0x1c | 0x8000,"Cannot initialize local segment"}, + {TE_SCI_CANNOT_INIT_LOCALSEGMENT,"Cannot initialize local segment"}, //TE_SCI_CANNOT_MAP_REMOTESEGMENT = 0x1d | TE_DO_DISCONNEC - {0x1d | 0x8000,"Cannot map remote segment"}, + {TE_SCI_CANNOT_MAP_REMOTESEGMENT,"Cannot map remote segment"}, //TE_SCI_UNABLE_TO_UNMAP_SEGMENT = 0x1e | TE_DO_DISCONNECT - {0x1e | 0x8000,"Cannot free the resources used by this segment (step 1)"}, + {TE_SCI_UNABLE_TO_UNMAP_SEGMENT,"Cannot free the resources used by this segment (step 1)"}, //TE_SCI_UNABLE_TO_REMOVE_SEGMENT = 0x1f | TE_DO_DISCONNEC - {0x1f | 0x8000,"Cannot free the resources used by this segment (step 2)"}, + {TE_SCI_UNABLE_TO_REMOVE_SEGMENT,"Cannot free the resources used by this segment (step 2)"}, //TE_SCI_UNABLE_TO_DISCONNECT_SEGMENT = 0x20 | TE_DO_DISCONNECT - {0x20 | 0x8000,"Cannot disconnect from a remote segment"}, + {TE_SCI_UNABLE_TO_DISCONNECT_SEGMENT,"Cannot disconnect from a remote segment"}, //TE_SHM_IPC_PERMANENT = 0x21 - {0x21,"Shm ipc Permanent error"}, + {TE_SHM_IPC_PERMANENT,"Shm ipc Permanent error"}, //TE_SCI_UNABLE_TO_CLOSE_CHANNEL = 0x22 - {0x22,"Unable to close the sci channel and the resources allocated"} + {TE_SCI_UNABLE_TO_CLOSE_CHANNEL,"Unable to close the sci channel and the resources allocated"} }; lenth = sizeof(TransporterErrorString)/sizeof(struct myTransporterError); From 4b965407d23cb68431d7a4de1f8b74645326bf8a Mon Sep 17 00:00:00 2001 From: "jonas@eel.(none)" <> Date: Fri, 2 Feb 2007 16:14:48 +0100 Subject: [PATCH 22/40] ndb - test prg fix failure during start --- storage/ndb/test/tools/listen.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/storage/ndb/test/tools/listen.cpp b/storage/ndb/test/tools/listen.cpp index cffe256bf40..6baa9f2665a 100644 --- a/storage/ndb/test/tools/listen.cpp +++ b/storage/ndb/test/tools/listen.cpp @@ -179,6 +179,9 @@ main(int argc, const char** argv){ } } end: + for(i= 0; i<(int)event_ops.size(); i++) + MyNdb.dropEventOperation(event_ops[i]); + return NDBT_ProgramExit(NDBT_OK); } From ef38f9b780692e054e9bba386b12952f94071ea6 Mon Sep 17 00:00:00 2001 From: "jonas@eel.(none)" <> Date: Fri, 2 Feb 2007 17:07:15 +0100 Subject: [PATCH 23/40] ndb - bug#25984 - more than 7 failed node restart can cause cluster failure new behaviour is as follows: 1) node is refused to start, and should fail with message in error log that it must be restarted --initial 2) if cluster failure in this situation, node must also be restarted --intial if not SR will fail, with this message --- .../ndb/src/kernel/blocks/dbdih/DbdihMain.cpp | 29 +++++- storage/ndb/test/ndbapi/testNodeRestart.cpp | 98 +++++++++++++++++++ .../ndb/test/run-test/daily-basic-tests.txt | 4 + 3 files changed, 129 insertions(+), 2 deletions(-) diff --git a/storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp b/storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp index 3512ba10af3..163e4c61533 100644 --- a/storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp +++ b/storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp @@ -1525,10 +1525,26 @@ void Dbdih::ndbStartReqLab(Signal* signal, BlockReference ref) */ SYSFILE->lastCompletedGCI[nodePtr.i] = 0; ndbrequire(nodePtr.p->nodeStatus != NodeRecord::ALIVE); - warningEvent("Making filesystem for node %d unusable", + warningEvent("Making filesystem for node %d unusable (need --initial)", nodePtr.i); } + else if (nodePtr.p->nodeStatus == NodeRecord::ALIVE && + SYSFILE->lastCompletedGCI[nodePtr.i] == 0) + { + jam(); + CRASH_INSERTION(7170); + char buf[255]; + BaseString::snprintf(buf, sizeof(buf), + "Cluster requires this node to be started " + " with --initial as partial start has been performed" + " and this filesystem is unusable"); + progError(__LINE__, + NDBD_EXIT_SR_RESTARTCONFLICT, + buf); + ndbrequire(false); + } } + /** * This set which GCI we will try to restart to */ @@ -12515,14 +12531,23 @@ void Dbdih::newCrashedReplica(Uint32 nodeId, ReplicaRecordPtr ncrReplicaPtr) /* THAT THE NEW REPLICA IS NOT STARTED YET AND REPLICA_LAST_GCI IS*/ /* SET TO -1 TO INDICATE THAT IT IS NOT DEAD YET. */ /*----------------------------------------------------------------------*/ + Uint32 lastGCI = SYSFILE->lastCompletedGCI[nodeId]; arrGuardErr(ncrReplicaPtr.p->noCrashedReplicas + 1, 8, NDBD_EXIT_MAX_CRASHED_REPLICAS); ncrReplicaPtr.p->replicaLastGci[ncrReplicaPtr.p->noCrashedReplicas] = - SYSFILE->lastCompletedGCI[nodeId]; + lastGCI; ncrReplicaPtr.p->noCrashedReplicas = ncrReplicaPtr.p->noCrashedReplicas + 1; ncrReplicaPtr.p->createGci[ncrReplicaPtr.p->noCrashedReplicas] = 0; ncrReplicaPtr.p->replicaLastGci[ncrReplicaPtr.p->noCrashedReplicas] = (Uint32)-1; + + if (ncrReplicaPtr.p->noCrashedReplicas == 7 && lastGCI) + { + jam(); + SYSFILE->lastCompletedGCI[nodeId] = 0; + warningEvent("Making filesystem for node %d unusable (need --initial)", + nodeId); + } }//Dbdih::newCrashedReplica() /*************************************************************************/ diff --git a/storage/ndb/test/ndbapi/testNodeRestart.cpp b/storage/ndb/test/ndbapi/testNodeRestart.cpp index 5185228fd37..04e77f70c38 100644 --- a/storage/ndb/test/ndbapi/testNodeRestart.cpp +++ b/storage/ndb/test/ndbapi/testNodeRestart.cpp @@ -1178,6 +1178,101 @@ int runBug25554(NDBT_Context* ctx, NDBT_Step* step){ return NDBT_OK; } +int runBug25984(NDBT_Context* ctx, NDBT_Step* step){ + + int result = NDBT_OK; + int loops = ctx->getNumLoops(); + int records = ctx->getNumRecords(); + NdbRestarter restarter; + + if (restarter.getNumDbNodes() < 2) + return NDBT_OK; + + if (restarter.restartAll(true, true, true)) + return NDBT_FAILED; + + if (restarter.waitClusterNoStart()) + return NDBT_FAILED; + + if (restarter.startAll()) + return NDBT_FAILED; + + if (restarter.waitClusterStarted()) + return NDBT_FAILED; + + int val2[] = { DumpStateOrd::CmvmiSetRestartOnErrorInsert, 1 }; + int master = restarter.getMasterNodeId(); + int victim = restarter.getRandomNodeOtherNodeGroup(master, rand()); + if (victim == -1) + victim = restarter.getRandomNodeSameNodeGroup(master, rand()); + + restarter.restartOneDbNode(victim, false, true, true); + + for (Uint32 i = 0; i<6; i++) + { + ndbout_c("Loop: %d", i); + if (restarter.waitNodesNoStart(&victim, 1)) + return NDBT_FAILED; + + if (restarter.dumpStateOneNode(victim, val2, 2)) + return NDBT_FAILED; + + if (restarter.insertErrorInNode(victim, 7016)) + return NDBT_FAILED; + + if (restarter.startNodes(&victim, 1)) + return NDBT_FAILED; + + if (restarter.waitNodesStartPhase(&victim, 1, 2)) + return NDBT_FAILED; + } + + if (restarter.waitNodesNoStart(&victim, 1)) + return NDBT_FAILED; + + if (restarter.dumpStateOneNode(victim, val2, 2)) + return NDBT_FAILED; + + if (restarter.insertErrorInNode(victim, 7170)) + return NDBT_FAILED; + + if (restarter.startNodes(&victim, 1)) + return NDBT_FAILED; + + if (restarter.waitNodesNoStart(&victim, 1)) + return NDBT_FAILED; + + if (restarter.restartAll(false, true, true)) + return NDBT_FAILED; + + if (restarter.insertErrorInAllNodes(932)) + return NDBT_FAILED; + + if (restarter.insertErrorInNode(master, 7170)) + return NDBT_FAILED; + + if (restarter.dumpStateAllNodes(val2, 2)) + return NDBT_FAILED; + + restarter.startNodes(&master, 1); + NdbSleep_MilliSleep(3000); + restarter.startAll(); + + if (restarter.waitClusterNoStart()) + return NDBT_FAILED; + + if (restarter.restartOneDbNode(victim, true, true, true)) + return NDBT_FAILED; + + if (restarter.startAll()) + return NDBT_FAILED; + + if (restarter.waitClusterStarted()) + return NDBT_FAILED; + + return NDBT_OK; +} + NDBT_TESTSUITE(testNodeRestart); TESTCASE("NoLoad", @@ -1514,6 +1609,9 @@ TESTCASE("Bug25468", ""){ TESTCASE("Bug25554", ""){ INITIALIZER(runBug25554); } +TESTCASE("Bug25984", ""){ + INITIALIZER(runBug25984); +} NDBT_TESTSUITE_END(testNodeRestart); int main(int argc, const char** argv){ diff --git a/storage/ndb/test/run-test/daily-basic-tests.txt b/storage/ndb/test/run-test/daily-basic-tests.txt index 8d2bf6704d7..c972d432375 100644 --- a/storage/ndb/test/run-test/daily-basic-tests.txt +++ b/storage/ndb/test/run-test/daily-basic-tests.txt @@ -525,6 +525,10 @@ max-time: 1000 cmd: testNodeRestart args: -n Bug25554 T1 +max-time: 1000 +cmd: testNodeRestart +args: -n Bug25984 + # # DICT TESTS max-time: 1500 From b3fa3c8d62a1c112010895c9a5974585a830774e Mon Sep 17 00:00:00 2001 From: "tomas@poseidon.mysql.com" <> Date: Mon, 5 Feb 2007 12:04:36 +0700 Subject: [PATCH 24/40] Bug #26019 - valgrind warning ndbcluster_log_schema_op/safe_mutex_lock invalid read protect the setting of ndb_schema_share = NULL with a mutex --- sql/ha_ndbcluster_binlog.cc | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/sql/ha_ndbcluster_binlog.cc b/sql/ha_ndbcluster_binlog.cc index 38b640d5f55..e48b92ca808 100644 --- a/sql/ha_ndbcluster_binlog.cc +++ b/sql/ha_ndbcluster_binlog.cc @@ -97,6 +97,7 @@ static ulonglong ndb_latest_received_binlog_epoch= 0; NDB_SHARE *ndb_apply_status_share= 0; NDB_SHARE *ndb_schema_share= 0; +pthread_mutex_t ndb_schema_share_mutex; /* Schema object distribution handling */ HASH ndb_schema_objects; @@ -621,6 +622,7 @@ static int ndbcluster_binlog_end(THD *thd) pthread_mutex_destroy(&injector_mutex); pthread_cond_destroy(&injector_cond); + pthread_mutex_destroy(&ndb_schema_share_mutex); #endif DBUG_RETURN(0); } @@ -1271,6 +1273,16 @@ int ndbcluster_log_schema_op(THD *thd, NDB_SHARE *share, int no_storage_nodes= g_ndb_cluster_connection->no_db_nodes(); bitmap_init(&schema_subscribers, bitbuf, sizeof(bitbuf)*8, FALSE); bitmap_set_all(&schema_subscribers); + + /* begin protect ndb_schema_share */ + pthread_mutex_lock(&ndb_schema_share_mutex); + if (ndb_schema_share == 0) + { + pthread_mutex_unlock(&ndb_schema_share_mutex); + if (ndb_schema_object) + ndb_free_schema_object(&ndb_schema_object, FALSE); + DBUG_RETURN(0); + } (void) pthread_mutex_lock(&ndb_schema_share->mutex); for (i= 0; i < no_storage_nodes; i++) { @@ -1283,6 +1295,9 @@ int ndbcluster_log_schema_op(THD *thd, NDB_SHARE *share, } } (void) pthread_mutex_unlock(&ndb_schema_share->mutex); + pthread_mutex_unlock(&ndb_schema_share_mutex); + /* end protect ndb_schema_share */ + if (updated) { bitmap_clear_bit(&schema_subscribers, node_id); @@ -1478,6 +1493,14 @@ end: &abstime); if (thd->killed) break; + + /* begin protect ndb_schema_share */ + pthread_mutex_lock(&ndb_schema_share_mutex); + if (ndb_schema_share == 0) + { + pthread_mutex_unlock(&ndb_schema_share_mutex); + break; + } (void) pthread_mutex_lock(&ndb_schema_share->mutex); for (i= 0; i < no_storage_nodes; i++) { @@ -1487,6 +1510,8 @@ end: bitmap_intersect(&schema_subscribers, tmp); } (void) pthread_mutex_unlock(&ndb_schema_share->mutex); + pthread_mutex_unlock(&ndb_schema_share_mutex); + /* end protect ndb_schema_share */ /* remove any unsubscribed from ndb_schema_object->slock */ bitmap_intersect(&ndb_schema_object->slock_bitmap, &schema_subscribers); @@ -1910,8 +1935,14 @@ ndb_binlog_thread_handle_schema_event(THD *thd, Ndb *ndb, ndb_binlog_tables_inited && ndb_binlog_running) sql_print_information("NDB Binlog: ndb tables initially " "read only on reconnect."); + + /* begin protect ndb_schema_share */ + pthread_mutex_lock(&ndb_schema_share_mutex); free_share(&ndb_schema_share); ndb_schema_share= 0; + pthread_mutex_unlock(&ndb_schema_share_mutex); + /* end protect ndb_schema_share */ + close_cached_tables((THD*) 0, 0, (TABLE_LIST*) 0, FALSE); // fall through case NDBEVENT::TE_ALTER: @@ -2278,6 +2309,7 @@ int ndbcluster_binlog_start() pthread_mutex_init(&injector_mutex, MY_MUTEX_INIT_FAST); pthread_cond_init(&injector_cond, NULL); + pthread_mutex_init(&ndb_schema_share_mutex, MY_MUTEX_INIT_FAST); /* Create injector thread */ if (pthread_create(&ndb_binlog_thread, &connection_attrib, @@ -3966,8 +3998,12 @@ err: } if (ndb_schema_share) { + /* begin protect ndb_schema_share */ + pthread_mutex_lock(&ndb_schema_share_mutex); free_share(&ndb_schema_share); ndb_schema_share= 0; + pthread_mutex_unlock(&ndb_schema_share_mutex); + /* end protect ndb_schema_share */ } /* remove all event operations */ From aad58e2613f507939da7dd069779907a6ce4fc17 Mon Sep 17 00:00:00 2001 From: "tomas@poseidon.mysql.com" <> Date: Mon, 5 Feb 2007 12:51:45 +0700 Subject: [PATCH 25/40] corrected merge error --- storage/ndb/src/ndbapi/NdbOperationExec.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/storage/ndb/src/ndbapi/NdbOperationExec.cpp b/storage/ndb/src/ndbapi/NdbOperationExec.cpp index 7400ea7d86a..ba1905760c3 100644 --- a/storage/ndb/src/ndbapi/NdbOperationExec.cpp +++ b/storage/ndb/src/ndbapi/NdbOperationExec.cpp @@ -179,6 +179,8 @@ NdbOperation::prepareSend(Uint32 aTC_ConnectPtr, // Simple state is set if start and commit is set and it is // a read request. Otherwise it is set to zero. //------------------------------------------------------------- + Uint8 tReadInd = (theOperationType == ReadRequest); + Uint8 tSimpleState = tReadInd & tSimpleIndicator; tcKeyReq->transId1 = tTransId1; tcKeyReq->transId2 = tTransId2; From 475da3469764447cca39682282a372f02aac34ed Mon Sep 17 00:00:00 2001 From: "tomas@poseidon.mysql.com" <> Date: Mon, 5 Feb 2007 13:21:18 +0700 Subject: [PATCH 26/40] Bug #26021 - valgrind reports error regarding handle_trailing_share and client thread share usage - add ndb_share connect_count to decide if share can be reused to setup replication --- sql/ha_ndbcluster.cc | 28 +++++++++++++++++++--------- sql/ha_ndbcluster.h | 1 + sql/ha_ndbcluster_binlog.cc | 17 ++++++++++++++--- sql/ha_ndbcluster_binlog.h | 5 ----- 4 files changed, 34 insertions(+), 17 deletions(-) diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index 21697be83aa..30515564a60 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -6837,7 +6837,7 @@ static int ndbcluster_end(handlerton *hton, ha_panic_function type) fprintf(stderr, "NDB: table share %s with use_count %d not freed\n", share->key, share->use_count); #endif - real_free_share(&share); + ndbcluster_real_free_share(&share); } pthread_mutex_unlock(&ndbcluster_mutex); } @@ -7449,14 +7449,20 @@ int handle_trailing_share(NDB_SHARE *share) bzero((char*) &table_list,sizeof(table_list)); table_list.db= share->db; table_list.alias= table_list.table_name= share->table_name; + safe_mutex_assert_owner(&LOCK_open); close_cached_tables(thd, 0, &table_list, TRUE); pthread_mutex_lock(&ndbcluster_mutex); if (!--share->use_count) { - DBUG_PRINT("info", ("NDB_SHARE: close_cashed_tables %s freed share.", - share->key)); - real_free_share(&share); + if (ndb_extra_logging) + sql_print_information("NDB_SHARE: trailing share %s(connect_count: %u) " + "released by close_cached_tables at " + "connect_count: %u", + share->key, + share->connect_count, + g_ndb_cluster_connection->get_connect_count()); + ndbcluster_real_free_share(&share); DBUG_RETURN(0); } @@ -7466,10 +7472,14 @@ int handle_trailing_share(NDB_SHARE *share) */ if (share->state != NSS_DROPPED && !--share->use_count) { - DBUG_PRINT("info", ("NDB_SHARE: %s already exists, " - "use_count=%d state != NSS_DROPPED.", - share->key, share->use_count)); - real_free_share(&share); + if (ndb_extra_logging) + sql_print_information("NDB_SHARE: trailing share %s(connect_count: %u) " + "released after NSS_DROPPED check " + "at connect_count: %u", + share->key, + share->connect_count, + g_ndb_cluster_connection->get_connect_count()); + ndbcluster_real_free_share(&share); DBUG_RETURN(0); } DBUG_PRINT("error", ("NDB_SHARE: %s already exists use_count=%d.", @@ -7736,7 +7746,7 @@ void ndbcluster_free_share(NDB_SHARE **share, bool have_lock) (*share)->util_lock= 0; if (!--(*share)->use_count) { - real_free_share(share); + ndbcluster_real_free_share(share); } else { diff --git a/sql/ha_ndbcluster.h b/sql/ha_ndbcluster.h index 5b6900766b6..63665fde0f8 100644 --- a/sql/ha_ndbcluster.h +++ b/sql/ha_ndbcluster.h @@ -108,6 +108,7 @@ typedef struct st_ndbcluster_share { char *table_name; Ndb::TupleIdRange tuple_id_range; #ifdef HAVE_NDB_BINLOG + uint32 connect_count; uint32 flags; NdbEventOperation *op; NdbEventOperation *op_old; // for rename table diff --git a/sql/ha_ndbcluster_binlog.cc b/sql/ha_ndbcluster_binlog.cc index e48b92ca808..5a0089e59ac 100644 --- a/sql/ha_ndbcluster_binlog.cc +++ b/sql/ha_ndbcluster_binlog.cc @@ -362,6 +362,8 @@ void ndbcluster_binlog_init_share(NDB_SHARE *share, TABLE *_table) int do_event_op= ndb_binlog_running; DBUG_ENTER("ndbcluster_binlog_init_share"); + share->connect_count= g_ndb_cluster_connection->get_connect_count(); + share->op= 0; share->table= 0; @@ -605,7 +607,7 @@ static int ndbcluster_binlog_end(THD *thd) ("table->s->db.table_name: %s.%s", share->table->s->db.str, share->table->s->table_name.str)); if (share->state != NSS_DROPPED && !--share->use_count) - real_free_share(&share); + ndbcluster_real_free_share(&share); else { DBUG_PRINT("share", @@ -2443,11 +2445,20 @@ int ndbcluster_create_binlog_setup(Ndb *ndb, const char *key, pthread_mutex_unlock(&ndbcluster_mutex); DBUG_RETURN(1); } - handle_trailing_share(share); + if (share->connect_count != + g_ndb_cluster_connection->get_connect_count()) + { + handle_trailing_share(share); + share= NULL; + } } /* Create share which is needed to hold replication information */ - if (!(share= get_share(key, 0, TRUE, TRUE))) + if (share) + { + ++share->use_count; + } + else if (!(share= get_share(key, 0, TRUE, TRUE))) { sql_print_error("NDB Binlog: " "allocating table share for %s failed", key); diff --git a/sql/ha_ndbcluster_binlog.h b/sql/ha_ndbcluster_binlog.h index 44183c6de9d..00fc689f061 100644 --- a/sql/ha_ndbcluster_binlog.h +++ b/sql/ha_ndbcluster_binlog.h @@ -208,11 +208,6 @@ inline void free_share(NDB_SHARE **share, bool have_lock= FALSE) ndbcluster_free_share(share, have_lock); } -inline void real_free_share(NDB_SHARE **share) -{ - ndbcluster_real_free_share(share); -} - inline Thd_ndb * get_thd_ndb(THD *thd) { return (Thd_ndb *) thd->ha_data[ndbcluster_hton->slot]; } From cb9e8bcad80be8e65e3ad6b08d0632c967c982e3 Mon Sep 17 00:00:00 2001 From: "knielsen@ymer.(none)" <> Date: Mon, 5 Feb 2007 10:50:08 +0100 Subject: [PATCH 27/40] Fix false Valgrind warning. On some compiler/platform combination, an assignment of form *p= *p would map to a memcpy() call, and Valgrind flags this as an overlapped memcpy() error. Fix by prefixing *p= *q with if(p!=q) when building for Valgrind (HAVE_purify). --- sql/sql_select.cc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index dcf1f0cfc79..ea69eb72b51 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -3520,7 +3520,11 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab, continue; } - *save_pos= *use; +#ifdef HAVE_purify + /* Valgrind complains about overlapped memcpy when save_pos==use. */ + if (save_pos != use) +#endif + *save_pos= *use; prev=use; found_eq_constant= !use->used_tables; /* Save ptr to first use */ From addb495339f9a64550930ae61fe9796b8b76ea8a Mon Sep 17 00:00:00 2001 From: "tomas@poseidon.mysql.com" <> Date: Tue, 6 Feb 2007 00:09:45 +0700 Subject: [PATCH 28/40] Bug #26021 valgrind warning handle_trailing_share/ndbcluster_free_share invalid read - revert bugfix, needs more work --- sql/ha_ndbcluster_binlog.cc | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/sql/ha_ndbcluster_binlog.cc b/sql/ha_ndbcluster_binlog.cc index 5a0089e59ac..55364f31764 100644 --- a/sql/ha_ndbcluster_binlog.cc +++ b/sql/ha_ndbcluster_binlog.cc @@ -2445,8 +2445,10 @@ int ndbcluster_create_binlog_setup(Ndb *ndb, const char *key, pthread_mutex_unlock(&ndbcluster_mutex); DBUG_RETURN(1); } +#ifdef NOT_YET if (share->connect_count != g_ndb_cluster_connection->get_connect_count()) +#endif { handle_trailing_share(share); share= NULL; @@ -2454,11 +2456,14 @@ int ndbcluster_create_binlog_setup(Ndb *ndb, const char *key, } /* Create share which is needed to hold replication information */ +#ifdef NOT_YET if (share) { ++share->use_count; } - else if (!(share= get_share(key, 0, TRUE, TRUE))) + else +#endif + if (!(share= get_share(key, 0, TRUE, TRUE))) { sql_print_error("NDB Binlog: " "allocating table share for %s failed", key); From 8619dfc22290e67d28bbf633e4f2a2c893b51528 Mon Sep 17 00:00:00 2001 From: "jonas@eel.(none)" <> Date: Mon, 5 Feb 2007 19:47:19 +0100 Subject: [PATCH 29/40] ndb - bug#25801 - improve error message if starting wo/ enough REDO - decrease likelyhood of trying to start too early --- storage/ndb/include/mgmapi/ndbd_exit_codes.h | 1 + .../ndb/src/kernel/blocks/dbdih/DbdihMain.cpp | 59 +++++++++- storage/ndb/src/kernel/blocks/qmgr/Qmgr.hpp | 1 + .../ndb/src/kernel/blocks/qmgr/QmgrMain.cpp | 105 ++++++++++++++---- .../ndb/src/kernel/error/ndbd_exit_codes.c | 1 + 5 files changed, 139 insertions(+), 28 deletions(-) diff --git a/storage/ndb/include/mgmapi/ndbd_exit_codes.h b/storage/ndb/include/mgmapi/ndbd_exit_codes.h index 982aaf5f925..71802fd8fcc 100644 --- a/storage/ndb/include/mgmapi/ndbd_exit_codes.h +++ b/storage/ndb/include/mgmapi/ndbd_exit_codes.h @@ -146,6 +146,7 @@ typedef ndbd_exit_classification_enum ndbd_exit_classification; #define NDBD_EXIT_AFS_READ_UNDERFLOW 2816 #define NDBD_EXIT_INVALID_LCP_FILE 2352 +#define NDBD_EXIT_INSUFFICENT_NODES 2353 const char * ndbd_exit_message(int faultId, ndbd_exit_classification *cl); diff --git a/storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp b/storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp index 163e4c61533..9cd7dbfc59b 100644 --- a/storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp +++ b/storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp @@ -1194,11 +1194,58 @@ void Dbdih::execTAB_COMMITREQ(Signal* signal) void Dbdih::execDIH_RESTARTREQ(Signal* signal) { jamEntry(); - cntrlblockref = signal->theData[0]; - if(m_ctx.m_config.getInitialStart()){ - sendSignal(cntrlblockref, GSN_DIH_RESTARTREF, signal, 1, JBB); - } else { - readGciFileLab(signal); + if (signal->theData[0]) + { + jam(); + cntrlblockref = signal->theData[0]; + if(m_ctx.m_config.getInitialStart()){ + sendSignal(cntrlblockref, GSN_DIH_RESTARTREF, signal, 1, JBB); + } else { + readGciFileLab(signal); + } + } + else + { + /** + * Precondition, (not checked) + * atleast 1 node in each node group + */ + Uint32 i; + NdbNodeBitmask mask; + mask.assign(NdbNodeBitmask::Size, signal->theData + 1); + Uint32 *node_gcis = signal->theData+1+NdbNodeBitmask::Size; + Uint32 node_group_gcis[MAX_NDB_NODES+1]; + bzero(node_group_gcis, sizeof(node_group_gcis)); + for (i = 0; inodeGroups); + ndbrequire(ng < MAX_NDB_NODES); + Uint32 gci = node_gcis[i]; + if (gci > node_group_gcis[ng]) + { + jam(); + node_group_gcis[ng] = gci; + } + } + } + for (i = 0; itheData[0] = i; + return; + } + } + signal->theData[0] = MAX_NDB_NODES; + return; } return; }//Dbdih::execDIH_RESTARTREQ() @@ -12391,7 +12438,7 @@ void Dbdih::makeNodeGroups(Uint32 nodeArray[]) (buf, sizeof(buf), "Illegal initial start, no alive node in nodegroup %u", i); progError(__LINE__, - NDBD_EXIT_SR_RESTARTCONFLICT, + NDBD_EXIT_INSUFFICENT_NODES, buf); } diff --git a/storage/ndb/src/kernel/blocks/qmgr/Qmgr.hpp b/storage/ndb/src/kernel/blocks/qmgr/Qmgr.hpp index 92b8b5d3306..e59268ecaed 100644 --- a/storage/ndb/src/kernel/blocks/qmgr/Qmgr.hpp +++ b/storage/ndb/src/kernel/blocks/qmgr/Qmgr.hpp @@ -128,6 +128,7 @@ public: Uint32 m_president_candidate_gci; Uint16 m_regReqReqSent; Uint16 m_regReqReqRecv; + Uint32 m_node_gci[MAX_NDB_NODES]; } c_start; NdbNodeBitmask c_definedNodes; // DB nodes in config diff --git a/storage/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp b/storage/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp index 4f3c4263fee..3db5915f41a 100644 --- a/storage/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp +++ b/storage/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp @@ -1093,7 +1093,8 @@ void Qmgr::execCM_REGREF(Signal* signal) jam(); c_start.m_starting_nodes_w_log.set(TaddNodeno); } - + c_start.m_node_gci[TaddNodeno] = node_gci; + skip_nodes.bitAND(c_definedNodes); c_start.m_skip_nodes.bitOR(skip_nodes); @@ -1242,6 +1243,7 @@ Qmgr::check_startup(Signal* signal) wait.bitANDC(tmp); Uint32 retVal = 0; + Uint32 incompleteng = MAX_NDB_NODES; // Illegal value NdbNodeBitmask report_mask; if ((c_start.m_latest_gci == 0) || @@ -1327,7 +1329,7 @@ Qmgr::check_startup(Signal* signal) report_mask.assign(c_definedNodes); report_mask.bitANDC(c_start.m_starting_nodes); retVal = 1; - goto start_report; + goto check_log; case CheckNodeGroups::Partitioning: ndbrequire(result != CheckNodeGroups::Lose); signal->theData[1] = @@ -1335,7 +1337,7 @@ Qmgr::check_startup(Signal* signal) report_mask.assign(c_definedNodes); report_mask.bitANDC(c_start.m_starting_nodes); retVal = 1; - goto start_report; + goto check_log; } } @@ -1359,12 +1361,7 @@ Qmgr::check_startup(Signal* signal) case CheckNodeGroups::Partitioning: if (now < partitioned_timeout && result != CheckNodeGroups::Win) { - signal->theData[1] = c_restartPartionedTimeout == (Uint32) ~0 ? 4 : 5; - signal->theData[2] = Uint32((partitioned_timeout - now + 500) / 1000); - report_mask.assign(c_definedNodes); - report_mask.bitANDC(c_start.m_starting_nodes); - retVal = 0; - goto start_report; + goto missinglog; } // Fall through... case CheckNodeGroups::Win: @@ -1372,12 +1369,61 @@ Qmgr::check_startup(Signal* signal) all ? 0x8001 : (result == CheckNodeGroups::Win ? 0x8002 : 0x8003); report_mask.assign(c_definedNodes); report_mask.bitANDC(c_start.m_starting_nodes); - retVal = 1; - goto start_report; + retVal = 2; + goto check_log; } } ndbrequire(false); +check_log: + jam(); + { + Uint32 save[4+4*NdbNodeBitmask::Size]; + memcpy(save, signal->theData, sizeof(save)); + + signal->theData[0] = 0; + c_start.m_starting_nodes.copyto(NdbNodeBitmask::Size, signal->theData+1); + memcpy(signal->theData+1+NdbNodeBitmask::Size, c_start.m_node_gci, + 4*MAX_NDB_NODES); + EXECUTE_DIRECT(DBDIH, GSN_DIH_RESTARTREQ, signal, + 1+NdbNodeBitmask::Size+MAX_NDB_NODES); + + incompleteng = signal->theData[0]; + memcpy(signal->theData, save, sizeof(save)); + + if (incompleteng != MAX_NDB_NODES) + { + jam(); + if (retVal == 1) + { + jam(); + goto incomplete_log; + } + else if (retVal == 2) + { + if (now <= partitioned_timeout) + { + jam(); + goto missinglog; + } + else + { + goto incomplete_log; + } + } + ndbrequire(false); + } + } + goto start_report; + +missinglog: + signal->theData[1] = c_restartPartionedTimeout == (Uint32) ~0 ? 4 : 5; + signal->theData[2] = Uint32((partitioned_timeout - now + 500) / 1000); + report_mask.assign(c_definedNodes); + report_mask.bitANDC(c_start.m_starting_nodes); + retVal = 0; + goto start_report; + start_report: jam(); { @@ -1396,17 +1442,32 @@ start_report: missing_nodegroup: jam(); - char buf[100], mask1[100], mask2[100]; - c_start.m_starting_nodes.getText(mask1); - tmp.assign(c_start.m_starting_nodes); - tmp.bitANDC(c_start.m_starting_nodes_w_log); - tmp.getText(mask2); - BaseString::snprintf(buf, sizeof(buf), - "Unable to start missing node group! " - " starting: %s (missing fs for: %s)", - mask1, mask2); - progError(__LINE__, NDBD_EXIT_SR_RESTARTCONFLICT, buf); - return 0; // Deadcode + { + char buf[100], mask1[100], mask2[100]; + c_start.m_starting_nodes.getText(mask1); + tmp.assign(c_start.m_starting_nodes); + tmp.bitANDC(c_start.m_starting_nodes_w_log); + tmp.getText(mask2); + BaseString::snprintf(buf, sizeof(buf), + "Unable to start missing node group! " + " starting: %s (missing fs for: %s)", + mask1, mask2); + progError(__LINE__, NDBD_EXIT_INSUFFICENT_NODES, buf); + return 0; // Deadcode + } + +incomplete_log: + jam(); + { + char buf[100], mask1[100]; + c_start.m_starting_nodes.getText(mask1); + BaseString::snprintf(buf, sizeof(buf), + "Incomplete log for node group: %d! " + " starting nodes: %s", + incompleteng, mask1); + progError(__LINE__, NDBD_EXIT_INSUFFICENT_NODES, buf); + return 0; // Deadcode + } } void diff --git a/storage/ndb/src/kernel/error/ndbd_exit_codes.c b/storage/ndb/src/kernel/error/ndbd_exit_codes.c index 14a55816036..9987f9e0ecb 100644 --- a/storage/ndb/src/kernel/error/ndbd_exit_codes.c +++ b/storage/ndb/src/kernel/error/ndbd_exit_codes.c @@ -160,6 +160,7 @@ static const ErrStruct errArray[] = {NDBD_EXIT_AFS_READ_UNDERFLOW , XFI, "Read underflow"}, {NDBD_EXIT_INVALID_LCP_FILE, XFI, "Invalid LCP" }, + {NDBD_EXIT_INSUFFICENT_NODES, XRE, "Insufficent nodes for system restart" }, /* Sentinel */ {0, XUE, From 35bfea94669d349945be04afe44dcca047b25eab Mon Sep 17 00:00:00 2001 From: "jonas@eel.(none)" <> Date: Mon, 5 Feb 2007 20:28:11 +0100 Subject: [PATCH 30/40] ndb - Add abort option to lots of Hugo code, as it assumes it and default value has changed --- storage/ndb/test/src/HugoTransactions.cpp | 214 ++-------------------- storage/ndb/test/src/UtilTransactions.cpp | 22 +-- 2 files changed, 30 insertions(+), 206 deletions(-) diff --git a/storage/ndb/test/src/HugoTransactions.cpp b/storage/ndb/test/src/HugoTransactions.cpp index 35c15a497fe..a628726d372 100644 --- a/storage/ndb/test/src/HugoTransactions.cpp +++ b/storage/ndb/test/src/HugoTransactions.cpp @@ -94,7 +94,7 @@ HugoTransactions::scanReadRecords(Ndb* pNdb, } } - check = pTrans->execute(NoCommit); + check = pTrans->execute(NoCommit, AbortOnError); if( check == -1 ) { const NdbError err = pTrans->getNdbError(); if (err.status == NdbError::TemporaryError){ @@ -245,183 +245,7 @@ HugoTransactions::scanReadRecords(Ndb* pNdb, } } - check = pTrans->execute(NoCommit); - 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 = pOp->nextResult(true)) == 0){ - rows++; - if (calc.verifyRowValues(&row) != 0){ - closeTransaction(pNdb); - return NDBT_FAILED; - } - - if (abortCount == rows && abortTrans == true){ - ndbout << "Scan is aborted" << endl; - g_info << "Scan is aborted" << endl; - pOp->close(); - if( check == -1 ) { - ERR(pTrans->getNdbError()); - closeTransaction(pNdb); - return NDBT_FAILED; - } - - closeTransaction(pNdb); - return NDBT_OK; - } - } - if (eof == -1) { - const NdbError err = pTrans->getNdbError(); - - if (err.status == NdbError::TemporaryError){ - ERR_INFO(err); - closeTransaction(pNdb); - 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; - } - - closeTransaction(pNdb); - - g_info << rows << " rows have been read" << endl; - if (records != 0 && rows != records){ - g_err << "Check expected number of records failed" << endl - << " expected=" << records <<", " << endl - << " read=" << rows << endl; - return NDBT_FAILED; - } - - return NDBT_OK; - } - return NDBT_FAILED; -} - - -#define RESTART_SCAN 99 - -int -HugoTransactions::scanUpdateRecords(Ndb* pNdb, - int records, - int abortPercent, - int parallelism){ - if(m_defaultScanUpdateMethod == 1){ - return scanUpdateRecords1(pNdb, records, abortPercent, parallelism); - } else if(m_defaultScanUpdateMethod == 2){ - return scanUpdateRecords2(pNdb, records, abortPercent, parallelism); - } else { - return scanUpdateRecords3(pNdb, records, abortPercent, parallelism); - } -} - -// Scan all records exclusive and update -// them one by one -int -HugoTransactions::scanUpdateRecords1(Ndb* pNdb, - int records, - int abortPercent, - int parallelism){ - return scanUpdateRecords3(pNdb, records, abortPercent, 1); -} - -// Scan all records exclusive and update -// them batched by asking nextScanResult to -// give us all cached records before fetching new -// records from db -int -HugoTransactions::scanUpdateRecords2(Ndb* pNdb, - int records, - int abortPercent, - int parallelism){ - return scanUpdateRecords3(pNdb, records, abortPercent, parallelism); -} - -int -HugoTransactions::scanUpdateRecords3(Ndb* pNdb, - int records, - int abortPercent, - int parallelism){ - int retryAttempt = 0; - int check, a; - NdbScanOperation *pOp; - - - while (true){ -restart: - if (retryAttempt++ >= m_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(); - ERR(err); - if (err.status == NdbError::TemporaryError){ - NdbSleep_MilliSleep(50); - continue; - } - return NDBT_FAILED; - } - - pOp = getScanOperation(pTrans); - if (pOp == NULL) { - ERR(pTrans->getNdbError()); - closeTransaction(pNdb); - return NDBT_FAILED; - } - - if( pOp->readTuplesExclusive(parallelism) ) { - ERR(pTrans->getNdbError()); - closeTransaction(pNdb); - return NDBT_FAILED; - } - - // Read all attributes from this table - for(a=0; agetValue(tab.getColumn(a)->getName())) == NULL){ - ERR(pTrans->getNdbError()); - closeTransaction(pNdb); - return NDBT_FAILED; - } - } - - check = pTrans->execute(NoCommit); + check = pTrans->execute(NoCommit, AbortOnError); if( check == -1 ) { const NdbError err = pTrans->getNdbError(); ERR(err); @@ -474,7 +298,7 @@ restart: } while((check = pOp->nextResult(false)) == 0); if(check != -1){ - check = pTrans->execute(Commit); + check = pTrans->execute(Commit, AbortOnError); if(check != -1) m_latest_gci = pTrans->getGCI(); pTrans->restart(); @@ -587,14 +411,14 @@ HugoTransactions::loadTable(Ndb* pNdb, closeTrans = false; if (!abort) { - check = pTrans->execute( Commit ); + check = pTrans->execute(Commit, AbortOnError); if(check != -1) m_latest_gci = pTrans->getGCI(); pTrans->restart(); } else { - check = pTrans->execute( NoCommit ); + check = pTrans->execute(NoCommit, AbortOnError); if (check != -1) { check = pTrans->execute( Rollback ); @@ -603,7 +427,7 @@ HugoTransactions::loadTable(Ndb* pNdb, } } else { closeTrans = false; - check = pTrans->execute( NoCommit ); + check = pTrans->execute(NoCommit, AbortOnError); } if(check == -1 ) { const NdbError err = pTrans->getNdbError(); @@ -717,7 +541,7 @@ HugoTransactions::fillTable(Ndb* pNdb, } // Execute the transaction and insert the record - check = pTrans->execute( Commit, CommitAsMuchAsPossible ); + check = pTrans->execute(Commit, CommitAsMuchAsPossible ); if(check == -1 ) { const NdbError err = pTrans->getNdbError(); closeTransaction(pNdb); @@ -829,7 +653,7 @@ HugoTransactions::pkReadRecords(Ndb* pNdb, return NDBT_FAILED; } - check = pTrans->execute(Commit); + check = pTrans->execute(Commit, AbortOnError); if( check == -1 ) { const NdbError err = pTrans->getNdbError(); @@ -950,7 +774,7 @@ HugoTransactions::pkUpdateRecords(Ndb* pNdb, return NDBT_FAILED; } - check = pTrans->execute(NoCommit); + check = pTrans->execute(NoCommit, AbortOnError); if( check == -1 ) { const NdbError err = pTrans->getNdbError(); @@ -991,7 +815,7 @@ HugoTransactions::pkUpdateRecords(Ndb* pNdb, if(check != 2) break; - if((check = pTrans->execute(NoCommit)) != 0) + if((check = pTrans->execute(NoCommit, , AbortOnError)) != 0) break; } if(check != 1 || rows_found != batch) @@ -1019,7 +843,7 @@ HugoTransactions::pkUpdateRecords(Ndb* pNdb, return NDBT_FAILED; } } - check = pTrans->execute(Commit); + check = pTrans->execute(Commit, AbortOnError); } if( check == -1 ) { const NdbError err = pTrans->getNdbError(); @@ -1119,7 +943,7 @@ HugoTransactions::pkInterpretedUpdateRecords(Ndb* pNdb, } } - check = pTrans->execute(NoCommit); + check = pTrans->execute(NoCommit, AbortOnError); if( check == -1 ) { const NdbError err = pTrans->getNdbError(); @@ -1194,7 +1018,7 @@ HugoTransactions::pkInterpretedUpdateRecords(Ndb* pNdb, - check = pTrans->execute(Commit); + check = pTrans->execute(Commit, AbortOnError); if( check == -1 ) { const NdbError err = pTrans->getNdbError(); @@ -1274,7 +1098,7 @@ HugoTransactions::pkDelRecords(Ndb* pNdb, return NDBT_FAILED; } - check = pTrans->execute(Commit); + check = pTrans->execute(Commit, AbortOnError); if( check == -1) { const NdbError err = pTrans->getNdbError(); @@ -1387,7 +1211,7 @@ HugoTransactions::lockRecords(Ndb* pNdb, int lockCount = lockTime / sleepInterval; int commitCount = 0; do { - check = pTrans->execute(NoCommit); + check = pTrans->execute(NoCommit, AbortOnError); if( check == -1) { const NdbError err = pTrans->getNdbError(); @@ -1413,7 +1237,7 @@ HugoTransactions::lockRecords(Ndb* pNdb, } while (commitCount < lockCount); // Really commit the trans, puuh! - check = pTrans->execute(Commit); + check = pTrans->execute(Commit, AbortOnError); if( check == -1) { const NdbError err = pTrans->getNdbError(); @@ -1543,7 +1367,7 @@ HugoTransactions::indexReadRecords(Ndb* pNdb, } } - check = pTrans->execute(Commit); + check = pTrans->execute(Commit, AbortOnError); check = (check == -1 ? -1 : !ordered ? check : sOp->nextResult(true)); if( check == -1 ) { const NdbError err = pTrans->getNdbError(); @@ -1684,7 +1508,7 @@ HugoTransactions::indexUpdateRecords(Ndb* pNdb, } } - check = pTrans->execute(NoCommit); + check = pTrans->execute(NoCommit, AbortOnError); check = (check == -1 ? -1 : !ordered ? check : sOp->nextResult(true)); if( check == -1 ) { const NdbError err = pTrans->getNdbError(); @@ -1756,7 +1580,7 @@ HugoTransactions::indexUpdateRecords(Ndb* pNdb, } } - check = pTrans->execute(Commit); + check = pTrans->execute(Commit, AbortOnError); if( check == -1 ) { const NdbError err = pTrans->getNdbError(); ERR(err); diff --git a/storage/ndb/test/src/UtilTransactions.cpp b/storage/ndb/test/src/UtilTransactions.cpp index acb8babf512..fd9ab2954f9 100644 --- a/storage/ndb/test/src/UtilTransactions.cpp +++ b/storage/ndb/test/src/UtilTransactions.cpp @@ -121,7 +121,7 @@ UtilTransactions::clearTable3(Ndb* pNdb, goto failed; } - if(pTrans->execute(NoCommit) != 0){ + if(pTrans->execute(NoCommit, AbortOnError) != 0){ err = pTrans->getNdbError(); if(err.status == NdbError::TemporaryError){ ERR(err); @@ -141,7 +141,7 @@ UtilTransactions::clearTable3(Ndb* pNdb, } while((check = pOp->nextResult(false)) == 0); if(check != -1){ - check = pTrans->execute(Commit); + check = pTrans->execute(Commit, AbortOnError); pTrans->restart(); } @@ -245,7 +245,7 @@ UtilTransactions::copyTableData(Ndb* pNdb, } } - check = pTrans->execute(NoCommit); + check = pTrans->execute(NoCommit, AbortOnError); if( check == -1 ) { ERR(pTrans->getNdbError()); closeTransaction(pNdb); @@ -262,7 +262,7 @@ UtilTransactions::copyTableData(Ndb* pNdb, } } while((eof = pOp->nextResult(false)) == 0); - check = pTrans->execute(Commit); + check = pTrans->execute(Commit, AbortOnError); pTrans->restart(); if( check == -1 ) { const NdbError err = pTrans->getNdbError(); @@ -414,7 +414,7 @@ UtilTransactions::scanReadRecords(Ndb* pNdb, } // ************************************************* - check = pTrans->execute(NoCommit); + check = pTrans->execute(NoCommit, AbortOnError); if( check == -1 ) { const NdbError err = pTrans->getNdbError(); @@ -520,7 +520,7 @@ UtilTransactions::selectCount(Ndb* pNdb, } - check = pTrans->execute(NoCommit); + check = pTrans->execute(NoCommit, AbortOnError); if( check == -1 ) { ERR(pTrans->getNdbError()); closeTransaction(pNdb); @@ -693,7 +693,7 @@ restart: } } - check = pTrans->execute(NoCommit); + check = pTrans->execute(NoCommit, AbortOnError); if( check == -1 ) { const NdbError err = pTrans->getNdbError(); @@ -956,7 +956,7 @@ UtilTransactions::readRowFromTableAndIndex(Ndb* pNdb, printf("\n"); #endif scanTrans->refresh(); - check = pTrans1->execute(Commit); + check = pTrans1->execute(Commit, AbortOnError); if( check == -1 ) { const NdbError err = pTrans1->getNdbError(); @@ -1078,7 +1078,7 @@ UtilTransactions::verifyOrderedIndex(Ndb* pNdb, abort(); } - check = pTrans->execute(NoCommit); + check = pTrans->execute(NoCommit, AbortOnError); if( check == -1 ) { const NdbError err = pTrans->getNdbError(); @@ -1137,7 +1137,7 @@ UtilTransactions::verifyOrderedIndex(Ndb* pNdb, goto error; } - check = pTrans->execute(NoCommit); + check = pTrans->execute(NoCommit, AbortOnError); if(check) goto error; @@ -1376,7 +1376,7 @@ loop: } } - if( pTrans->execute(NoCommit) == -1 ) { + if( pTrans->execute(NoCommit, AbortOnError) == -1 ) { ERR(err= pTrans->getNdbError()); goto error; } From 3edab3e4c8ba8c8381de892c9e3852254734ee5b Mon Sep 17 00:00:00 2001 From: "jonas@eel.(none)" <> Date: Mon, 5 Feb 2007 21:38:16 +0100 Subject: [PATCH 31/40] ndb - some more hugo abort option fix --- storage/ndb/test/src/HugoTransactions.cpp | 180 +++++++++++++++++++++- storage/ndb/test/src/UtilTransactions.cpp | 3 +- 2 files changed, 180 insertions(+), 3 deletions(-) diff --git a/storage/ndb/test/src/HugoTransactions.cpp b/storage/ndb/test/src/HugoTransactions.cpp index a628726d372..34f77d9a2da 100644 --- a/storage/ndb/test/src/HugoTransactions.cpp +++ b/storage/ndb/test/src/HugoTransactions.cpp @@ -245,6 +245,182 @@ HugoTransactions::scanReadRecords(Ndb* pNdb, } } + check = pTrans->execute(NoCommit, AbortOnError); + 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 = pOp->nextResult(true)) == 0){ + rows++; + if (calc.verifyRowValues(&row) != 0){ + closeTransaction(pNdb); + return NDBT_FAILED; + } + + if (abortCount == rows && abortTrans == true){ + ndbout << "Scan is aborted" << endl; + g_info << "Scan is aborted" << endl; + pOp->close(); + if( check == -1 ) { + ERR(pTrans->getNdbError()); + closeTransaction(pNdb); + return NDBT_FAILED; + } + + closeTransaction(pNdb); + return NDBT_OK; + } + } + if (eof == -1) { + const NdbError err = pTrans->getNdbError(); + + if (err.status == NdbError::TemporaryError){ + ERR_INFO(err); + closeTransaction(pNdb); + 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; + } + + closeTransaction(pNdb); + + g_info << rows << " rows have been read" << endl; + if (records != 0 && rows != records){ + g_err << "Check expected number of records failed" << endl + << " expected=" << records <<", " << endl + << " read=" << rows << endl; + return NDBT_FAILED; + } + + return NDBT_OK; + } + return NDBT_FAILED; +} + + +#define RESTART_SCAN 99 + +int +HugoTransactions::scanUpdateRecords(Ndb* pNdb, + int records, + int abortPercent, + int parallelism){ + if(m_defaultScanUpdateMethod == 1){ + return scanUpdateRecords1(pNdb, records, abortPercent, parallelism); + } else if(m_defaultScanUpdateMethod == 2){ + return scanUpdateRecords2(pNdb, records, abortPercent, parallelism); + } else { + return scanUpdateRecords3(pNdb, records, abortPercent, parallelism); + } +} + +// Scan all records exclusive and update +// them one by one +int +HugoTransactions::scanUpdateRecords1(Ndb* pNdb, + int records, + int abortPercent, + int parallelism){ + return scanUpdateRecords3(pNdb, records, abortPercent, 1); +} + +// Scan all records exclusive and update +// them batched by asking nextScanResult to +// give us all cached records before fetching new +// records from db +int +HugoTransactions::scanUpdateRecords2(Ndb* pNdb, + int records, + int abortPercent, + int parallelism){ + return scanUpdateRecords3(pNdb, records, abortPercent, parallelism); +} + +int +HugoTransactions::scanUpdateRecords3(Ndb* pNdb, + int records, + int abortPercent, + int parallelism){ + int retryAttempt = 0; + int check, a; + NdbScanOperation *pOp; + + + while (true){ +restart: + if (retryAttempt++ >= m_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(); + ERR(err); + if (err.status == NdbError::TemporaryError){ + NdbSleep_MilliSleep(50); + continue; + } + return NDBT_FAILED; + } + + pOp = getScanOperation(pTrans); + if (pOp == NULL) { + ERR(pTrans->getNdbError()); + closeTransaction(pNdb); + return NDBT_FAILED; + } + + if( pOp->readTuplesExclusive(parallelism) ) { + ERR(pTrans->getNdbError()); + closeTransaction(pNdb); + return NDBT_FAILED; + } + + // Read all attributes from this table + for(a=0; agetValue(tab.getColumn(a)->getName())) == NULL){ + ERR(pTrans->getNdbError()); + closeTransaction(pNdb); + return NDBT_FAILED; + } + } + check = pTrans->execute(NoCommit, AbortOnError); if( check == -1 ) { const NdbError err = pTrans->getNdbError(); @@ -541,7 +717,7 @@ HugoTransactions::fillTable(Ndb* pNdb, } // Execute the transaction and insert the record - check = pTrans->execute(Commit, CommitAsMuchAsPossible ); + check = pTrans->execute(Commit, CommitAsMuchAsPossible); if(check == -1 ) { const NdbError err = pTrans->getNdbError(); closeTransaction(pNdb); @@ -815,7 +991,7 @@ HugoTransactions::pkUpdateRecords(Ndb* pNdb, if(check != 2) break; - if((check = pTrans->execute(NoCommit, , AbortOnError)) != 0) + if((check = pTrans->execute(NoCommit, AbortOnError)) != 0) break; } if(check != 1 || rows_found != batch) diff --git a/storage/ndb/test/src/UtilTransactions.cpp b/storage/ndb/test/src/UtilTransactions.cpp index fd9ab2954f9..453364fa1b2 100644 --- a/storage/ndb/test/src/UtilTransactions.cpp +++ b/storage/ndb/test/src/UtilTransactions.cpp @@ -1398,7 +1398,8 @@ loop: ERR(err= cmp.getTransaction()->getNdbError()); goto error; } - if(cmp.execute_Commit(pNdb) != NDBT_OK) + if(cmp.execute_Commit(pNdb) != NDBT_OK || + cmp.getTransaction()->getNdbError().code) { ERR(err= cmp.getTransaction()->getNdbError()); goto error; From a8f0edea67ccebc902abc920cdbcabf765e00646 Mon Sep 17 00:00:00 2001 From: "tomas@poseidon.mysql.com" <> Date: Tue, 6 Feb 2007 11:57:56 +0700 Subject: [PATCH 32/40] ndb: remove WAITFOR_RESPONSE_TIMEOUT printout - to get cleaner error log in debug mode --- storage/ndb/src/ndbapi/TransporterFacade.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/ndb/src/ndbapi/TransporterFacade.cpp b/storage/ndb/src/ndbapi/TransporterFacade.cpp index 24bf6dbbc6a..c4b84eb5239 100644 --- a/storage/ndb/src/ndbapi/TransporterFacade.cpp +++ b/storage/ndb/src/ndbapi/TransporterFacade.cpp @@ -1403,7 +1403,7 @@ int PollGuard::wait_for_input_in_loop(int wait_time, bool forceSend) } if (wait_time == -1) { -#ifdef VM_TRACE +#ifdef NOT_USED ndbout << "Waited WAITFOR_RESPONSE_TIMEOUT, continuing wait" << endl; #endif continue; From bbe3008a490163941668d634ac7794c2ad8e9215 Mon Sep 17 00:00:00 2001 From: "tomas@poseidon.mysql.com" <> Date: Tue, 6 Feb 2007 12:40:26 +0700 Subject: [PATCH 33/40] Bug #26021 - ndb: valgrind warning handle_trailing_share/ndbcluster_free_share invalid read --- sql/ha_ndbcluster.cc | 163 +++++++++++++++++++++++++++++++----- sql/ha_ndbcluster_binlog.cc | 109 ++++++++++++++++++++++-- 2 files changed, 244 insertions(+), 28 deletions(-) diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index 30515564a60..ae7c1f9dade 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -5009,11 +5009,17 @@ int ha_ndbcluster::create(const char *name, get a new share */ + /* ndb_share reference create */ if (!(share= get_share(name, form, true, true))) { sql_print_error("NDB: allocating table share for %s failed", name); /* my_errno is set */ } + else + { + DBUG_PRINT("NDB_SHARE", ("%s binlog create use_count: %u", + share->key, share->use_count)); + } pthread_mutex_unlock(&ndbcluster_mutex); while (!IS_TMP_PREFIX(m_tabname)) @@ -5037,7 +5043,7 @@ int ha_ndbcluster::create(const char *name, if (ndb_extra_logging) sql_print_information("NDB Binlog: CREATE TABLE Event: %s", event_name.c_ptr()); - if (share && do_event_op && + if (share && ndbcluster_create_event_ops(share, m_table, event_name.c_ptr())) { sql_print_error("NDB Binlog: FAILED CREATE TABLE event operations." @@ -5129,6 +5135,9 @@ int ha_ndbcluster::create_handler_files(const char *file, } set_ndb_share_state(m_share, NSS_INITIAL); + /* ndb_share reference schema(?) free */ + DBUG_PRINT("NDB_SHARE", ("%s binlog schema(?) free use_count: %u", + m_share->key, m_share->use_count)); free_share(&m_share); // Decrease ref_count DBUG_RETURN(error); @@ -5255,7 +5264,10 @@ int ha_ndbcluster::create_ndb_index(const char *name, */ void ha_ndbcluster::prepare_for_alter() { + /* ndb_share reference schema */ ndbcluster_get_share(m_share); // Increase ref_count + DBUG_PRINT("NDB_SHARE", ("%s binlog schema use_count: %u", + m_share->key, m_share->use_count)); set_ndb_share_state(m_share, NSS_ALTERED); } @@ -5289,6 +5301,9 @@ int ha_ndbcluster::add_index(TABLE *table_arg, if (error) { set_ndb_share_state(m_share, NSS_INITIAL); + /* ndb_share reference schema free */ + DBUG_PRINT("NDB_SHARE", ("%s binlog schema free use_count: %u", + m_share->key, m_share->use_count)); free_share(&m_share); // Decrease ref_count } DBUG_RETURN(error); @@ -5333,6 +5348,9 @@ int ha_ndbcluster::final_drop_index(TABLE *table_arg) if((error= drop_indexes(ndb, table_arg))) { m_share->state= NSS_INITIAL; + /* ndb_share reference schema free */ + DBUG_PRINT("NDB_SHARE", ("%s binlog schema free use_count: %u", + m_share->key, m_share->use_count)); free_share(&m_share); // Decrease ref_count } DBUG_RETURN(error); @@ -5374,9 +5392,12 @@ int ha_ndbcluster::rename_table(const char *from, const char *to) int ndb_table_id= orig_tab->getObjectId(); int ndb_table_version= orig_tab->getObjectVersion(); + /* ndb_share reference temporary */ NDB_SHARE *share= get_share(from, 0, false); if (share) { + DBUG_PRINT("NDB_SHARE", ("%s temporary use_count: %u", + share->key, share->use_count)); int r= rename_share(share, to); DBUG_ASSERT(r == 0); } @@ -5400,6 +5421,9 @@ int ha_ndbcluster::rename_table(const char *from, const char *to) { int r= rename_share(share, from); DBUG_ASSERT(r == 0); + /* ndb_share reference temporary free */ + DBUG_PRINT("NDB_SHARE", ("%s temporary free use_count: %u", + share->key, share->use_count)); free_share(&share); } #endif @@ -5412,7 +5436,12 @@ int ha_ndbcluster::rename_table(const char *from, const char *to) // ToDo in 4.1 should rollback alter table... #ifdef HAVE_NDB_BINLOG if (share) + { + /* ndb_share reference temporary free */ + DBUG_PRINT("NDB_SHARE", ("%s temporary use_count: %u", + share->key, share->use_count)); free_share(&share); + } #endif DBUG_RETURN(result); } @@ -5446,7 +5475,7 @@ int ha_ndbcluster::rename_table(const char *from, const char *to) if (ndb_extra_logging) sql_print_information("NDB Binlog: RENAME Event: %s", event_name.c_ptr()); - if (share && ndb_binlog_running && + if (share && ndbcluster_create_event_ops(share, ndbtab, event_name.c_ptr())) { sql_print_error("NDB Binlog: FAILED create event operations " @@ -5493,7 +5522,12 @@ int ha_ndbcluster::rename_table(const char *from, const char *to) } } if (share) + { + /* ndb_share reference temporary free */ + DBUG_PRINT("NDB_SHARE", ("%s temporary free use_count: %u", + share->key, share->use_count)); free_share(&share); + } #endif DBUG_RETURN(result); @@ -5528,7 +5562,13 @@ ha_ndbcluster::delete_table(ha_ndbcluster *h, Ndb *ndb, DBUG_PRINT("info", ("Schema distribution table not setup")); DBUG_RETURN(HA_ERR_NO_CONNECTION); } + /* ndb_share reference temporary */ NDB_SHARE *share= get_share(path, 0, false); + if (share) + { + DBUG_PRINT("NDB_SHARE", ("%s temporary use_count: %u", + share->key, share->use_count)); + } #endif /* Drop the table from NDB */ @@ -5608,9 +5648,14 @@ retry_temporary_error1: The share kept by the server has not been freed, free it */ share->state= NSS_DROPPED; + /* ndb_share reference create free */ + DBUG_PRINT("NDB_SHARE", ("%s create free use_count: %u", + share->key, share->use_count)); free_share(&share, TRUE); } - /* free the share taken above */ + /* ndb_share reference temporary free */ + DBUG_PRINT("NDB_SHARE", ("%s temporary free use_count: %u", + share->key, share->use_count)); free_share(&share, TRUE); pthread_mutex_unlock(&ndbcluster_mutex); } @@ -5660,9 +5705,14 @@ retry_temporary_error1: The share kept by the server has not been freed, free it */ share->state= NSS_DROPPED; + /* ndb_share reference create free */ + DBUG_PRINT("NDB_SHARE", ("%s create free use_count: %u", + share->key, share->use_count)); free_share(&share, TRUE); } - /* free the share taken above */ + /* ndb_share reference temporary free */ + DBUG_PRINT("NDB_SHARE", ("%s temporary free use_count: %u", + share->key, share->use_count)); free_share(&share, TRUE); pthread_mutex_unlock(&ndbcluster_mutex); } @@ -5838,6 +5888,9 @@ ha_ndbcluster::~ha_ndbcluster() if (m_share) { + /* ndb_share reference handler free */ + DBUG_PRINT("NDB_SHARE", ("%s handler free use_count: %u", + m_share->key, m_share->use_count)); free_share(&m_share); } release_metadata(thd, ndb); @@ -5900,14 +5953,21 @@ int ha_ndbcluster::open(const char *name, int mode, uint test_if_locked) DBUG_PRINT("info", ("ref_length: %d", ref_length)); // Init table lock structure + /* ndb_share reference handler */ if (!(m_share=get_share(name, table))) DBUG_RETURN(1); + DBUG_PRINT("NDB_SHARE", ("%s handler use_count: %u", + m_share->key, m_share->use_count)); thr_lock_data_init(&m_share->lock,&m_lock,(void*) 0); set_dbname(name); set_tabname(name); - if (check_ndb_connection()) { + if (check_ndb_connection()) + { + /* ndb_share reference handler free */ + DBUG_PRINT("NDB_SHARE", ("%s handler free use_count: %u", + m_share->key, m_share->use_count)); free_share(&m_share); m_share= 0; DBUG_RETURN(HA_ERR_NO_CONNECTION); @@ -5968,6 +6028,9 @@ int ha_ndbcluster::close(void) DBUG_ENTER("close"); THD *thd= current_thd; Ndb *ndb= thd ? check_ndb_in_thd(thd) : g_ndb; + /* ndb_share reference handler free */ + DBUG_PRINT("NDB_SHARE", ("%s handler free use_count: %u", + m_share->key, m_share->use_count)); free_share(&m_share); m_share= 0; release_metadata(thd, ndb); @@ -6074,7 +6137,13 @@ int ndbcluster_discover(handlerton *hton, THD* thd, const char *db, ndb->setDatabaseName(db); NDBDICT* dict= ndb->getDictionary(); build_table_filename(key, sizeof(key), db, name, "", 0); + /* ndb_share reference temporary */ NDB_SHARE *share= get_share(key, 0, false); + if (share) + { + DBUG_PRINT("NDB_SHARE", ("%s temporary use_count: %u", + share->key, share->use_count)); + } if (share && get_ndb_share_state(share) == NSS_ALTERED) { // Frm has been altered on disk, but not yet written to ndb @@ -6120,12 +6189,22 @@ int ndbcluster_discover(handlerton *hton, THD* thd, const char *db, *frmblob= data; if (share) + { + /* ndb_share reference temporary free */ + DBUG_PRINT("NDB_SHARE", ("%s temporary free use_count: %u", + share->key, share->use_count)); free_share(&share); + } DBUG_RETURN(0); err: if (share) + { + /* ndb_share reference temporary free */ + DBUG_PRINT("NDB_SHARE", ("%s temporary free use_count: %u", + share->key, share->use_count)); free_share(&share); + } if (ndb_error.code) { ERR_RETURN(ndb_error); @@ -6362,7 +6441,13 @@ int ndbcluster_find_all_files(THD *thd) } else if (cmp_frm(ndbtab, pack_data, pack_length)) { + /* ndb_share reference temporary */ NDB_SHARE *share= get_share(key, 0, false); + if (share) + { + DBUG_PRINT("NDB_SHARE", ("%s temporary use_count: %u", + share->key, share->use_count)); + } if (!share || get_ndb_share_state(share) != NSS_ALTERED) { discover= 1; @@ -6370,7 +6455,12 @@ int ndbcluster_find_all_files(THD *thd) elmt.database, elmt.name); } if (share) + { + /* ndb_share reference temporary free */ + DBUG_PRINT("NDB_SHARE", ("%s temporary free use_count: %u", + share->key, share->use_count)); free_share(&share); + } } my_free((char*) data, MYF(MY_ALLOW_ZERO_PTR)); my_free((char*) pack_data, MYF(MY_ALLOW_ZERO_PTR)); @@ -7175,7 +7265,10 @@ uint ndb_get_commitcount(THD *thd, char *dbname, char *tabname, DBUG_PRINT("info", ("Table %s not found in ndbcluster_open_tables", name)); DBUG_RETURN(1); } + /* ndb_share reference temporary, free below */ share->use_count++; + DBUG_PRINT("NDB_SHARE", ("%s temporary use_count: %u", + share->key, share->use_count)); pthread_mutex_unlock(&ndbcluster_mutex); pthread_mutex_lock(&share->mutex); @@ -7188,6 +7281,9 @@ uint ndb_get_commitcount(THD *thd, char *dbname, char *tabname, DBUG_PRINT("info", ("Getting commit_count: %s from share", llstr(share->commit_count, buff))); pthread_mutex_unlock(&share->mutex); + /* ndb_share reference temporary free */ + DBUG_PRINT("NDB_SHARE", ("%s temporary free use_count: %u", + share->key, share->use_count)); free_share(&share); DBUG_RETURN(0); } @@ -7206,6 +7302,9 @@ uint ndb_get_commitcount(THD *thd, char *dbname, char *tabname, if (ndbtab_g.get_table() == 0 || ndb_get_table_statistics(NULL, false, ndb, ndbtab_g.get_table(), &stat)) { + /* ndb_share reference temporary free */ + DBUG_PRINT("NDB_SHARE", ("%s temporary free use_count: %u", + share->key, share->use_count)); free_share(&share); DBUG_RETURN(1); } @@ -7226,6 +7325,9 @@ uint ndb_get_commitcount(THD *thd, char *dbname, char *tabname, *commit_count= 0; } pthread_mutex_unlock(&share->mutex); + /* ndb_share reference temporary free */ + DBUG_PRINT("NDB_SHARE", ("%s temporary free use_count: %u", + share->key, share->use_count)); free_share(&share); DBUG_RETURN(0); } @@ -7442,7 +7544,10 @@ int handle_trailing_share(NDB_SHARE *share) static ulong trailing_share_id= 0; DBUG_ENTER("handle_trailing_share"); + /* ndb_share reference temporary, free below */ ++share->use_count; + DBUG_PRINT("NDB_SHARE", ("%s temporary use_count: %u", + share->key, share->use_count)); pthread_mutex_unlock(&ndbcluster_mutex); TABLE_LIST table_list; @@ -7453,10 +7558,14 @@ int handle_trailing_share(NDB_SHARE *share) close_cached_tables(thd, 0, &table_list, TRUE); pthread_mutex_lock(&ndbcluster_mutex); + /* ndb_share reference temporary free */ + DBUG_PRINT("NDB_SHARE", ("%s temporary free use_count: %u", + share->key, share->use_count)); if (!--share->use_count) { if (ndb_extra_logging) - sql_print_information("NDB_SHARE: trailing share %s(connect_count: %u) " + sql_print_information("NDB_SHARE: trailing share " + "%s(connect_count: %u) " "released by close_cached_tables at " "connect_count: %u", share->key, @@ -7470,20 +7579,28 @@ int handle_trailing_share(NDB_SHARE *share) share still exists, if share has not been dropped by server release that share */ - if (share->state != NSS_DROPPED && !--share->use_count) + if (share->state != NSS_DROPPED) { - if (ndb_extra_logging) - sql_print_information("NDB_SHARE: trailing share %s(connect_count: %u) " - "released after NSS_DROPPED check " - "at connect_count: %u", - share->key, - share->connect_count, - g_ndb_cluster_connection->get_connect_count()); - ndbcluster_real_free_share(&share); - DBUG_RETURN(0); + share->state= NSS_DROPPED; + /* ndb_share reference create free */ + DBUG_PRINT("NDB_SHARE", ("%s create free use_count: %u", + share->key, share->use_count)); + --share->use_count; + + if (share->use_count == 0) + { + if (ndb_extra_logging) + sql_print_information("NDB_SHARE: trailing share " + "%s(connect_count: %u) " + "released after NSS_DROPPED check " + "at connect_count: %u", + share->key, + share->connect_count, + g_ndb_cluster_connection->get_connect_count()); + ndbcluster_real_free_share(&share); + DBUG_RETURN(0); + } } - DBUG_PRINT("error", ("NDB_SHARE: %s already exists use_count=%d.", - share->key, share->use_count)); sql_print_error("NDB_SHARE: %s already exists use_count=%d." " Moving away for safety, but possible memleak.", @@ -8540,7 +8657,10 @@ pthread_handler_t ndb_util_thread_func(void *arg __attribute__((unused))) continue; // injector thread is the only user, skip statistics share->util_lock= current_thd; // Mark that util thread has lock #endif /* HAVE_NDB_BINLOG */ + /* ndb_share reference temporary, free below */ share->use_count++; /* Make sure the table can't be closed */ + DBUG_PRINT("NDB_SHARE", ("%s temporary use_count: %u", + share->key, share->use_count)); DBUG_PRINT("ndb_util_thread", ("Found open table[%d]: %s, use_count: %d", i, share->table_name, share->use_count)); @@ -8561,6 +8681,9 @@ pthread_handler_t ndb_util_thread_func(void *arg __attribute__((unused))) /* Util thread and injector thread is the only user, skip statistics */ + /* ndb_share reference temporary free */ + DBUG_PRINT("NDB_SHARE", ("%s temporary free use_count: %u", + share->key, share->use_count)); free_share(&share); continue; } @@ -8604,7 +8727,9 @@ pthread_handler_t ndb_util_thread_func(void *arg __attribute__((unused))) share->commit_count= stat.commit_count; pthread_mutex_unlock(&share->mutex); - /* Decrease the use count and possibly free share */ + /* ndb_share reference temporary free */ + DBUG_PRINT("NDB_SHARE", ("%s temporary free use_count: %u", + share->key, share->use_count)); free_share(&share); } diff --git a/sql/ha_ndbcluster_binlog.cc b/sql/ha_ndbcluster_binlog.cc index 55364f31764..67b82a1643b 100644 --- a/sql/ha_ndbcluster_binlog.cc +++ b/sql/ha_ndbcluster_binlog.cc @@ -371,6 +371,10 @@ void ndbcluster_binlog_init_share(NDB_SHARE *share, TABLE *_table) strcmp(share->db, NDB_REP_DB) == 0 && strcmp(share->table_name, NDB_SCHEMA_TABLE) == 0) do_event_op= 1; + else if (!ndb_apply_status_share && + strcmp(share->db, NDB_REP_DB) == 0 && + strcmp(share->table_name, NDB_APPLY_TABLE) == 0) + do_event_op= 1; { int i, no_nodes= g_ndb_cluster_connection->no_db_nodes(); @@ -606,7 +610,14 @@ static int ndbcluster_binlog_end(THD *thd) DBUG_PRINT("share", ("table->s->db.table_name: %s.%s", share->table->s->db.str, share->table->s->table_name.str)); - if (share->state != NSS_DROPPED && !--share->use_count) + /* ndb_share reference create free */ + if (share->state != NSS_DROPPED) + { + DBUG_PRINT("NDB_SHARE", ("%s create free use_count: %u", + share->key, share->use_count)); + --share->use_count; + } + if (share->use_count == 0) ndbcluster_real_free_share(&share); else { @@ -1716,15 +1727,25 @@ ndb_handle_schema_change(THD *thd, Ndb *ndb, NdbEventOperation *pOp, (void) pthread_cond_signal(&injector_cond); pthread_mutex_lock(&ndbcluster_mutex); + /* ndb_share reference binlog free */ + DBUG_PRINT("NDB_SHARE", ("%s binlog free use_count: %u", + share->key, share->use_count)); free_share(&share, TRUE); if (is_remote_change && share && share->state != NSS_DROPPED) { DBUG_PRINT("info", ("remote change")); share->state= NSS_DROPPED; if (share->use_count != 1) + { + /* open handler holding reference */ + /* wait with freeing create ndb_share to below */ do_close_cached_tables= TRUE; + } else { + /* ndb_share reference create free */ + DBUG_PRINT("NDB_SHARE", ("%s create free use_count: %u", + share->key, share->use_count)); free_share(&share, TRUE); share= 0; } @@ -1747,6 +1768,9 @@ ndb_handle_schema_change(THD *thd, Ndb *ndb, NdbEventOperation *pOp, table_list.db= (char *)dbname; table_list.alias= table_list.table_name= (char *)tabname; close_cached_tables(thd, 0, &table_list); + /* ndb_share reference create free */ + DBUG_PRINT("NDB_SHARE", ("%s create free use_count: %u", + share->key, share->use_count)); free_share(&share); } DBUG_RETURN(0); @@ -1814,7 +1838,13 @@ ndb_binlog_thread_handle_schema_event(THD *thd, Ndb *ndb, char key[FN_REFLEN]; build_table_filename(key, sizeof(key), schema->db, schema->name, "", 0); + /* ndb_share reference temporary, free below */ NDB_SHARE *share= get_share(key, 0, FALSE, FALSE); + if (share) + { + DBUG_PRINT("NDB_SHARE", ("%s temporary use_count: %u", + share->key, share->use_count)); + } // invalidation already handled by binlog thread if (!share || !share->op) { @@ -1830,8 +1860,13 @@ ndb_binlog_thread_handle_schema_event(THD *thd, Ndb *ndb, table_list.alias= table_list.table_name= schema->name; close_cached_tables(thd, 0, &table_list, FALSE); } + /* ndb_share reference temporary free */ if (share) + { + DBUG_PRINT("NDB_SHARE", ("%s temporary free use_count: %u", + share->key, share->use_count)); free_share(&share); + } } // fall through case SOT_CREATE_TABLE: @@ -1940,6 +1975,10 @@ ndb_binlog_thread_handle_schema_event(THD *thd, Ndb *ndb, /* begin protect ndb_schema_share */ pthread_mutex_lock(&ndb_schema_share_mutex); + /* ndb_share reference binlog extra free */ + DBUG_PRINT("NDB_SHARE", ("%s binlog extra free use_count: %u", + ndb_schema_share->key, + ndb_schema_share->use_count)); free_share(&ndb_schema_share); ndb_schema_share= 0; pthread_mutex_unlock(&ndb_schema_share_mutex); @@ -2066,7 +2105,13 @@ ndb_binlog_thread_handle_schema_event_post_epoch(THD *thd, pthread_mutex_unlock(&ndbcluster_mutex); continue; } + /* ndb_share reference temporary, free below */ NDB_SHARE *share= get_share(key, 0, FALSE, FALSE); + if (share) + { + DBUG_PRINT("NDB_SHARE", ("%s temporary use_count: %u", + share->key, share->use_count)); + } switch (schema_type) { case SOT_DROP_DB: @@ -2111,6 +2156,9 @@ ndb_binlog_thread_handle_schema_event_post_epoch(THD *thd, */ if (share) { + /* ndb_share reference temporary free */ + DBUG_PRINT("NDB_SHARE", ("%s temporary free use_count: %u", + share->key, share->use_count)); free_share(&share); share= 0; } @@ -2143,6 +2191,9 @@ ndb_binlog_thread_handle_schema_event_post_epoch(THD *thd, } if (share) { + /* ndb_share reference temporary free */ + DBUG_PRINT("NDB_SHARE", ("%s temporary free use_count: %u", + share->key, share->use_count)); free_share(&share); share= 0; } @@ -2445,10 +2496,8 @@ int ndbcluster_create_binlog_setup(Ndb *ndb, const char *key, pthread_mutex_unlock(&ndbcluster_mutex); DBUG_RETURN(1); } -#ifdef NOT_YET - if (share->connect_count != + if (!share_may_exist || share->connect_count != g_ndb_cluster_connection->get_connect_count()) -#endif { handle_trailing_share(share); share= NULL; @@ -2456,23 +2505,33 @@ int ndbcluster_create_binlog_setup(Ndb *ndb, const char *key, } /* Create share which is needed to hold replication information */ -#ifdef NOT_YET if (share) { + /* ndb_share reference create */ ++share->use_count; + DBUG_PRINT("NDB_SHARE", ("%s create use_count: %u", + share->key, share->use_count)); } - else -#endif - if (!(share= get_share(key, 0, TRUE, TRUE))) + /* ndb_share reference create */ + else if (!(share= get_share(key, 0, TRUE, TRUE))) { sql_print_error("NDB Binlog: " "allocating table share for %s failed", key); } + else + { + DBUG_PRINT("NDB_SHARE", ("%s create use_count: %u", + share->key, share->use_count)); + } if (!ndb_schema_share && strcmp(share->db, NDB_REP_DB) == 0 && strcmp(share->table_name, NDB_SCHEMA_TABLE) == 0) do_event_op= 1; + else if (!ndb_apply_status_share && + strcmp(share->db, NDB_REP_DB) == 0 && + strcmp(share->table_name, NDB_APPLY_TABLE) == 0) + do_event_op= 1; if (!do_event_op) { @@ -2744,7 +2803,7 @@ ndbcluster_create_event_ops(NDB_SHARE *share, const NDBTAB *ndbtab, else if (!ndb_apply_status_share && strcmp(share->db, NDB_REP_DB) == 0 && strcmp(share->table_name, NDB_APPLY_TABLE) == 0) do_ndb_apply_status_share= 1; - else if (!binlog_filter->db_ok(share->db)) + else if (!binlog_filter->db_ok(share->db) || !ndb_binlog_running) { share->flags|= NSF_NO_BINLOG; DBUG_RETURN(0); @@ -2756,6 +2815,9 @@ ndbcluster_create_event_ops(NDB_SHARE *share, const NDBTAB *ndbtab, DBUG_ASSERT(share->use_count > 1); sql_print_error("NDB Binlog: discover reusing old ev op"); + /* ndb_share reference ToDo free */ + DBUG_PRINT("NDB_SHARE", ("%s ToDo free use_count: %u", + share->key, share->use_count)); free_share(&share); // old event op already has reference DBUG_RETURN(0); } @@ -2898,15 +2960,24 @@ ndbcluster_create_event_ops(NDB_SHARE *share, const NDBTAB *ndbtab, break; } + /* ndb_share reference binlog */ get_share(share); + DBUG_PRINT("NDB_SHARE", ("%s binlog use_count: %u", + share->key, share->use_count)); if (do_ndb_apply_status_share) { + /* ndb_share reference binlog extra */ ndb_apply_status_share= get_share(share); + DBUG_PRINT("NDB_SHARE", ("%s binlog extra use_count: %u", + share->key, share->use_count)); (void) pthread_cond_signal(&injector_cond); } else if (do_ndb_schema_share) { + /* ndb_share reference binlog extra */ ndb_schema_share= get_share(share); + DBUG_PRINT("NDB_SHARE", ("%s binlog extra use_count: %u", + share->key, share->use_count)); (void) pthread_cond_signal(&injector_cond); } @@ -3093,6 +3164,9 @@ ndb_binlog_thread_handle_non_data_event(THD *thd, Ndb *ndb, ndb_binlog_tables_inited && ndb_binlog_running) sql_print_information("NDB Binlog: ndb tables initially " "read only on reconnect."); + /* ndb_share reference binlog extra free */ + DBUG_PRINT("NDB_SHARE", ("%s binlog extra free use_count: %u", + share->key, share->use_count)); free_share(&ndb_apply_status_share); ndb_apply_status_share= 0; } @@ -3109,6 +3183,9 @@ ndb_binlog_thread_handle_non_data_event(THD *thd, Ndb *ndb, ndb_binlog_tables_inited && ndb_binlog_running) sql_print_information("NDB Binlog: ndb tables initially " "read only on reconnect."); + /* ndb_share reference binlog extra free */ + DBUG_PRINT("NDB_SHARE", ("%s binlog extra free use_count: %u", + share->key, share->use_count)); free_share(&ndb_apply_status_share); ndb_apply_status_share= 0; } @@ -4009,6 +4086,10 @@ err: if (ndb_apply_status_share) { + /* ndb_share reference binlog extra free */ + DBUG_PRINT("NDB_SHARE", ("%s binlog extra free use_count: %u", + ndb_apply_status_share->key, + ndb_apply_status_share->use_count)); free_share(&ndb_apply_status_share); ndb_apply_status_share= 0; } @@ -4016,6 +4097,10 @@ err: { /* begin protect ndb_schema_share */ pthread_mutex_lock(&ndb_schema_share_mutex); + /* ndb_share reference binlog extra free */ + DBUG_PRINT("NDB_SHARE", ("%s binlog extra free use_count: %u", + ndb_schema_share->key, + ndb_schema_share->use_count)); free_share(&ndb_schema_share); ndb_schema_share= 0; pthread_mutex_unlock(&ndb_schema_share_mutex); @@ -4037,6 +4122,9 @@ err: DBUG_ASSERT(share->op == op || share->op_old == op); share->op= share->op_old= 0; + /* ndb_share reference binlog free */ + DBUG_PRINT("NDB_SHARE", ("%s binlog free use_count: %u", + share->key, share->use_count)); free_share(&share); s_ndb->dropEventOperation(op); } @@ -4057,6 +4145,9 @@ err: DBUG_ASSERT(share->op == op || share->op_old == op); share->op= share->op_old= 0; + /* ndb_share reference binlog free */ + DBUG_PRINT("NDB_SHARE", ("%s binlog free use_count: %u", + share->key, share->use_count)); free_share(&share); i_ndb->dropEventOperation(op); } From 6765e30aa04c20f10c0f86c55ff38b77a961bc41 Mon Sep 17 00:00:00 2001 From: "tomas@poseidon.mysql.com" <> Date: Tue, 6 Feb 2007 15:01:24 +0700 Subject: [PATCH 34/40] ndb: only inject events (ACTIVE, NODE_FAILURE, CLUSTER_FAILURE) if bit shows connected --- storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp b/storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp index 828ba51bc21..2a700a6c4ea 100644 --- a/storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp +++ b/storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp @@ -1615,13 +1615,19 @@ NdbEventBuffer::insert_event(NdbEventOperationImpl* impl, { do { - oid_ref = impl->m_oid; - insertDataL(impl, &data, ptr); + if (impl->m_node_bit_mask.get(0u)) + { + oid_ref = impl->m_oid; + insertDataL(impl, &data, ptr); + } NdbEventOperationImpl* blob_op = impl->theBlobOpList; while (blob_op != NULL) { - oid_ref = blob_op->m_oid; - insertDataL(blob_op, &data, ptr); + if (blob_op->m_node_bit_mask.get(0u)) + { + oid_ref = blob_op->m_oid; + insertDataL(blob_op, &data, ptr); + } blob_op = blob_op->m_next; } } while((impl = impl->m_next)); From 07dd9a61c180116033fb0010628eeabace8c40b0 Mon Sep 17 00:00:00 2001 From: "msvensson@pilot.mysql.com" <> Date: Tue, 6 Feb 2007 22:06:13 +0100 Subject: [PATCH 35/40] Bug#26015 valgrind warning PollGuard::unlock_and_signal()/NdbCondition_Destroy - Add variable "ndbcluster_binlog_terminating" and use that to signal the cluster binlog thread it's time to shutdown. This allows exact control of when the thread shutdown, previous implementation would start shutdown of the thread as soon as the mysqld started shutdown. Now we will shutdown cluster binlog thread in 'ndbcluster_binlog_end' --- sql/ha_ndbcluster_binlog.cc | 83 ++++++++++--------------------------- 1 file changed, 23 insertions(+), 60 deletions(-) diff --git a/sql/ha_ndbcluster_binlog.cc b/sql/ha_ndbcluster_binlog.cc index c959d512764..ea5a2deaeb3 100644 --- a/sql/ha_ndbcluster_binlog.cc +++ b/sql/ha_ndbcluster_binlog.cc @@ -81,6 +81,7 @@ static Ndb *injector_ndb= 0; static Ndb *schema_ndb= 0; static int ndbcluster_binlog_inited= 0; +static int ndbcluster_binlog_terminating= 0; /* Mutex and condition used for interacting between client sql thread @@ -582,61 +583,18 @@ static int ndbcluster_binlog_end(THD *thd) #ifdef HAVE_NDB_BINLOG /* wait for injector thread to finish */ + ndbcluster_binlog_terminating= 1; + pthread_cond_signal(&injector_cond); pthread_mutex_lock(&injector_mutex); - if (ndb_binlog_thread_running > 0) - { - pthread_cond_signal(&injector_cond); - pthread_mutex_unlock(&injector_mutex); - - pthread_mutex_lock(&injector_mutex); - while (ndb_binlog_thread_running > 0) - { - struct timespec abstime; - set_timespec(abstime, 1); - pthread_cond_timedwait(&injector_cond, &injector_mutex, &abstime); - } - } + while (ndb_binlog_thread_running > 0) + pthread_cond_wait(&injector_cond, &injector_mutex); pthread_mutex_unlock(&injector_mutex); - - /* remove all shares */ - { - pthread_mutex_lock(&ndbcluster_mutex); - for (uint i= 0; i < ndbcluster_open_tables.records; i++) - { - NDB_SHARE *share= - (NDB_SHARE*) hash_element(&ndbcluster_open_tables, i); - if (share->table) - DBUG_PRINT("share", - ("table->s->db.table_name: %s.%s", - share->table->s->db.str, share->table->s->table_name.str)); - /* ndb_share reference create free */ - if (share->state != NSS_DROPPED) - { - DBUG_PRINT("NDB_SHARE", ("%s create free use_count: %u", - share->key, share->use_count)); - --share->use_count; - } - if (share->use_count == 0) - ndbcluster_real_free_share(&share); - else - { - DBUG_PRINT("share", - ("[%d] 0x%lx key: %s key_length: %d", - i, (long) share, share->key, share->key_length)); - DBUG_PRINT("share", - ("db.tablename: %s.%s use_count: %d commit_count: %lu", - share->db, share->table_name, - share->use_count, (long) share->commit_count)); - } - } - pthread_mutex_unlock(&ndbcluster_mutex); - } - pthread_mutex_destroy(&injector_mutex); pthread_cond_destroy(&injector_cond); pthread_mutex_destroy(&ndb_schema_share_mutex); #endif + DBUG_RETURN(0); } @@ -2385,7 +2343,6 @@ int ndbcluster_binlog_start() if (ndb_binlog_thread_running < 0) DBUG_RETURN(-1); - DBUG_RETURN(0); } @@ -3562,6 +3519,9 @@ pthread_handler_t ndb_binlog_thread_func(void *arg) s_ndb->init()) { sql_print_error("NDB Binlog: Getting Schema Ndb object failed"); + ndb_binlog_thread_running= -1; + pthread_mutex_unlock(&injector_mutex); + pthread_cond_signal(&injector_cond); goto err; } @@ -3592,7 +3552,7 @@ pthread_handler_t ndb_binlog_thread_func(void *arg) p_latest_trans_gci= injector_ndb->get_ndb_cluster_connection().get_latest_trans_gci(); schema_ndb= s_ndb; - ndb_binlog_thread_running= 1; + if (opt_bin_log) { if (global_system_variables.binlog_format == BINLOG_FORMAT_ROW || @@ -3605,10 +3565,9 @@ pthread_handler_t ndb_binlog_thread_func(void *arg) sql_print_error("NDB: only row based binary logging is supported"); } } - /* - We signal the thread that started us that we've finished - starting up. - */ + + /* Thread start up completed */ + ndb_binlog_thread_running= 1; pthread_mutex_unlock(&injector_mutex); pthread_cond_signal(&injector_cond); @@ -3627,7 +3586,7 @@ restart: struct timespec abstime; set_timespec(abstime, 1); pthread_cond_timedwait(&injector_cond, &injector_mutex, &abstime); - if (abort_loop) + if (ndbcluster_binlog_terminating) { pthread_mutex_unlock(&injector_mutex); goto err; @@ -3652,13 +3611,15 @@ restart: { // wait for the first event thd->proc_info= "Waiting for first event from ndbcluster"; - DBUG_PRINT("info", ("Waiting for the first event")); int schema_res, res; Uint64 schema_gci; do { - if (abort_loop) + DBUG_PRINT("info", ("Waiting for the first event")); + + if (ndbcluster_binlog_terminating) goto err; + schema_res= s_ndb->pollEvents(100, &schema_gci); } while (schema_gci == 0 || ndb_latest_received_binlog_epoch == schema_gci); if (ndb_binlog_running) @@ -3666,7 +3627,7 @@ restart: Uint64 gci= i_ndb->getLatestGCI(); while (gci < schema_gci || gci == ndb_latest_received_binlog_epoch) { - if (abort_loop) + if (ndbcluster_binlog_terminating) goto err; res= i_ndb->pollEvents(10, &gci); } @@ -3713,7 +3674,8 @@ restart: thd->db= db; } do_ndbcluster_binlog_close_connection= BCCC_running; - for ( ; !((abort_loop || do_ndbcluster_binlog_close_connection) && + for ( ; !((ndbcluster_binlog_terminating || + do_ndbcluster_binlog_close_connection) && ndb_latest_handled_binlog_epoch >= *p_latest_trans_gci) && do_ndbcluster_binlog_close_connection != BCCC_restart; ) { @@ -3760,7 +3722,8 @@ restart: schema_res= s_ndb->pollEvents(10, &schema_gci); } - if ((abort_loop || do_ndbcluster_binlog_close_connection) && + if ((ndbcluster_binlog_terminating || + do_ndbcluster_binlog_close_connection) && (ndb_latest_handled_binlog_epoch >= *p_latest_trans_gci || !ndb_binlog_running)) break; /* Shutting down server */ From db8a7b513cbbd3ae6c5d47cb904f7386f1215769 Mon Sep 17 00:00:00 2001 From: "svoj@mysql.com/april.(none)" <> Date: Wed, 7 Feb 2007 01:37:21 +0400 Subject: [PATCH 36/40] Excluded wrongly merged changeset. --- include/my_pthread.h | 9 --------- include/thr_alarm.h | 8 +++++--- mysys/my_pthread.c | 8 +++----- mysys/my_thr_init.c | 21 -------------------- mysys/thr_alarm.c | 47 +++++++++++++++++++++----------------------- sql/mysqld.cc | 34 ++++++++++++++------------------ 6 files changed, 45 insertions(+), 82 deletions(-) diff --git a/include/my_pthread.h b/include/my_pthread.h index 4d9f5350b1e..a3e1007bf31 100644 --- a/include/my_pthread.h +++ b/include/my_pthread.h @@ -690,15 +690,6 @@ extern uint my_thread_end_wait_time; Keep track of shutdown,signal, and main threads so that my_end() will not report errors with them */ - -/* Which kind of thread library is in use */ - -#define THD_LIB_OTHER 1 -#define THD_LIB_NPTL 2 -#define THD_LIB_LT 4 - -extern uint thd_lib_detected; - /* statistics_xxx functions are for not essential statistic */ #ifndef thread_safe_increment diff --git a/include/thr_alarm.h b/include/thr_alarm.h index 13940e88c08..90f785c022f 100644 --- a/include/thr_alarm.h +++ b/include/thr_alarm.h @@ -24,6 +24,11 @@ extern "C" { #ifndef USE_ALARM_THREAD #define USE_ONE_SIGNAL_HAND /* One must call process_alarm */ #endif +#ifdef HAVE_LINUXTHREADS +#define THR_CLIENT_ALARM SIGALRM +#else +#define THR_CLIENT_ALARM SIGUSR1 +#endif #ifdef HAVE_rts_threads #undef USE_ONE_SIGNAL_HAND #define USE_ALARM_THREAD @@ -84,9 +89,6 @@ typedef struct st_alarm { my_bool malloced; } ALARM; -extern uint thr_client_alarm; -extern pthread_t alarm_thread; - #define thr_alarm_init(A) (*(A))=0 #define thr_alarm_in_use(A) (*(A)!= 0) void init_thr_alarm(uint max_alarm); diff --git a/mysys/my_pthread.c b/mysys/my_pthread.c index 2bfae397c85..844112991f6 100644 --- a/mysys/my_pthread.c +++ b/mysys/my_pthread.c @@ -29,8 +29,6 @@ #define SCHED_POLICY SCHED_OTHER #endif -uint thd_lib_detected; - #ifndef my_pthread_setprio void my_pthread_setprio(pthread_t thread_id,int prior) { @@ -314,6 +312,8 @@ void sigwait_handle_sig(int sig) pthread_mutex_unlock(&LOCK_sigwait); } +extern pthread_t alarm_thread; + void *sigwait_thread(void *set_arg) { sigset_t *set=(sigset_t*) set_arg; @@ -332,9 +332,7 @@ void *sigwait_thread(void *set_arg) sigaction(i, &sact, (struct sigaction*) 0); } } - /* Ensure that init_thr_alarm() is called */ - DBUG_ASSERT(thr_client_alarm); - sigaddset(set, thr_client_alarm); + sigaddset(set,THR_CLIENT_ALARM); pthread_sigmask(SIG_UNBLOCK,(sigset_t*) set,(sigset_t*) 0); alarm_thread=pthread_self(); /* For thr_alarm */ diff --git a/mysys/my_thr_init.c b/mysys/my_thr_init.c index bb502846331..853a2761224 100644 --- a/mysys/my_thr_init.c +++ b/mysys/my_thr_init.c @@ -20,7 +20,6 @@ #include "mysys_priv.h" #include -#include #ifdef THREAD #ifdef USE_TLS @@ -64,8 +63,6 @@ pthread_handler_t nptl_pthread_exit_hack_handler(void *arg) #endif -static uint get_thread_lib(void); - /* initialize thread environment @@ -79,8 +76,6 @@ static uint get_thread_lib(void); my_bool my_thread_global_init(void) { - thd_lib_detected= get_thread_lib(); - if (pthread_key_create(&THR_KEY_mysys,0)) { fprintf(stderr,"Can't initialize threads: error %d\n",errno); @@ -397,20 +392,4 @@ const char *my_thread_name(void) } #endif /* DBUG_OFF */ - -static uint get_thread_lib(void) -{ - char buff[64]; - -#ifdef _CS_GNU_LIBPTHREAD_VERSION - confstr(_CS_GNU_LIBPTHREAD_VERSION, buff, sizeof(buff)); - - if (!strncasecmp(buff, "NPTL", 4)) - return THD_LIB_NPTL; - if (!strncasecmp(buff, "linuxthreads", 12)) - return THD_LIB_LT; -#endif - return THD_LIB_OTHER; -} - #endif /* THREAD */ diff --git a/mysys/thr_alarm.c b/mysys/thr_alarm.c index 9c92333d1bd..170ee8a1b73 100644 --- a/mysys/thr_alarm.c +++ b/mysys/thr_alarm.c @@ -34,7 +34,6 @@ #define ETIME ETIMEDOUT #endif -uint thr_client_alarm; static int alarm_aborted=1; /* No alarm thread */ my_bool thr_alarm_inited= 0; volatile my_bool alarm_thread_running= 0; @@ -57,7 +56,9 @@ static void *alarm_handler(void *arg); #define reschedule_alarms() pthread_kill(alarm_thread,THR_SERVER_ALARM) #endif +#if THR_CLIENT_ALARM != SIGALRM || defined(USE_ALARM_THREAD) static sig_handler thread_alarm(int sig __attribute__((unused))); +#endif static int compare_ulong(void *not_used __attribute__((unused)), byte *a_ptr,byte* b_ptr) @@ -76,16 +77,9 @@ void init_thr_alarm(uint max_alarms) sigfillset(&full_signal_set); /* Neaded to block signals */ pthread_mutex_init(&LOCK_alarm,MY_MUTEX_INIT_FAST); pthread_cond_init(&COND_alarm,NULL); - if (thd_lib_detected == THD_LIB_LT) - thr_client_alarm= SIGALRM; - else - thr_client_alarm= SIGUSR1; -#ifndef USE_ALARM_THREAD - if (thd_lib_detected != THD_LIB_LT) +#if THR_CLIENT_ALARM != SIGALRM || defined(USE_ALARM_THREAD) + my_sigset(THR_CLIENT_ALARM,thread_alarm); #endif - { - my_sigset(thr_client_alarm, thread_alarm); - } sigemptyset(&s); sigaddset(&s, THR_SERVER_ALARM); alarm_thread=pthread_self(); @@ -103,11 +97,10 @@ void init_thr_alarm(uint max_alarms) } #elif defined(USE_ONE_SIGNAL_HAND) pthread_sigmask(SIG_BLOCK, &s, NULL); /* used with sigwait() */ - if (thd_lib_detected == THD_LIB_LT) - { - my_sigset(thr_client_alarm, process_alarm); /* Linuxthreads */ - pthread_sigmask(SIG_UNBLOCK, &s, NULL); - } +#if THR_SERVER_ALARM == THR_CLIENT_ALARM + my_sigset(THR_CLIENT_ALARM,process_alarm); /* Linuxthreads */ + pthread_sigmask(SIG_UNBLOCK, &s, NULL); +#endif #else my_sigset(THR_SERVER_ALARM, process_alarm); pthread_sigmask(SIG_UNBLOCK, &s, NULL); @@ -158,7 +151,7 @@ my_bool thr_alarm(thr_alarm_t *alrm, uint sec, ALARM *alarm_data) now=(ulong) time((time_t*) 0); pthread_sigmask(SIG_BLOCK,&full_signal_set,&old_mask); - pthread_mutex_lock(&LOCK_alarm); /* Lock from threads & alarms */ + pthread_mutex_lock(&LOCK_alarm); /* Lock from threads & alarms */ if (alarm_aborted > 0) { /* No signal thread */ DBUG_PRINT("info", ("alarm aborted")); @@ -278,17 +271,18 @@ sig_handler process_alarm(int sig __attribute__((unused))) This must be first as we can't call DBUG inside an alarm for a normal thread */ - if (thd_lib_detected == THD_LIB_LT && - !pthread_equal(pthread_self(),alarm_thread)) +#if THR_SERVER_ALARM == THR_CLIENT_ALARM + if (!pthread_equal(pthread_self(),alarm_thread)) { #if defined(MAIN) && !defined(__bsdi__) printf("thread_alarm in process_alarm\n"); fflush(stdout); #endif #ifdef DONT_REMEMBER_SIGNAL - my_sigset(thr_client_alarm, process_alarm); /* int. thread system calls */ + my_sigset(THR_CLIENT_ALARM,process_alarm); /* int. thread system calls */ #endif return; } +#endif /* We have to do do the handling of the alarm in a sub function, @@ -332,7 +326,7 @@ static sig_handler process_alarm_part2(int sig __attribute__((unused))) alarm_data=(ALARM*) queue_element(&alarm_queue,i); alarm_data->alarmed=1; /* Info to thread */ if (pthread_equal(alarm_data->thread,alarm_thread) || - pthread_kill(alarm_data->thread, thr_client_alarm)) + pthread_kill(alarm_data->thread, THR_CLIENT_ALARM)) { #ifdef MAIN printf("Warning: pthread_kill couldn't find thread!!!\n"); @@ -356,7 +350,7 @@ static sig_handler process_alarm_part2(int sig __attribute__((unused))) alarm_data->alarmed=1; /* Info to thread */ DBUG_PRINT("info",("sending signal to waiting thread")); if (pthread_equal(alarm_data->thread,alarm_thread) || - pthread_kill(alarm_data->thread, thr_client_alarm)) + pthread_kill(alarm_data->thread, THR_CLIENT_ALARM)) { #ifdef MAIN printf("Warning: pthread_kill couldn't find thread!!!\n"); @@ -493,7 +487,7 @@ void thr_alarm_info(ALARM_INFO *info) ARGSUSED */ - +#if THR_CLIENT_ALARM != SIGALRM || defined(USE_ALARM_THREAD) static sig_handler thread_alarm(int sig) { #ifdef MAIN @@ -503,6 +497,7 @@ static sig_handler thread_alarm(int sig) my_sigset(sig,thread_alarm); /* int. thread system calls */ #endif } +#endif #ifdef HAVE_TIMESPEC_TS_SEC @@ -788,7 +783,9 @@ static void *signal_hand(void *arg __attribute__((unused))) sigaddset(&set,SIGINT); sigaddset(&set,SIGQUIT); sigaddset(&set,SIGTERM); +#if THR_CLIENT_ALARM != SIGHUP sigaddset(&set,SIGHUP); +#endif #ifdef SIGTSTP sigaddset(&set,SIGTSTP); #endif @@ -799,7 +796,7 @@ static void *signal_hand(void *arg __attribute__((unused))) puts("Starting signal handling thread"); #endif printf("server alarm: %d thread alarm: %d\n", - THR_SERVER_ALARM, thr_client_alarm); + THR_SERVER_ALARM,THR_CLIENT_ALARM); DBUG_PRINT("info",("Starting signal and alarm handling thread")); for(;;) { @@ -867,11 +864,11 @@ int main(int argc __attribute__((unused)),char **argv __attribute__((unused))) sigaddset(&set,SIGTSTP); #endif sigaddset(&set,THR_SERVER_ALARM); - sigdelset(&set, thr_client_alarm); + sigdelset(&set,THR_CLIENT_ALARM); (void) pthread_sigmask(SIG_SETMASK,&set,NULL); #ifdef NOT_USED sigemptyset(&set); - sigaddset(&set, thr_client_alarm); + sigaddset(&set,THR_CLIENT_ALARM); VOID(pthread_sigmask(SIG_UNBLOCK, &set, (sigset_t*) 0)); #endif diff --git a/sql/mysqld.cc b/sql/mysqld.cc index fc2360a8c02..26ab79ac207 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -199,6 +199,12 @@ inline void reset_floating_point_exceptions() } /* cplusplus */ + +#if defined(HAVE_LINUXTHREADS) +#define THR_KILL_SIGNAL SIGINT +#else +#define THR_KILL_SIGNAL SIGUSR2 // Can't use this with LinuxThreads +#endif #define MYSQL_KILL_SIGNAL SIGTERM #ifdef HAVE_GLIBC2_STYLE_GETHOSTBYNAME_R @@ -587,7 +593,6 @@ pthread_mutex_t LOCK_server_started; pthread_cond_t COND_server_started; int mysqld_server_started= 0; -static uint thr_kill_signal; File_parser_dummy_hook file_parser_dummy_hook; @@ -769,7 +774,7 @@ static void close_connections(void) DBUG_PRINT("info",("Waiting for select thread")); #ifndef DONT_USE_THR_ALARM - if (pthread_kill(select_thread, thr_client_alarm)) + if (pthread_kill(select_thread,THR_CLIENT_ALARM)) break; // allready dead #endif set_timespec(abstime, 2); @@ -2206,9 +2211,7 @@ static void init_signals(void) DBUG_ENTER("init_signals"); if (test_flags & TEST_SIGINT) - { - my_sigset(thr_kill_signal, end_thread_signal); - } + my_sigset(THR_KILL_SIGNAL,end_thread_signal); my_sigset(THR_SERVER_ALARM,print_signal_warning); // Should never be called! if (!(test_flags & TEST_NO_STACKTRACE) || (test_flags & TEST_CORE_ON_SIGNAL)) @@ -2265,12 +2268,8 @@ static void init_signals(void) #endif sigaddset(&set,THR_SERVER_ALARM); if (test_flags & TEST_SIGINT) - { - // May be SIGINT - sigdelset(&set, thr_kill_signal); - } - // For alarms - sigdelset(&set, thr_client_alarm); + sigdelset(&set,THR_KILL_SIGNAL); // May be SIGINT + sigdelset(&set,THR_CLIENT_ALARM); // For alarms sigprocmask(SIG_SETMASK,&set,NULL); pthread_sigmask(SIG_SETMASK,&set,NULL); DBUG_VOID_RETURN; @@ -2333,19 +2332,23 @@ pthread_handler_t signal_hand(void *arg __attribute__((unused))) */ init_thr_alarm(max_connections + global_system_variables.max_insert_delayed_threads + 10); - if (thd_lib_detected != THD_LIB_LT && (test_flags & TEST_SIGINT)) +#if SIGINT != THR_KILL_SIGNAL + if (test_flags & TEST_SIGINT) { (void) sigemptyset(&set); // Setup up SIGINT for debug (void) sigaddset(&set,SIGINT); // For debugging (void) pthread_sigmask(SIG_UNBLOCK,&set,NULL); } +#endif (void) sigemptyset(&set); // Setup up SIGINT for debug #ifdef USE_ONE_SIGNAL_HAND (void) sigaddset(&set,THR_SERVER_ALARM); // For alarms #endif #ifndef IGNORE_SIGHUP_SIGQUIT (void) sigaddset(&set,SIGQUIT); +#if THR_CLIENT_ALARM != SIGHUP (void) sigaddset(&set,SIGHUP); +#endif #endif (void) sigaddset(&set,SIGTERM); (void) sigaddset(&set,SIGTSTP); @@ -3508,13 +3511,6 @@ int main(int argc, char **argv) MY_INIT(argv[0]); // init my_sys library & pthreads /* nothing should come before this line ^^^ */ - /* Set signal used to kill MySQL */ -#if defined(SIGUSR2) - thr_kill_signal= thd_lib_detected == THD_LIB_LT ? SIGINT : SIGUSR2; -#else - thr_kill_signal= SIGINT; -#endif - /* Perform basic logger initialization logger. Should be called after MY_INIT, as it initializes mutexes. Log tables are inited later. From 0446aa9cbd0513fdb1e67601ccbac8b935fc7183 Mon Sep 17 00:00:00 2001 From: "mskold/marty@mysql.com/linux.site" <> Date: Tue, 6 Feb 2007 23:06:58 +0100 Subject: [PATCH 37/40] Fix for bug#25821 Excessive partition pruning for multi-range index scan in NDB API: don't set distribution key if multi_range --- mysql-test/r/ndb_read_multi_range.result | 7 +++++++ mysql-test/t/ndb_read_multi_range.test | 9 +++++++++ ndb/include/ndbapi/NdbIndexScanOperation.hpp | 6 ++++-- ndb/include/ndbapi/NdbScanOperation.hpp | 5 ++++- ndb/src/ndbapi/NdbScanOperation.cpp | 5 +++-- sql/ha_ndbcluster.cc | 2 +- sql/ha_ndbcluster.h | 1 + 7 files changed, 29 insertions(+), 6 deletions(-) diff --git a/mysql-test/r/ndb_read_multi_range.result b/mysql-test/r/ndb_read_multi_range.result index d279485e48e..64a6749bed1 100644 --- a/mysql-test/r/ndb_read_multi_range.result +++ b/mysql-test/r/ndb_read_multi_range.result @@ -398,3 +398,10 @@ INSERT INTO t1 VALUES (1,1),(2,2),(3,3); UPDATE t1 SET var2 = 9 WHERE var1 IN(1,2,3); DROP TRIGGER testtrigger; DROP TABLE t1, t2; +create table t2 (a int, b int, primary key (a), key ab (a,b)) engine=ndbcluster; +insert into t2 values (1,1), (10,10); +select * from t2 use index (ab) where a in(1,10) order by a; +a b +1 1 +10 10 +drop table t2; diff --git a/mysql-test/t/ndb_read_multi_range.test b/mysql-test/t/ndb_read_multi_range.test index cfbf0561d1e..e1f1dfc1150 100644 --- a/mysql-test/t/ndb_read_multi_range.test +++ b/mysql-test/t/ndb_read_multi_range.test @@ -282,3 +282,12 @@ UPDATE t1 SET var2 = 9 WHERE var1 IN(1,2,3); DROP TRIGGER testtrigger; DROP TABLE t1, t2; + +#bug#25821 +create table t2 (a int, b int, primary key (a), key ab (a,b)) engine=ndbcluster; + +insert into t2 values (1,1), (10,10); + +select * from t2 use index (ab) where a in(1,10) order by a; + +drop table t2; diff --git a/ndb/include/ndbapi/NdbIndexScanOperation.hpp b/ndb/include/ndbapi/NdbIndexScanOperation.hpp index 7ef66f9a30b..ae7e2579dd8 100644 --- a/ndb/include/ndbapi/NdbIndexScanOperation.hpp +++ b/ndb/include/ndbapi/NdbIndexScanOperation.hpp @@ -64,12 +64,14 @@ public: bool order_by, bool order_desc = false, bool read_range_no = false, - bool keyinfo = false) { + bool keyinfo = false, + bool multi_range = false) { Uint32 scan_flags = (SF_OrderBy & -(Int32)order_by) | (SF_Descending & -(Int32)order_desc) | (SF_ReadRangeNo & -(Int32)read_range_no) | - (SF_KeyInfo & -(Int32)keyinfo); + (SF_KeyInfo & -(Int32)keyinfo) | + (SF_MultiRange & -(Int32)multi_range); return readTuples(lock_mode, scan_flags, parallel, batch); } diff --git a/ndb/include/ndbapi/NdbScanOperation.hpp b/ndb/include/ndbapi/NdbScanOperation.hpp index beaf9402b77..1e03eee5a39 100644 --- a/ndb/include/ndbapi/NdbScanOperation.hpp +++ b/ndb/include/ndbapi/NdbScanOperation.hpp @@ -45,6 +45,7 @@ public: SF_OrderBy = (1 << 24), // index scan in order SF_Descending = (2 << 24), // index scan in descending order SF_ReadRangeNo = (4 << 24), // enable @ref get_range_no + SF_MultiRange = (8 << 24), // scan is part of multi-range scan SF_KeyInfo = 1 // request KeyInfo to be sent back }; @@ -71,7 +72,8 @@ public: */ #ifdef ndb_readtuples_impossible_overload int readTuples(LockMode lock_mode = LM_Read, - Uint32 batch = 0, Uint32 parallel = 0, bool keyinfo = false); + Uint32 batch = 0, Uint32 parallel = 0, + bool keyinfo = false, bool multi_range); #endif inline int readTuples(int parallell){ @@ -263,6 +265,7 @@ protected: bool m_descending; Uint32 m_read_range_no; NdbRecAttr *m_curr_row; // Pointer to last returned row + bool m_multi_range; // Mark if operation is part of multi-range scan }; inline diff --git a/ndb/src/ndbapi/NdbScanOperation.cpp b/ndb/src/ndbapi/NdbScanOperation.cpp index a0322f09256..bccf391acef 100644 --- a/ndb/src/ndbapi/NdbScanOperation.cpp +++ b/ndb/src/ndbapi/NdbScanOperation.cpp @@ -1189,7 +1189,7 @@ NdbIndexScanOperation::setBound(const NdbColumnImpl* tAttrInfo, * so it's safe to use [tIndexAttrId] * (instead of looping as is NdbOperation::equal_impl) */ - if(type == BoundEQ && tDistrKey) + if(type == BoundEQ && tDistrKey && !m_multi_range) { theNoOfTupKeyLeft--; return handle_distribution_key((Uint64*)aValue, sizeInWords); @@ -1250,7 +1250,8 @@ NdbIndexScanOperation::readTuples(LockMode lm, const bool order_by = scan_flags & SF_OrderBy; const bool order_desc = scan_flags & SF_Descending; const bool read_range_no = scan_flags & SF_ReadRangeNo; - + m_multi_range = scan_flags & SF_MultiRange; + int res = NdbScanOperation::readTuples(lm, scan_flags, parallel, batch); if(!res && read_range_no) { diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index 080abf2ce54..f53e1673a16 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -6348,7 +6348,7 @@ ha_ndbcluster::read_multi_range_first(KEY_MULTI_RANGE **found_range_p, } else if ((scanOp= m_active_trans->getNdbIndexScanOperation(idx, tab)) &&!scanOp->readTuples(lm, 0, parallelism, sorted, - FALSE, TRUE, need_pk) + FALSE, TRUE, need_pk, TRUE) &&!generate_scan_filter(m_cond_stack, scanOp) &&!define_read_attrs(end_of_buffer-reclength, scanOp)) { diff --git a/sql/ha_ndbcluster.h b/sql/ha_ndbcluster.h index 5d66a7920f9..eeca67d506a 100644 --- a/sql/ha_ndbcluster.h +++ b/sql/ha_ndbcluster.h @@ -661,6 +661,7 @@ private: const NdbOperation *first, const NdbOperation *last, uint errcode); + bool key_fields_not_in_write_set(THD *thd, const KEY* key_info); int peek_indexed_rows(const byte *record, bool check_pk); int unique_index_read(const byte *key, uint key_len, byte *buf); From 259d3dce267c9a765ff8509267dafef83aa08979 Mon Sep 17 00:00:00 2001 From: "mskold/marty@mysql.com/linux.site" <> Date: Wed, 7 Feb 2007 09:19:33 +0100 Subject: [PATCH 38/40] bug#25821 Excessive partition pruning for multi-range index scan in NDB API: post-review fix, added default value --- ndb/include/ndbapi/NdbScanOperation.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ndb/include/ndbapi/NdbScanOperation.hpp b/ndb/include/ndbapi/NdbScanOperation.hpp index 1e03eee5a39..d1af4732525 100644 --- a/ndb/include/ndbapi/NdbScanOperation.hpp +++ b/ndb/include/ndbapi/NdbScanOperation.hpp @@ -73,7 +73,7 @@ public: #ifdef ndb_readtuples_impossible_overload int readTuples(LockMode lock_mode = LM_Read, Uint32 batch = 0, Uint32 parallel = 0, - bool keyinfo = false, bool multi_range); + bool keyinfo = false, bool multi_range = false); #endif inline int readTuples(int parallell){ From 931a48904d8193390526e30a205d474220303da1 Mon Sep 17 00:00:00 2001 From: "mskold/marty@mysql.com/linux.site" <> Date: Wed, 7 Feb 2007 09:49:16 +0100 Subject: [PATCH 39/40] bug#25821 Excessive partition pruning for multi-range index scan in NDB API: added original test case --- mysql-test/r/ndb_read_multi_range.result | 15 +++++++++++---- mysql-test/t/ndb_read_multi_range.test | 13 ++++++++++--- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/mysql-test/r/ndb_read_multi_range.result b/mysql-test/r/ndb_read_multi_range.result index 12009d9d080..aef009212a4 100644 --- a/mysql-test/r/ndb_read_multi_range.result +++ b/mysql-test/r/ndb_read_multi_range.result @@ -459,10 +459,17 @@ INSERT INTO t1 VALUES (1,1),(2,2),(3,3); UPDATE t1 SET var2 = 9 WHERE var1 IN(1,2,3); DROP TRIGGER testtrigger; DROP TABLE t1, t2; -create table t2 (a int, b int, primary key (a), key ab (a,b)) engine=ndbcluster; -insert into t2 values (1,1), (10,10); -select * from t2 use index (ab) where a in(1,10) order by a; +create table t1 (a int, b int, primary key (a), key ab (a,b)) engine=ndbcluster; +insert into t1 values (1,1), (10,10); +select * from t1 use index (ab) where a in(1,10) order by a; a b 1 1 10 10 -drop table t2; +create table t2 (a int, b int, primary key (a,b)) engine=ndbcluster +partition by key(a); +insert into t2 values (1,1), (10,10); +select * from t2 where a in (1,10) order by a; +a b +1 1 +10 10 +drop table t1, t2; diff --git a/mysql-test/t/ndb_read_multi_range.test b/mysql-test/t/ndb_read_multi_range.test index 853d8919088..b490eeb68a3 100644 --- a/mysql-test/t/ndb_read_multi_range.test +++ b/mysql-test/t/ndb_read_multi_range.test @@ -303,10 +303,17 @@ DROP TRIGGER testtrigger; DROP TABLE t1, t2; #bug#25821 -create table t2 (a int, b int, primary key (a), key ab (a,b)) engine=ndbcluster; +create table t1 (a int, b int, primary key (a), key ab (a,b)) engine=ndbcluster; + +insert into t1 values (1,1), (10,10); + +select * from t1 use index (ab) where a in(1,10) order by a; + +create table t2 (a int, b int, primary key (a,b)) engine=ndbcluster +partition by key(a); insert into t2 values (1,1), (10,10); -select * from t2 use index (ab) where a in(1,10) order by a; +select * from t2 where a in (1,10) order by a; -drop table t2; +drop table t1, t2; From 2d0bd82a06ef744fb4a1b4bd7b974279437f6632 Mon Sep 17 00:00:00 2001 From: "mskold/marty@mysql.com/linux.site" <> Date: Wed, 7 Feb 2007 11:36:34 +0100 Subject: [PATCH 40/40] NdbScanOperation.hpp, NdbScanOperation.cpp, ha_ndbcluster.cc: bug#25821 Excessive partition pruning for multi-range index scan in NDB API: added multi_range error checking in end_of_bound ha_ndbcluster.h: Removed stray mthod declaration --- ndb/include/ndbapi/NdbScanOperation.hpp | 3 ++- ndb/src/ndbapi/NdbScanOperation.cpp | 10 ++++++++-- sql/ha_ndbcluster.cc | 6 ++---- sql/ha_ndbcluster.h | 1 - 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/ndb/include/ndbapi/NdbScanOperation.hpp b/ndb/include/ndbapi/NdbScanOperation.hpp index d1af4732525..88f96c88031 100644 --- a/ndb/include/ndbapi/NdbScanOperation.hpp +++ b/ndb/include/ndbapi/NdbScanOperation.hpp @@ -38,7 +38,8 @@ class NdbScanOperation : public NdbOperation { public: /** * Scan flags. OR-ed together and passed as second argument to - * readTuples. + * readTuples. Note that SF_MultiRange has to be set if several + * ranges (bounds) are to be passed. */ enum ScanFlag { SF_TupScan = (1 << 16), // scan TUP diff --git a/ndb/src/ndbapi/NdbScanOperation.cpp b/ndb/src/ndbapi/NdbScanOperation.cpp index bccf391acef..e30e9cb66e9 100644 --- a/ndb/src/ndbapi/NdbScanOperation.cpp +++ b/ndb/src/ndbapi/NdbScanOperation.cpp @@ -1718,6 +1718,12 @@ NdbIndexScanOperation::reset_bounds(bool forceSend){ int NdbIndexScanOperation::end_of_bound(Uint32 no) { + DBUG_ENTER("end_of_bound"); + DBUG_PRINT("info", ("Range number %u", no)); + /* Check that SF_MultiRange has been specified if more + than one range is specified */ + if (no > 0 && !m_multi_range) + DBUG_RETURN(-1); if(no < (1 << 13)) // Only 12-bits no of ranges { Uint32 bound_head = * m_first_bound_word; @@ -1726,9 +1732,9 @@ NdbIndexScanOperation::end_of_bound(Uint32 no) m_first_bound_word = theKEYINFOptr + theTotalNrOfKeyWordInSignal;; m_this_bound_start = theTupKeyLen; - return 0; + DBUG_RETURN(0); } - return -1; + DBUG_RETURN(-1); } int diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index f53e1673a16..514d4b83a04 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -1996,8 +1996,7 @@ int ha_ndbcluster::set_bounds(NdbIndexScanOperation *op, DBUG_PRINT("error", ("key %d unknown flag %d", j, p.key->flag)); DBUG_ASSERT(FALSE); // Stop setting bounds but continue with what we have - op->end_of_bound(range_no); - DBUG_RETURN(0); + DBUG_RETURN(op->end_of_bound(range_no)); } } } @@ -2044,8 +2043,7 @@ int ha_ndbcluster::set_bounds(NdbIndexScanOperation *op, tot_len+= part_store_len; } - op->end_of_bound(range_no); - DBUG_RETURN(0); + DBUG_RETURN(op->end_of_bound(range_no)); } /* diff --git a/sql/ha_ndbcluster.h b/sql/ha_ndbcluster.h index eeca67d506a..5d66a7920f9 100644 --- a/sql/ha_ndbcluster.h +++ b/sql/ha_ndbcluster.h @@ -661,7 +661,6 @@ private: const NdbOperation *first, const NdbOperation *last, uint errcode); - bool key_fields_not_in_write_set(THD *thd, const KEY* key_info); int peek_indexed_rows(const byte *record, bool check_pk); int unique_index_read(const byte *key, uint key_len, byte *buf);