diff options
author | unknown <tomas@whalegate.ndb.mysql.com> | 2007-03-23 08:20:36 +0100 |
---|---|---|
committer | unknown <tomas@whalegate.ndb.mysql.com> | 2007-03-23 08:20:36 +0100 |
commit | 9fb4f3cda8aa97d883e6927c4a603cbb1793efa0 (patch) | |
tree | 7a38b5185da3d93a1b74b63af9c74229bbedc958 /storage | |
parent | 95b334506ce0614718a0bf9826dd274db95749d4 (diff) | |
parent | 0ca0887b24100441a4da8b6e7646e20b2dce098e (diff) | |
download | mariadb-git-9fb4f3cda8aa97d883e6927c4a603cbb1793efa0.tar.gz |
Merge whalegate.ndb.mysql.com:/home/tomas/mysql-5.1-new-ndb
into whalegate.ndb.mysql.com:/home/tomas/mysql-5.1-single-user
sql/ha_ndbcluster.cc:
Auto merged
storage/ndb/src/kernel/blocks/dbtc/Dbtc.hpp:
Auto merged
storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp:
Auto merged
Diffstat (limited to 'storage')
-rw-r--r-- | storage/ndb/include/ndbapi/NdbRecAttr.hpp | 50 | ||||
-rw-r--r-- | storage/ndb/include/util/OutputStream.hpp | 1 | ||||
-rw-r--r-- | storage/ndb/src/kernel/blocks/dbtc/Dbtc.hpp | 11 | ||||
-rw-r--r-- | storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp | 133 | ||||
-rw-r--r-- | storage/ndb/src/ndbapi/ClusterMgr.cpp | 2 | ||||
-rw-r--r-- | storage/ndb/src/ndbapi/Ndb.cpp | 11 | ||||
-rw-r--r-- | storage/ndb/src/ndbapi/NdbRecAttr.cpp | 144 | ||||
-rw-r--r-- | storage/ndb/src/ndbapi/TransporterFacade.hpp | 16 | ||||
-rw-r--r-- | storage/ndb/tools/restore/Restore.cpp | 18 | ||||
-rw-r--r-- | storage/ndb/tools/restore/Restore.hpp | 11 | ||||
-rw-r--r-- | storage/ndb/tools/restore/consumer_printer.cpp | 22 | ||||
-rw-r--r-- | storage/ndb/tools/restore/consumer_restore.cpp | 35 | ||||
-rw-r--r-- | storage/ndb/tools/restore/restore_main.cpp | 337 |
13 files changed, 672 insertions, 119 deletions
diff --git a/storage/ndb/include/ndbapi/NdbRecAttr.hpp b/storage/ndb/include/ndbapi/NdbRecAttr.hpp index 40d5b598c0c..fe903de6498 100644 --- a/storage/ndb/include/ndbapi/NdbRecAttr.hpp +++ b/storage/ndb/include/ndbapi/NdbRecAttr.hpp @@ -131,6 +131,13 @@ public: /** * Get value stored in NdbRecAttr object. + * + * @return Medium value. + */ + Int32 medium_value() const; + + /** + * Get value stored in NdbRecAttr object. * * @return Short value. */ @@ -160,6 +167,13 @@ public: /** * Get value stored in NdbRecAttr object. * + * @return Unsigned medium value. + */ + Uint32 u_medium_value() const; + + /** + * Get value stored in NdbRecAttr object. + * * @return Unsigned short value. */ Uint16 u_short_value() const; @@ -288,6 +302,16 @@ NdbRecAttr::int32_value() const } inline +Int32 +NdbRecAttr::medium_value() const +{ + Uint32 tmp = *(Uint32*)theRef; + if (tmp & (0x1<<23)) + tmp|= (0xFF<<24); + return (Int32)tmp; +} + +inline short NdbRecAttr::short_value() const { @@ -309,6 +333,13 @@ NdbRecAttr::u_32_value() const } inline +Uint32 +NdbRecAttr::u_medium_value() const +{ + return *(Uint32*)theRef; +} + +inline Uint16 NdbRecAttr::u_short_value() const { @@ -409,6 +440,25 @@ NdbRecAttr::setUNDEFINED() class NdbOut& operator <<(class NdbOut&, const NdbRecAttr &); +class NdbRecordPrintFormat +{ +public: + NdbRecordPrintFormat(); + virtual ~NdbRecordPrintFormat(); + const char *lines_terminated_by; + const char *fields_terminated_by; + const char *start_array_enclosure; + const char *end_array_enclosure; + const char *fields_enclosed_by; + const char *fields_optionally_enclosed_by; + const char *hex_prefix; + const char *null_string; + int hex_format; +}; +NdbOut& +ndbrecattr_print_formatted(NdbOut& out, const NdbRecAttr &r, + const NdbRecordPrintFormat &f); + #endif // ifndef DOXYGEN_SHOULD_SKIP_INTERNAL #endif diff --git a/storage/ndb/include/util/OutputStream.hpp b/storage/ndb/include/util/OutputStream.hpp index d56d04adc50..78072320493 100644 --- a/storage/ndb/include/util/OutputStream.hpp +++ b/storage/ndb/include/util/OutputStream.hpp @@ -36,6 +36,7 @@ class FileOutputStream : public OutputStream { public: FileOutputStream(FILE * file = stdout); virtual ~FileOutputStream() {} + FILE *getFile() { return f; } int print(const char * fmt, ...); int println(const char * fmt, ...); diff --git a/storage/ndb/src/kernel/blocks/dbtc/Dbtc.hpp b/storage/ndb/src/kernel/blocks/dbtc/Dbtc.hpp index 302e395f19e..652ed2dee10 100644 --- a/storage/ndb/src/kernel/blocks/dbtc/Dbtc.hpp +++ b/storage/ndb/src/kernel/blocks/dbtc/Dbtc.hpp @@ -1840,9 +1840,14 @@ private: Uint32 transid2); void removeMarkerForFailedAPI(Signal* signal, Uint32 nodeId, Uint32 bucket); - bool getAllowStartTransaction() const { - if(getNodeState().getSingleUserMode()) - return true; + bool getAllowStartTransaction(Uint32 nodeId) const { + if (unlikely(getNodeState().getSingleUserMode())) + { + if (getNodeState().getSingleUserApi() == nodeId) + return true; + else + return false; + } return getNodeState().startLevel < NodeState::SL_STOPPING_2; } diff --git a/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp b/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp index 7e7a264d1be..b7bdd1d5f7c 100644 --- a/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp +++ b/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp @@ -1202,16 +1202,14 @@ void Dbtc::execTCSEIZEREQ(Signal* signal) const NodeId senderNodeId = refToNode(tapiBlockref); const bool local = senderNodeId == getOwnNodeId() || senderNodeId == 0; - if(!(senderNodeId == getNodeState().getSingleUserApi()) && - !getNodeState().getSingleUserMode()) { - if(!(sl==NodeState::SL_SINGLEUSER && - senderNodeId == getNodeState().getSingleUserApi())) { + { + { if (!(sl == NodeState::SL_STARTED || (sl == NodeState::SL_STARTING && local == true))) { jam(); - Uint32 errCode; - if(!(sl == NodeState::SL_SINGLEUSER && local)) + Uint32 errCode = 0; + if(!local) { switch(sl){ case NodeState::SL_STARTING: @@ -1219,6 +1217,9 @@ void Dbtc::execTCSEIZEREQ(Signal* signal) break; case NodeState::SL_STOPPING_1: case NodeState::SL_STOPPING_2: + if (getNodeState().getSingleUserMode() && + getNodeState().getSingleUserApi() == senderNodeId) + break; case NodeState::SL_STOPPING_3: case NodeState::SL_STOPPING_4: if(getNodeState().stopping.systemShutdown) @@ -1227,16 +1228,21 @@ void Dbtc::execTCSEIZEREQ(Signal* signal) errCode = ZNODE_SHUTDOWN_IN_PROGRESS; break; case NodeState::SL_SINGLEUSER: + if (getNodeState().getSingleUserApi() == senderNodeId) + break; errCode = ZCLUSTER_IN_SINGLEUSER_MODE; break; default: errCode = ZWRONG_STATE; break; } - signal->theData[0] = tapiPointer; - signal->theData[1] = errCode; - sendSignal(tapiBlockref, GSN_TCSEIZEREF, signal, 2, JBB); - return; + if (errCode) + { + signal->theData[0] = tapiPointer; + signal->theData[1] = errCode; + sendSignal(tapiBlockref, GSN_TCSEIZEREF, signal, 2, JBB); + return; + } }//if (!(sl == SL_SINGLEUSER)) } //if } @@ -1724,8 +1730,14 @@ Dbtc::TCKEY_abort(Signal* signal, int place) * Initialize object before starting error handling */ initApiConnectRec(signal, apiConnectptr.p, true); +start_failure: switch(getNodeState().startLevel){ case NodeState::SL_STOPPING_2: + if (getNodeState().getSingleUserMode()) + { + terrorCode = ZCLUSTER_IN_SINGLEUSER_MODE; + break; + } case NodeState::SL_STOPPING_3: case NodeState::SL_STOPPING_4: if(getNodeState().stopping.systemShutdown) @@ -1736,6 +1748,12 @@ Dbtc::TCKEY_abort(Signal* signal, int place) case NodeState::SL_SINGLEUSER: terrorCode = ZCLUSTER_IN_SINGLEUSER_MODE; break; + case NodeState::SL_STOPPING_1: + if (getNodeState().getSingleUserMode()) + { + terrorCode = ZCLUSTER_IN_SINGLEUSER_MODE; + break; + } default: terrorCode = ZWRONG_STATE; break; @@ -1757,6 +1775,13 @@ Dbtc::TCKEY_abort(Signal* signal, int place) return; } + case 60: + { + jam(); + initApiConnectRec(signal, apiConnectptr.p, true); + apiConnectptr.p->m_exec_flag = 1; + goto start_failure; + } default: jam(); systemErrorLab(signal, __LINE__); @@ -2486,6 +2511,7 @@ Dbtc::seizeCacheRecord(Signal* signal) /*****************************************************************************/ void Dbtc::execTCKEYREQ(Signal* signal) { + Uint32 sendersNodeId = refToNode(signal->getSendersBlockRef()); UintR compare_transid1, compare_transid2; UintR titcLenAiInTckeyreq; UintR TkeyLength; @@ -2531,7 +2557,7 @@ void Dbtc::execTCKEYREQ(Signal* signal) regApiPtr->m_exec_flag |= TexecFlag; switch (regApiPtr->apiConnectstate) { case CS_CONNECTED:{ - if (TstartFlag == 1 && getAllowStartTransaction() == true){ + if (TstartFlag == 1 && getAllowStartTransaction(sendersNodeId) == true){ //--------------------------------------------------------------------- // Initialise API connect record if transaction is started. //--------------------------------------------------------------------- @@ -2539,7 +2565,7 @@ void Dbtc::execTCKEYREQ(Signal* signal) initApiConnectRec(signal, regApiPtr); regApiPtr->m_exec_flag = TexecFlag; } else { - if(getAllowStartTransaction() == true){ + if(getAllowStartTransaction(sendersNodeId) == true){ /*------------------------------------------------------------------ * WE EXPECTED A START TRANSACTION. SINCE NO OPERATIONS HAVE BEEN * RECEIVED WE INDICATE THIS BY SETTING FIRST_TC_CONNECT TO RNIL TO @@ -2549,9 +2575,9 @@ void Dbtc::execTCKEYREQ(Signal* signal) return; } else { /** - * getAllowStartTransaction() == false + * getAllowStartTransaction(sendersNodeId) == false */ - TCKEY_abort(signal, 57); + TCKEY_abort(signal, TexecFlag ? 60 : 57); return; }//if } @@ -6154,9 +6180,11 @@ and otherwise we spread it out 310 ms. void Dbtc::timeOutLoopStartLab(Signal* signal, Uint32 api_con_ptr) { Uint32 end_ptr, time_passed, time_out_value, mask_value; + Uint32 old_mask_value= 0; const Uint32 api_con_sz= capiConnectFilesize; const Uint32 tc_timer= ctcTimer; const Uint32 time_out_param= ctimeOutValue; + const Uint32 old_time_out_param= c_abortRec.oldTimeOutValue; ctimeOutCheckHeartbeat = tc_timer; @@ -6177,11 +6205,39 @@ void Dbtc::timeOutLoopStartLab(Signal* signal, Uint32 api_con_ptr) jam(); mask_value= 31; } + if (time_out_param != old_time_out_param && + getNodeState().getSingleUserMode()) + { + // abort during single user mode, use old_mask_value as flag + // and calculate value to be used for connections with allowed api + if (old_time_out_param > 300) { + jam(); + old_mask_value= 63; + } else if (old_time_out_param < 30) { + jam(); + old_mask_value= 7; + } else { + jam(); + old_mask_value= 31; + } + } for ( ; api_con_ptr < end_ptr; api_con_ptr++) { Uint32 api_timer= getApiConTimer(api_con_ptr); jam(); if (api_timer != 0) { time_out_value= time_out_param + (api_con_ptr & mask_value); + if (unlikely(old_mask_value)) // abort during single user mode + { + apiConnectptr.i = api_con_ptr; + ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord); + if (getNodeState().getSingleUserApi() == + refToNode(apiConnectptr.p->ndbapiBlockref)) + { + // api allowed during single user, use original timeout + time_out_value= + old_time_out_param + (api_con_ptr & old_mask_value); + } + } time_passed= tc_timer - api_timer; if (time_passed > time_out_value) { @@ -6798,6 +6854,33 @@ void Dbtc::timeOutFoundFragLab(Signal* signal, UintR TscanConPtr) c_scan_frag_pool.getPtr(ptr, TscanConPtr); DEBUG(TscanConPtr << " timeOutFoundFragLab: scanFragState = "<< ptr.p->scanFragState); + const Uint32 time_out_param= ctimeOutValue; + const Uint32 old_time_out_param= c_abortRec.oldTimeOutValue; + + if (unlikely(time_out_param != old_time_out_param && + getNodeState().getSingleUserMode())) + { + jam(); + ScanRecordPtr scanptr; + scanptr.i = ptr.p->scanRec; + ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord); + ApiConnectRecordPtr TlocalApiConnectptr; + TlocalApiConnectptr.i = scanptr.p->scanApiRec; + ptrCheckGuard(TlocalApiConnectptr, capiConnectFilesize, apiConnectRecord); + + if (refToNode(TlocalApiConnectptr.p->ndbapiBlockref) == + getNodeState().getSingleUserApi()) + { + jam(); + Uint32 val = ctcTimer - ptr.p->scanFragTimer; + if (val <= old_time_out_param) + { + jam(); + goto next; + } + } + } + /*-------------------------------------------------------------------------*/ // The scan fragment has expired its timeout. Check its state to decide // what to do. @@ -6859,6 +6942,7 @@ void Dbtc::timeOutFoundFragLab(Signal* signal, UintR TscanConPtr) break; }//switch +next: signal->theData[0] = TcContinueB::ZCONTINUE_TIME_OUT_FRAG_CONTROL; signal->theData[1] = TscanConPtr + 1; sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB); @@ -8689,6 +8773,14 @@ void Dbtc::execSCAN_TABREQ(Signal* signal) } } + if (getNodeState().startLevel == NodeState::SL_SINGLEUSER && + getNodeState().getSingleUserApi() != + refToNode(apiConnectptr.p->ndbapiBlockref)) + { + errCode = ZCLUSTER_IN_SINGLEUSER_MODE; + goto SCAN_TAB_error; + } + seizeTcConnect(signal); tcConnectptr.p->apiConnect = apiConnectptr.i; tcConnectptr.p->tcConnectstate = OS_WAIT_SCAN; @@ -11009,7 +11101,7 @@ void Dbtc::execABORT_ALL_REQ(Signal* signal) const Uint32 senderData = req->senderData; const BlockReference senderRef = req->senderRef; - if(getAllowStartTransaction() == true && !getNodeState().getSingleUserMode()){ + if(getAllowStartTransaction(refToNode(senderRef)) == true && !getNodeState().getSingleUserMode()){ jam(); ref->senderData = senderData; @@ -11437,6 +11529,17 @@ void Dbtc::execTCINDXREQ(Signal* signal) regApiPtr->transid[1] = tcIndxReq->transId2; }//if + if (getNodeState().startLevel == NodeState::SL_SINGLEUSER && + getNodeState().getSingleUserApi() != + refToNode(regApiPtr->ndbapiBlockref)) + { + terrorCode = ZCLUSTER_IN_SINGLEUSER_MODE; + regApiPtr->m_exec_flag |= TcKeyReq::getExecuteFlag(tcIndxRequestInfo); + apiConnectptr = transPtr; + abortErrorLab(signal); + return; + } + if (ERROR_INSERTED(8036) || !seizeIndexOperation(regApiPtr, indexOpPtr)) { jam(); // Failed to allocate index operation diff --git a/storage/ndb/src/ndbapi/ClusterMgr.cpp b/storage/ndb/src/ndbapi/ClusterMgr.cpp index 2a794f69ecb..52c95df6d15 100644 --- a/storage/ndb/src/ndbapi/ClusterMgr.cpp +++ b/storage/ndb/src/ndbapi/ClusterMgr.cpp @@ -389,7 +389,7 @@ ClusterMgr::execAPI_REGCONF(const Uint32 * theData){ node.m_state = apiRegConf->nodeState; if (node.compatible && (node.m_state.startLevel == NodeState::SL_STARTED || - node.m_state.startLevel == NodeState::SL_SINGLEUSER)){ + node.m_state.getSingleUserMode())){ set_node_alive(node, true); } else { set_node_alive(node, false); diff --git a/storage/ndb/src/ndbapi/Ndb.cpp b/storage/ndb/src/ndbapi/Ndb.cpp index e90dfbfa959..495b848645f 100644 --- a/storage/ndb/src/ndbapi/Ndb.cpp +++ b/storage/ndb/src/ndbapi/Ndb.cpp @@ -58,6 +58,8 @@ NdbTransaction* Ndb::doConnect(Uint32 tConNode) // We have connections now to the desired node. Return //**************************************************************************** DBUG_RETURN(getConnectedNdbTransaction(tConNode)); + } else if (TretCode < 0) { + DBUG_RETURN(NULL); } else if (TretCode != 0) { tAnyAlive = 1; }//if @@ -81,6 +83,8 @@ NdbTransaction* Ndb::doConnect(Uint32 tConNode) // We have connections now to the desired node. Return //**************************************************************************** DBUG_RETURN(getConnectedNdbTransaction(tNode)); + } else if (TretCode < 0) { + DBUG_RETURN(NULL); } else if (TretCode != 0) { tAnyAlive= 1; }//if @@ -109,6 +113,8 @@ NdbTransaction* Ndb::doConnect(Uint32 tConNode) // We have connections now to the desired node. Return //**************************************************************************** DBUG_RETURN(getConnectedNdbTransaction(tNode)); + } else if (TretCode < 0) { + DBUG_RETURN(NULL); } else if (TretCode != 0) { tAnyAlive= 1; }//if @@ -195,6 +201,11 @@ Ndb::NDB_connect(Uint32 tNode) DBUG_PRINT("info", ("unsuccessful connect tReturnCode %d, tNdbCon->Status() %d", tReturnCode, tNdbCon->Status())); + if (theError.code == 299) + { + // single user mode so no need to retry with other node + DBUG_RETURN(-1); + } DBUG_RETURN(3); }//if }//Ndb::NDB_connect() diff --git a/storage/ndb/src/ndbapi/NdbRecAttr.cpp b/storage/ndb/src/ndbapi/NdbRecAttr.cpp index 188e718d968..0bd0cdf8572 100644 --- a/storage/ndb/src/ndbapi/NdbRecAttr.cpp +++ b/storage/ndb/src/ndbapi/NdbRecAttr.cpp @@ -138,8 +138,24 @@ NdbRecAttr::receive_data(const Uint32 * data, Uint32 sz) return false; } +NdbRecordPrintFormat::NdbRecordPrintFormat() +{ + fields_terminated_by= ";"; + start_array_enclosure= "["; + end_array_enclosure= "]"; + fields_enclosed_by= ""; + fields_optionally_enclosed_by= "\""; + lines_terminated_by= "\n"; + hex_prefix= "H'"; + null_string= "[NULL]"; + hex_format= 0; +} +NdbRecordPrintFormat::~NdbRecordPrintFormat() {} +static const NdbRecordPrintFormat default_print_format; + static void -ndbrecattr_print_string(NdbOut& out, const char *type, +ndbrecattr_print_string(NdbOut& out, const NdbRecordPrintFormat &f, + const char *type, bool is_binary, const char *aref, unsigned sz) { const unsigned char* ref = (const unsigned char*)aref; @@ -148,6 +164,25 @@ ndbrecattr_print_string(NdbOut& out, const char *type, for (i=sz-1; i >= 0; i--) if (ref[i] == 0) sz--; else break; + if (!is_binary) + { + // trailing spaces are not printed + for (i=sz-1; i >= 0; i--) + if (ref[i] == 32) sz--; + else break; + } + if (is_binary && f.hex_format) + { + if (sz == 0) + { + out.print("0x0"); + return; + } + out.print("0x"); + for (len = 0; len < (int)sz; len++) + out.print("%02X", (int)ref[len]); + return; + } if (sz == 0) return; // empty for (len=0; len < (int)sz && ref[i] != 0; len++) @@ -168,37 +203,68 @@ ndbrecattr_print_string(NdbOut& out, const char *type, for (i= len+1; ref[i] != 0; i++) out.print("%u]",len-i); assert((int)sz > i); - ndbrecattr_print_string(out,type,aref+i,sz-i); + ndbrecattr_print_string(out,f,type,is_binary,aref+i,sz-i); } } -NdbOut& operator<<(NdbOut& out, const NdbRecAttr &r) +NdbOut& +ndbrecattr_print_formatted(NdbOut& out, const NdbRecAttr &r, + const NdbRecordPrintFormat &f) { if (r.isNULL()) { - out << "[NULL]"; + out << f.null_string; return out; } const NdbDictionary::Column* c = r.getColumn(); uint length = c->getLength(); - if (length > 1) - out << "["; - - for (Uint32 j = 0; j < length; j++) { - if (j > 0) - out << " "; - + const char *fields_optionally_enclosed_by; + if (f.fields_enclosed_by[0] == '\0') + fields_optionally_enclosed_by= + f.fields_optionally_enclosed_by; + else + fields_optionally_enclosed_by= ""; + out << f.fields_enclosed_by; + Uint32 j; switch(r.getType()){ case NdbDictionary::Column::Bigunsigned: out << r.u_64_value(); break; case NdbDictionary::Column::Bit: - out << hex << "H'" << r.u_32_value() << dec; + out << f.hex_prefix << "0x"; + if (length < 33) + { + out.print("%X", r.u_32_value()); + } + else if (length < 65) + { + out.print("%llX", r.u_64_value()); + } + else + { + const unsigned char *buf = (unsigned char *)r.aRef(); + int k = 4*((length+31)/32); + while (k > 0 && (*(buf + --k) == 0)); + do + { + out.print("%X", (Uint32)*(buf + k--)); + } + while (k >= 0); + } break; case NdbDictionary::Column::Unsigned: - out << *((Uint32*)r.aRef() + j); + if (length > 1) + out << f.start_array_enclosure; + out << *(Uint32*)r.aRef(); + for (j = 1; j < length; j++) + out << " " << *((Uint32*)r.aRef() + j); + if (length > 1) + out << f.end_array_enclosure; + break; + case NdbDictionary::Column::Mediumunsigned: + out << r.u_medium_value(); break; case NdbDictionary::Column::Smallunsigned: out << r.u_short_value(); @@ -212,6 +278,9 @@ NdbOut& operator<<(NdbOut& out, const NdbRecAttr &r) case NdbDictionary::Column::Int: out << r.int32_value(); break; + case NdbDictionary::Column::Mediumint: + out << r.medium_value(); + break; case NdbDictionary::Column::Smallint: out << r.short_value(); break; @@ -219,25 +288,37 @@ NdbOut& operator<<(NdbOut& out, const NdbRecAttr &r) out << (int) r.char_value(); break; case NdbDictionary::Column::Binary: + if (!f.hex_format) + out << fields_optionally_enclosed_by; j = r.get_size_in_bytes(); - ndbrecattr_print_string(out,"Binary", r.aRef(), j); + ndbrecattr_print_string(out,f,"Binary", true, r.aRef(), j); + if (!f.hex_format) + out << fields_optionally_enclosed_by; break; case NdbDictionary::Column::Char: + out << fields_optionally_enclosed_by; j = r.get_size_in_bytes(); - ndbrecattr_print_string(out,"Char", r.aRef(), j); + ndbrecattr_print_string(out,f,"Char", false, r.aRef(), j); + out << fields_optionally_enclosed_by; break; case NdbDictionary::Column::Varchar: { + out << fields_optionally_enclosed_by; unsigned len = *(const unsigned char*)r.aRef(); - ndbrecattr_print_string(out,"Varchar", r.aRef()+1,len); + ndbrecattr_print_string(out,f,"Varchar", false, r.aRef()+1,len); j = length; + out << fields_optionally_enclosed_by; } break; case NdbDictionary::Column::Varbinary: { + if (!f.hex_format) + out << fields_optionally_enclosed_by; unsigned len = *(const unsigned char*)r.aRef(); - ndbrecattr_print_string(out,"Varbinary", r.aRef()+1,len); + ndbrecattr_print_string(out,f,"Varbinary", true, r.aRef()+1,len); j = length; + if (!f.hex_format) + out << fields_optionally_enclosed_by; } break; case NdbDictionary::Column::Float: @@ -366,16 +447,26 @@ NdbOut& operator<<(NdbOut& out, const NdbRecAttr &r) break; case NdbDictionary::Column::Longvarchar: { + out << fields_optionally_enclosed_by; + unsigned len = uint2korr(r.aRef()); + ndbrecattr_print_string(out,f,"Longvarchar", false, r.aRef()+2,len); + j = length; + out << fields_optionally_enclosed_by; + } + break; + case NdbDictionary::Column::Longvarbinary: + { + if (!f.hex_format) + out << fields_optionally_enclosed_by; unsigned len = uint2korr(r.aRef()); - ndbrecattr_print_string(out,"Longvarchar", r.aRef()+2,len); + ndbrecattr_print_string(out,f,"Longvarbinary", true, r.aRef()+2,len); j = length; + if (!f.hex_format) + out << fields_optionally_enclosed_by; } break; case NdbDictionary::Column::Undefined: - case NdbDictionary::Column::Mediumint: - case NdbDictionary::Column::Mediumunsigned: - case NdbDictionary::Column::Longvarbinary: unknown: //default: /* no print functions for the rest, just print type */ out << (int) r.getType(); @@ -384,16 +475,17 @@ NdbOut& operator<<(NdbOut& out, const NdbRecAttr &r) out << " " << j << " times"; break; } - } - - if (length > 1) - { - out << "]"; + out << f.fields_enclosed_by; } return out; } +NdbOut& operator<<(NdbOut& out, const NdbRecAttr &r) +{ + return ndbrecattr_print_formatted(out, r, default_print_format); +} + Int64 NdbRecAttr::int64_value() const { diff --git a/storage/ndb/src/ndbapi/TransporterFacade.hpp b/storage/ndb/src/ndbapi/TransporterFacade.hpp index d19974f8999..23fea8792f7 100644 --- a/storage/ndb/src/ndbapi/TransporterFacade.hpp +++ b/storage/ndb/src/ndbapi/TransporterFacade.hpp @@ -365,7 +365,8 @@ inline bool TransporterFacade::get_node_stopping(NodeId n) const { const ClusterMgr::Node & node = theClusterMgr->getNodeInfo(n); - return ((node.m_state.startLevel == NodeState::SL_STOPPING_1) || + return (!node.m_state.getSingleUserMode() && + (node.m_state.startLevel == NodeState::SL_STOPPING_1) || (node.m_state.startLevel == NodeState::SL_STOPPING_2)); } @@ -376,16 +377,9 @@ TransporterFacade::getIsNodeSendable(NodeId n) const { const Uint32 startLevel = node.m_state.startLevel; if (node.m_info.m_type == NodeInfo::DB) { - if(node.m_state.singleUserMode && - ownId() == node.m_state.singleUserApi) { - return (node.compatible && - (node.m_state.startLevel == NodeState::SL_STOPPING_1 || - node.m_state.startLevel == NodeState::SL_STARTED || - node.m_state.startLevel == NodeState::SL_SINGLEUSER)); - } - else - return node.compatible && (startLevel == NodeState::SL_STARTED || - startLevel == NodeState::SL_STOPPING_1); + return node.compatible && (startLevel == NodeState::SL_STARTED || + startLevel == NodeState::SL_STOPPING_1 || + node.m_state.getSingleUserMode()); } else { ndbout_c("TransporterFacade::getIsNodeSendable: Illegal node type: " "%d of node: %d", diff --git a/storage/ndb/tools/restore/Restore.cpp b/storage/ndb/tools/restore/Restore.cpp index 6b00d69108d..f99cacfc613 100644 --- a/storage/ndb/tools/restore/Restore.cpp +++ b/storage/ndb/tools/restore/Restore.cpp @@ -27,6 +27,7 @@ #include <NdbAutoPtr.hpp> #include "../../../../sql/ha_ndbcluster_tables.h" +extern NdbRecordPrintFormat g_ndbrecord_print_format; Uint16 Twiddle16(Uint16 in); // Byte shift 16-bit data Uint32 Twiddle32(Uint32 in); // Byte shift 32-bit data @@ -298,6 +299,7 @@ RestoreMetaData::markSysTables() Uint32 i; for (i = 0; i < getNoOfTables(); i++) { TableS* table = allTables[i]; + table->m_local_id = i; const char* tableName = table->getTableName(); if ( // XXX should use type strcmp(tableName, "SYSTAB_0") == 0 || @@ -314,6 +316,7 @@ RestoreMetaData::markSysTables() strcmp(tableName, OLD_NDB_REP_DB "/def/" OLD_NDB_SCHEMA_TABLE) == 0 || strcmp(tableName, NDB_REP_DB "/def/" NDB_APPLY_TABLE) == 0 || strcmp(tableName, NDB_REP_DB "/def/" NDB_SCHEMA_TABLE)== 0 ) + table->isSysTable = true; } for (i = 0; i < getNoOfTables(); i++) { @@ -331,6 +334,7 @@ RestoreMetaData::markSysTables() if (table->getTableId() == (Uint32) id1) { if (table->isSysTable) blobTable->isSysTable = true; + blobTable->m_main_table = table; break; } } @@ -428,6 +432,7 @@ TableS::TableS(Uint32 version, NdbTableImpl* tableImpl) m_noOfRecords= 0; backupVersion = version; isSysTable = false; + m_main_table = NULL; for (int i = 0; i < tableImpl->getNoOfColumns(); i++) createAttr(tableImpl->getColumn(i)); @@ -897,6 +902,7 @@ bool RestoreDataIterator::readFragmentHeader(int & ret, Uint32 *fragmentId) return false; } + info.setLevel(254); info << "_____________________________________________________" << endl << "Processing data in table: " << m_currentTable->getTableName() << "(" << Header.TableId << ") fragment " @@ -1154,14 +1160,14 @@ operator<<(NdbOut& ndbout, const AttributeS& attr){ if (data.null) { - ndbout << "<NULL>"; + ndbout << g_ndbrecord_print_format.null_string; return ndbout; } NdbRecAttr tmprec(0); - tmprec.setup(desc.m_column, (char *)data.void_value); + tmprec.setup(desc.m_column, 0); tmprec.receive_data((Uint32*)data.void_value, data.size); - ndbout << tmprec; + ndbrecattr_print_formatted(ndbout, tmprec, g_ndbrecord_print_format); return ndbout; } @@ -1170,17 +1176,15 @@ operator<<(NdbOut& ndbout, const AttributeS& attr){ NdbOut& operator<<(NdbOut& ndbout, const TupleS& tuple) { - ndbout << tuple.getTable()->getTableName() << "; "; for (int i = 0; i < tuple.getNoOfAttributes(); i++) { + if (i > 0) + ndbout << g_ndbrecord_print_format.fields_terminated_by; AttributeData * attr_data = tuple.getData(i); const AttributeDesc * attr_desc = tuple.getDesc(i); const AttributeS attr = {attr_desc, *attr_data}; debug << i << " " << attr_desc->m_column->getName(); ndbout << attr; - - if (i != (tuple.getNoOfAttributes() - 1)) - ndbout << delimiter << " "; } // for return ndbout; } diff --git a/storage/ndb/tools/restore/Restore.hpp b/storage/ndb/tools/restore/Restore.hpp index 74834fe0abc..406899b2b4d 100644 --- a/storage/ndb/tools/restore/Restore.hpp +++ b/storage/ndb/tools/restore/Restore.hpp @@ -25,8 +25,6 @@ #include <ndb_version.h> #include <version.h> -#define delimiter ";" - const int FileNameLenC = 256; const int TableNameLenC = 256; const int AttrNameLenC = 256; @@ -142,6 +140,8 @@ class TableS { Uint64 m_max_auto_val; bool isSysTable; + TableS *m_main_table; + Uint32 m_local_id; Uint64 m_noOfRecords; Vector<FragmentInfo *> m_fragmentInfo; @@ -156,6 +156,9 @@ public: Uint32 getTableId() const { return m_dictTable->getTableId(); } + Uint32 getLocalId() const { + return m_local_id; + } Uint32 getNoOfRecords() const { return m_noOfRecords; } @@ -239,6 +242,10 @@ public: return isSysTable; } + const TableS *getMainTable() const { + return m_main_table; + } + TableS& operator=(TableS& org) ; }; // TableS; diff --git a/storage/ndb/tools/restore/consumer_printer.cpp b/storage/ndb/tools/restore/consumer_printer.cpp index dabd77f7358..721e0332381 100644 --- a/storage/ndb/tools/restore/consumer_printer.cpp +++ b/storage/ndb/tools/restore/consumer_printer.cpp @@ -14,6 +14,9 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "consumer_printer.hpp" +extern FilteredNdbOut info; +extern NdbRecordPrintFormat g_ndbrecord_print_format; +extern const char *tab_path; bool BackupPrinter::table(const TableS & tab) @@ -21,7 +24,8 @@ BackupPrinter::table(const TableS & tab) if (m_print || m_print_meta) { m_ndbout << tab; - ndbout_c("Successfully printed table: %s", tab.m_dictTable->getName()); + info.setLevel(254); + info << "Successfully printed table: ", tab.m_dictTable->getName(); } return true; } @@ -31,7 +35,14 @@ BackupPrinter::tuple(const TupleS & tup, Uint32 fragId) { m_dataCount++; if (m_print || m_print_data) - m_ndbout << tup << endl; + { + if (m_ndbout.m_out == info.m_out) + { + info.setLevel(254); + info << tup.getTable()->getTableName() << "; "; + } + m_ndbout << tup << g_ndbrecord_print_format.lines_terminated_by; + } } void @@ -47,9 +58,10 @@ BackupPrinter::endOfLogEntrys() { if (m_print || m_print_log) { - ndbout << "Printed " << m_dataCount << " tuples and " - << m_logCount << " log entries" - << " to stdout." << endl; + info.setLevel(254); + info << "Printed " << m_dataCount << " tuples and " + << m_logCount << " log entries" + << " to stdout." << endl; } } bool diff --git a/storage/ndb/tools/restore/consumer_restore.cpp b/storage/ndb/tools/restore/consumer_restore.cpp index 2ea79a2aa6c..e8f9842e554 100644 --- a/storage/ndb/tools/restore/consumer_restore.cpp +++ b/storage/ndb/tools/restore/consumer_restore.cpp @@ -619,6 +619,7 @@ BackupRestore::update_apply_status(const RestoreMetaData &metaData) return true; bool result= false; + unsigned apply_table_format= 0; m_ndb->setDatabaseName(NDB_REP_DB); m_ndb->setSchemaName("def"); @@ -631,8 +632,33 @@ BackupRestore::update_apply_status(const RestoreMetaData &metaData) << dict->getNdbError() << endl; return false; } + if + (ndbtab->getColumn(0)->getType() == NdbDictionary::Column::Unsigned && + ndbtab->getColumn(1)->getType() == NdbDictionary::Column::Bigunsigned) + { + if (ndbtab->getNoOfColumns() == 2) + { + apply_table_format= 1; + } + else if + (ndbtab->getColumn(2)->getType() == NdbDictionary::Column::Varchar && + ndbtab->getColumn(3)->getType() == NdbDictionary::Column::Bigunsigned && + ndbtab->getColumn(4)->getType() == NdbDictionary::Column::Bigunsigned) + { + apply_table_format= 2; + } + } + if (apply_table_format == 0) + { + err << Ndb_apply_table << " has wrong format\n"; + return false; + } + Uint32 server_id= 0; Uint64 epoch= metaData.getStopGCP(); + Uint64 zero= 0; + char empty_string[1]; + empty_string[0]= 0; NdbTransaction * trans= m_ndb->startTransaction(); if (!trans) { @@ -655,6 +681,15 @@ BackupRestore::update_apply_status(const RestoreMetaData &metaData) << op->getNdbError() << endl; goto err; } + if ((apply_table_format == 2) && + (op->setValue(2u, (const char *)&empty_string, 1) || + op->setValue(3u, (const char *)&zero, sizeof(zero)) || + op->setValue(4u, (const char *)&zero, sizeof(zero)))) + { + err << Ndb_apply_table << ": " + << op->getNdbError() << endl; + goto err; + } if (trans->execute(NdbTransaction::Commit)) { err << Ndb_apply_table << ": " diff --git a/storage/ndb/tools/restore/restore_main.cpp b/storage/ndb/tools/restore/restore_main.cpp index ee3af467aa7..8353f049647 100644 --- a/storage/ndb/tools/restore/restore_main.cpp +++ b/storage/ndb/tools/restore/restore_main.cpp @@ -20,6 +20,7 @@ #include <NdbTCP.h> #include <NdbMem.h> #include <NdbOut.hpp> +#include <OutputStream.hpp> #include <NDBT_ReturnCodes.h> #include "consumer_restore.hpp" @@ -34,14 +35,24 @@ static int ga_nParallelism = 128; static int ga_backupId = 0; static bool ga_dont_ignore_systab_0 = false; static Vector<class BackupConsumer *> g_consumers; +static BackupPrinter* g_printer = NULL; -static const char* ga_backupPath = "." DIR_SEPARATOR; +static const char* default_backupPath = "." DIR_SEPARATOR; +static const char* ga_backupPath = default_backupPath; static const char *opt_nodegroup_map_str= 0; static unsigned opt_nodegroup_map_len= 0; static NODE_GROUP_MAP opt_nodegroup_map[MAX_NODE_GROUP_MAPS]; #define OPT_NDB_NODEGROUP_MAP 'z' +const char *opt_ndb_database= NULL; +const char *opt_ndb_table= NULL; +unsigned int opt_verbose; +unsigned int opt_hex_format; +Vector<BaseString> g_databases; +Vector<BaseString> g_tables; +NdbRecordPrintFormat g_ndbrecord_print_format; + NDB_STD_OPTS_VARS; /** @@ -62,6 +73,28 @@ BaseString g_options("ndb_restore"); const char *load_default_groups[]= { "mysql_cluster","ndb_restore",0 }; +enum ndb_restore_options { + OPT_PRINT= NDB_STD_OPTIONS_LAST, + OPT_PRINT_DATA, + OPT_PRINT_LOG, + OPT_PRINT_META, + OPT_BACKUP_PATH, + OPT_HEX_FORMAT, + OPT_FIELDS_ENCLOSED_BY, + OPT_FIELDS_TERMINATED_BY, + OPT_FIELDS_OPTIONALLY_ENCLOSED_BY, + OPT_LINES_TERMINATED_BY, + OPT_APPEND, + OPT_VERBOSE +}; +static const char *opt_fields_enclosed_by= NULL; +static const char *opt_fields_terminated_by= NULL; +static const char *opt_fields_optionally_enclosed_by= NULL; +static const char *opt_lines_terminated_by= NULL; + +static const char *tab_path= NULL; +static int opt_append; + static struct my_option my_long_options[] = { NDB_STD_OPTS("ndb_restore"), @@ -100,19 +133,19 @@ static struct my_option my_long_options[] = "(parallelism can be 1 to 1024)", (gptr*) &ga_nParallelism, (gptr*) &ga_nParallelism, 0, GET_INT, REQUIRED_ARG, 128, 1, 1024, 0, 1, 0 }, - { "print", 256, "Print data and log to stdout", + { "print", OPT_PRINT, "Print data and log to stdout", (gptr*) &_print, (gptr*) &_print, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, - { "print_data", 257, "Print data to stdout", + { "print_data", OPT_PRINT_DATA, "Print data to stdout", (gptr*) &_print_data, (gptr*) &_print_data, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, - { "print_meta", 258, "Print meta data to stdout", + { "print_meta", OPT_PRINT_META, "Print meta data to stdout", (gptr*) &_print_meta, (gptr*) &_print_meta, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, - { "print_log", 259, "Print log to stdout", + { "print_log", OPT_PRINT_LOG, "Print log to stdout", (gptr*) &_print_log, (gptr*) &_print_log, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, - { "backup_path", 260, "Path to backup files", + { "backup_path", OPT_BACKUP_PATH, "Path to backup files", (gptr*) &ga_backupPath, (gptr*) &ga_backupPath, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, { "dont_ignore_systab_0", 'f', @@ -125,6 +158,37 @@ static struct my_option my_long_options[] = (gptr*) &opt_nodegroup_map_str, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, + { "fields-enclosed-by", OPT_FIELDS_ENCLOSED_BY, + "Fields are enclosed by ...", + (gptr*) &opt_fields_enclosed_by, (gptr*) &opt_fields_enclosed_by, 0, + GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, + { "fields-terminated-by", OPT_FIELDS_TERMINATED_BY, + "Fields are terminated by ...", + (gptr*) &opt_fields_terminated_by, + (gptr*) &opt_fields_terminated_by, 0, + GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, + { "fields-optionally-enclosed-by", OPT_FIELDS_OPTIONALLY_ENCLOSED_BY, + "Fields are optionally enclosed by ...", + (gptr*) &opt_fields_optionally_enclosed_by, + (gptr*) &opt_fields_optionally_enclosed_by, 0, + GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, + { "hex", OPT_HEX_FORMAT, "print binary types in hex format", + (gptr*) &opt_hex_format, (gptr*) &opt_hex_format, 0, + GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, + { "tab", 'T', "Creates tab separated textfile for each table to " + "given path. (creates .txt files)", + (gptr*) &tab_path, (gptr*) &tab_path, 0, + GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + { "append", OPT_APPEND, "for --tab append data to file", + (gptr*) &opt_append, (gptr*) &opt_append, 0, + GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, + { "lines-terminated-by", OPT_LINES_TERMINATED_BY, "", + (gptr*) &opt_lines_terminated_by, (gptr*) &opt_lines_terminated_by, 0, + GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, + { "verbose", OPT_VERBOSE, + "verbosity", + (gptr*) &opt_verbose, (gptr*) &opt_verbose, 0, + GET_INT, REQUIRED_ARG, 1, 0, 255, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; @@ -259,20 +323,25 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), #endif ndb_std_get_one_option(optid, opt, argument); switch (optid) { + case OPT_VERBOSE: + info.setThreshold(255-opt_verbose); + break; case 'n': if (ga_nodeId == 0) { - printf("Error in --nodeid,-n setting, see --help\n"); + err << "Error in --nodeid,-n setting, see --help"; exit(NDBT_ProgramExit(NDBT_WRONGARGS)); } + info.setLevel(254); info << "Nodeid = " << ga_nodeId << endl; break; case 'b': if (ga_backupId == 0) { - printf("Error in --backupid,-b setting, see --help\n"); + err << "Error in --backupid,-b setting, see --help"; exit(NDBT_ProgramExit(NDBT_WRONGARGS)); } + info.setLevel(254); info << "Backup Id = " << ga_backupId << endl; break; case OPT_NDB_NODEGROUP_MAP: @@ -281,6 +350,8 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), to nodegroup in new cluster. */ opt_nodegroup_map_len= 0; + + info.setLevel(254); info << "Analyse node group map" << endl; if (analyse_nodegroup_map(opt_nodegroup_map_str, &opt_nodegroup_map[0])) @@ -335,9 +406,9 @@ o verify nodegroup mapping exit(NDBT_ProgramExit(NDBT_WRONGARGS)); #endif - BackupPrinter* printer = new BackupPrinter(opt_nodegroup_map, - opt_nodegroup_map_len); - if (printer == NULL) + g_printer = new BackupPrinter(opt_nodegroup_map, + opt_nodegroup_map_len); + if (g_printer == NULL) return false; BackupRestore* restore = new BackupRestore(opt_nodegroup_map, @@ -345,7 +416,8 @@ o verify nodegroup mapping ga_nParallelism); if (restore == NULL) { - delete printer; + delete g_printer; + g_printer = NULL; return false; } @@ -353,22 +425,22 @@ o verify nodegroup mapping { ga_print = true; ga_restore = true; - printer->m_print = true; + g_printer->m_print = true; } if (_print_meta) { ga_print = true; - printer->m_print_meta = true; + g_printer->m_print_meta = true; } if (_print_data) { ga_print = true; - printer->m_print_data = true; + g_printer->m_print_data = true; } if (_print_log) { ga_print = true; - printer->m_print_log = true; + g_printer->m_print_log = true; } if (_restore_data) @@ -394,19 +466,64 @@ o verify nodegroup mapping } { - BackupConsumer * c = printer; + BackupConsumer * c = g_printer; g_consumers.push_back(c); } { BackupConsumer * c = restore; g_consumers.push_back(c); } - // Set backup file path - if (*pargv[0] != NULL) + for (;;) { - ga_backupPath = *pargv[0]; + int i= 0; + if (ga_backupPath == default_backupPath) + { + // Set backup file path + if ((*pargv)[i] == NULL) + break; + ga_backupPath = (*pargv)[i++]; + } + if ((*pargv)[i] == NULL) + break; + g_databases.push_back((*pargv)[i++]); + while ((*pargv)[i] != NULL) + { + g_tables.push_back((*pargv)[i++]); + } + break; } + info.setLevel(254); info << "backup path = " << ga_backupPath << endl; + if (g_databases.size() > 0) + { + info << "Restoring only from database " << g_databases[0].c_str() << endl; + if (g_tables.size() > 0) + info << "Restoring only tables:"; + for (unsigned i= 0; i < g_tables.size(); i++) + { + info << " " << g_tables[i].c_str(); + } + if (g_tables.size() > 0) + info << endl; + } + /* + the below formatting follows the formatting from mysqldump + do not change unless to adopt to changes in mysqldump + */ + g_ndbrecord_print_format.fields_enclosed_by= + opt_fields_enclosed_by ? opt_fields_enclosed_by : ""; + g_ndbrecord_print_format.fields_terminated_by= + opt_fields_terminated_by ? opt_fields_terminated_by : "\t"; + g_ndbrecord_print_format.fields_optionally_enclosed_by= + opt_fields_optionally_enclosed_by ? opt_fields_optionally_enclosed_by : ""; + g_ndbrecord_print_format.lines_terminated_by= + opt_lines_terminated_by ? opt_lines_terminated_by : "\n"; + if (g_ndbrecord_print_format.fields_optionally_enclosed_by[0] == '\0') + g_ndbrecord_print_format.null_string= "\\N"; + else + g_ndbrecord_print_format.null_string= ""; + g_ndbrecord_print_format.hex_prefix= ""; + g_ndbrecord_print_format.hex_format= opt_hex_format; return true; } @@ -431,6 +548,70 @@ checkSysTable(const RestoreMetaData& metaData, uint i) return checkSysTable(metaData[i]); } +static inline bool +isBlobTable(const TableS* table) +{ + return table->getMainTable() != NULL; +} + +static inline bool +isIndex(const TableS* table) +{ + const NdbTableImpl & tmptab = NdbTableImpl::getImpl(* table->m_dictTable); + return (int) tmptab.m_indexType != (int) NdbDictionary::Index::Undefined; +} + +static inline bool +checkDbAndTableName(const TableS* table) +{ + if (g_tables.size() == 0 && + g_databases.size() == 0) + return true; + if (g_databases.size() == 0) + g_databases.push_back("TEST_DB"); + + // Filter on the main table name for indexes and blobs + const char *table_name; + if (isBlobTable(table)) + table_name= table->getMainTable()->getTableName(); + else if (isIndex(table)) + table_name= + NdbTableImpl::getImpl(*table->m_dictTable).m_primaryTable.c_str(); + else + table_name= table->getTableName(); + + unsigned i; + for (i= 0; i < g_databases.size(); i++) + { + if (strncmp(table_name, g_databases[i].c_str(), + g_databases[i].length()) == 0 && + table_name[g_databases[i].length()] == '/') + { + // we have a match + if (g_databases.size() > 1 || g_tables.size() == 0) + return true; + break; + } + } + if (i == g_databases.size()) + return false; // no match found + + while (*table_name != '/') table_name++; + table_name++; + while (*table_name != '/') table_name++; + table_name++; + + for (i= 0; i < g_tables.size(); i++) + { + if (strcmp(table_name, g_tables[i].c_str()) == 0) + { + // we have a match + return true; + } + } + return false; +} + static void free_data_callback() { @@ -490,9 +671,10 @@ main(int argc, char** argv) const Uint32 version = tmp.NdbVersion; char buf[NDB_VERSION_STRING_BUF_SZ]; + info.setLevel(254); info << "Ndb version in backup files: " - << getVersionString(version, 0, buf, sizeof(buf)) << endl; - + << getVersionString(version, 0, buf, sizeof(buf)) << endl; + /** * check wheater we can restore the backup (right version). */ @@ -560,27 +742,59 @@ main(int argc, char** argv) exitHandler(NDBT_FAILED); } } - debug << "Restoring tables" << endl; + + Vector<OutputStream *> table_output(metaData.getNoOfTables()); + debug << "Restoring tables" << endl; for(i = 0; i<metaData.getNoOfTables(); i++) { - if (checkSysTable(metaData, i)) + const TableS *table= metaData[i]; + table_output.push_back(NULL); + if (!checkDbAndTableName(table)) + continue; + if (checkSysTable(table)) { + if (!tab_path || isBlobTable(table) || isIndex(table)) + { + table_output[i]= ndbout.m_out; + } + else + { + FILE* res; + char filename[FN_REFLEN], tmp_path[FN_REFLEN]; + const char *table_name; + table_name= table->getTableName(); + while (*table_name != '/') table_name++; + table_name++; + while (*table_name != '/') table_name++; + table_name++; + convert_dirname(tmp_path, tab_path, NullS); + res= my_fopen(fn_format(filename, table_name, tmp_path, ".txt", 4), + opt_append ? + O_WRONLY|O_APPEND|O_CREAT : + O_WRONLY|O_TRUNC|O_CREAT, + MYF(MY_WME)); + if (res == 0) + { + exitHandler(NDBT_FAILED); + } + FileOutputStream *f= new FileOutputStream(res); + table_output[i]= f; + } for(Uint32 j= 0; j < g_consumers.size(); j++) - if (!g_consumers[j]->table(* metaData[i])) + if (!g_consumers[j]->table(* table)) { err << "Restore: Failed to restore table: "; - err << metaData[i]->getTableName() << " ... Exiting " << endl; + err << table->getTableName() << " ... Exiting " << endl; exitHandler(NDBT_FAILED); } } else { for(Uint32 j= 0; j < g_consumers.size(); j++) - if (!g_consumers[j]->createSystable(* metaData[i])) + if (!g_consumers[j]->createSystable(* table)) { err << "Restore: Failed to restore system table: "; - err << metaData[i]->getTableName() << " ... Exiting " << endl; + err << table->getTableName() << " ... Exiting " << endl; exitHandler(NDBT_FAILED); } - } } debug << "Close tables" << endl; @@ -624,9 +838,15 @@ main(int argc, char** argv) const TupleS* tuple; while ((tuple = dataIter.getNextTuple(res= 1)) != 0) { - if (checkSysTable(tuple->getTable())) - for(Uint32 j= 0; j < g_consumers.size(); j++) - g_consumers[j]->tuple(* tuple, fragmentId); + const TableS* table = tuple->getTable(); + OutputStream *output = table_output[table->getLocalId()]; + if (!output) + continue; + OutputStream *tmp = ndbout.m_out; + ndbout.m_out = output; + for(Uint32 j= 0; j < g_consumers.size(); j++) + g_consumers[j]->tuple(* tuple, fragmentId); + ndbout.m_out = tmp; } // while (tuple != NULL); if (res < 0) @@ -668,9 +888,12 @@ main(int argc, char** argv) const LogEntry * logEntry = 0; while ((logEntry = logIter.getNextLogEntry(res= 0)) != 0) { - if (checkSysTable(logEntry->m_table)) - for(Uint32 j= 0; j < g_consumers.size(); j++) - g_consumers[j]->logEntry(* logEntry); + const TableS* table = logEntry->m_table; + OutputStream *output = table_output[table->getLocalId()]; + if (!output) + continue; + for(Uint32 j= 0; j < g_consumers.size(); j++) + g_consumers[j]->logEntry(* logEntry); } if (res < 0) { @@ -687,27 +910,27 @@ main(int argc, char** argv) { for(i = 0; i<metaData.getNoOfTables(); i++) { - if (checkSysTable(metaData, i)) - { - for(Uint32 j= 0; j < g_consumers.size(); j++) - if (!g_consumers[j]->finalize_table(* metaData[i])) - { - err << "Restore: Failed to finalize restore table: %s. "; - err << "Exiting... " << metaData[i]->getTableName() << endl; - exitHandler(NDBT_FAILED); - } - } + const TableS* table = metaData[i]; + OutputStream *output = table_output[table->getLocalId()]; + if (!output) + continue; + for(Uint32 j= 0; j < g_consumers.size(); j++) + if (!g_consumers[j]->finalize_table(*table)) + { + err << "Restore: Failed to finalize restore table: %s. "; + err << "Exiting... " << metaData[i]->getTableName() << endl; + exitHandler(NDBT_FAILED); + } } } } - if (ga_restore_epoch) { for (i= 0; i < g_consumers.size(); i++) if (!g_consumers[i]->update_apply_status(metaData)) { - err << "Restore: Failed to restore epoch" << endl; - return -1; + err << "Restore: Failed to restore epoch" << endl; + return -1; } } @@ -722,7 +945,23 @@ main(int argc, char** argv) } clearConsumers(); - return NDBT_ProgramExit(NDBT_OK); + + for(i = 0; i < metaData.getNoOfTables(); i++) + { + if (table_output[i] && + table_output[i] != ndbout.m_out) + { + my_fclose(((FileOutputStream *)table_output[i])->getFile(), MYF(MY_WME)); + delete table_output[i]; + table_output[i] = NULL; + } + } + + if (opt_verbose) + return NDBT_ProgramExit(NDBT_OK); + else + return 0; } // main template class Vector<BackupConsumer*>; +template class Vector<OutputStream*>; |