From: magnus.blaudd Date: June 26 2012 2:29pm Subject: bzr push into mysql-5.5-cluster-7.3 branch (magnus.blaudd:3894 to 3895) List-Archive: http://lists.mysql.com/commits/144322 Message-Id: <20120626142941.2570.21144.3895@peek02.se.oracle.com> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit 3895 magnus.blaudd@stripped 2012-06-26 [merge] Merge 7.2 -> 7.3 added: mysql-test/suite/ndb/r/ndb_mgmd.result mysql-test/suite/ndb/t/ndb_mgmd.cnf mysql-test/suite/ndb/t/ndb_mgmd.test modified: storage/ndb/include/logger/FileLogHandler.hpp storage/ndb/include/logger/LogHandler.hpp storage/ndb/include/logger/Logger.hpp storage/ndb/src/common/logger/LogHandler.cpp storage/ndb/src/common/logger/Logger.cpp storage/ndb/src/mgmsrv/MgmtSrvr.cpp storage/ndb/src/mgmsrv/MgmtSrvr.hpp storage/ndb/src/ndbapi/NdbScanOperation.cpp storage/ndb/src/ndbapi/ndberror.c storage/ndb/test/ndbapi/testScan.cpp storage/ndb/test/run-test/daily-basic-tests.txt storage/ndb/tools/ndb_error_reporter 3894 magnus.blaudd@stripped 2012-06-25 [merge] Merge 7.2 -> 7.3 modified: mysql-test/suite/ndb/r/ndb_alter_table_online.result mysql-test/suite/ndb/r/ndb_index_stat_restart.result mysql-test/suite/ndb/r/ndb_reconnect.result mysql-test/suite/ndb/t/ndb_alter_table_online.test mysql-test/suite/ndb/t/ndb_reconnect.test mysql-test/suite/ndb_big/my.cnf sql/ha_ndbcluster.cc sql/ha_ndbcluster_binlog.cc sql/ndb_thd_ndb.h sql/sql_show.cc sql/sql_show.h sql/sql_table.cc storage/ndb/include/kernel/ndb_limits.h storage/ndb/include/kernel/signaldata/CreateTable.hpp storage/ndb/include/kernel/signaldata/DictTabInfo.hpp storage/ndb/include/kernel/signaldata/ScanTab.hpp storage/ndb/include/ndb_version.h.in storage/ndb/src/common/debugger/signaldata/DictTabInfo.cpp storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp storage/ndb/src/kernel/blocks/dbdih/Dbdih.hpp storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp storage/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp storage/ndb/src/kernel/blocks/ndbfs/AsyncIoThread.hpp storage/ndb/src/kernel/blocks/ndbfs/Ndbfs.cpp storage/ndb/src/kernel/blocks/suma/Suma.hpp storage/ndb/src/kernel/vm/SimulatedBlock.hpp storage/ndb/src/kernel/vm/mt.cpp storage/ndb/src/ndbapi/NdbDictionary.cpp storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp storage/ndb/src/ndbapi/NdbQueryOperation.cpp storage/ndb/src/ndbapi/NdbScanOperation.cpp storage/ndb/test/include/NdbBackup.hpp storage/ndb/test/include/NdbConfig.hpp storage/ndb/test/ndbapi/testBackup.cpp storage/ndb/test/ndbapi/testBasic.cpp storage/ndb/test/ndbapi/testSystemRestart.cpp storage/ndb/test/ndbapi/testTimeout.cpp storage/ndb/test/ndbapi/testUpgrade.cpp storage/ndb/test/run-test/daily-basic-tests.txt support-files/mysql.spec.sh === added file 'mysql-test/suite/ndb/r/ndb_mgmd.result' --- a/mysql-test/suite/ndb/r/ndb_mgmd.result 1970-01-01 00:00:00 +0000 +++ b/mysql-test/suite/ndb/r/ndb_mgmd.result 2012-06-26 13:03:52 +0000 @@ -0,0 +1,5 @@ +# +# BUG#11764570 NDB_ERROR_REPORTER ONLY COLLECTS LOGS MATCHING NAME NDB_*. +# +Make sure that ndb_mgmd creates ndb__cluster.log file +Make sure that ndb_mgmd does _not_ create logger.log file === added file 'mysql-test/suite/ndb/t/ndb_mgmd.cnf' --- a/mysql-test/suite/ndb/t/ndb_mgmd.cnf 1970-01-01 00:00:00 +0000 +++ b/mysql-test/suite/ndb/t/ndb_mgmd.cnf 2012-06-26 13:03:52 +0000 @@ -0,0 +1,5 @@ +!include ../my.cnf + +[cluster_config.ndb_mgmd.1.1] +LogDestination=FILE:maxsize=32000000,maxfiles=6 + === added file 'mysql-test/suite/ndb/t/ndb_mgmd.test' --- a/mysql-test/suite/ndb/t/ndb_mgmd.test 1970-01-01 00:00:00 +0000 +++ b/mysql-test/suite/ndb/t/ndb_mgmd.test 2012-06-26 13:03:52 +0000 @@ -0,0 +1,13 @@ +--source include/have_ndb.inc + +--echo # +--echo # BUG#11764570 NDB_ERROR_REPORTER ONLY COLLECTS LOGS MATCHING NAME NDB_$ID*. +--echo # + +--echo Make sure that ndb_mgmd creates ndb__cluster.log file +--file_exists $MYSQLTEST_VARDIR/mysql_cluster.1/ndb_mgmd.1/ndb_3_cluster.log + +--echo Make sure that ndb_mgmd does _not_ create logger.log file +--error 1 +--file_exists $MYSQLTEST_VARDIR/mysql_cluster.1/ndb_mgmd.1/logger.log + === modified file 'storage/ndb/include/logger/FileLogHandler.hpp' --- a/storage/ndb/include/logger/FileLogHandler.hpp 2011-06-30 15:59:25 +0000 +++ b/storage/ndb/include/logger/FileLogHandler.hpp 2012-06-26 13:03:52 +0000 @@ -49,7 +49,7 @@ public: * @param maxFileSize the maximum log file size before archiving. * @param maxLogEntries the maximum number of log entries before checking time to archive. */ - FileLogHandler(const char* aFileName = "logger.log", + FileLogHandler(const char* aFileName, int maxNoFiles = 6, long maxFileSize = 1024000, unsigned int maxLogEntries = 10000); === modified file 'storage/ndb/include/logger/LogHandler.hpp' --- a/storage/ndb/include/logger/LogHandler.hpp 2011-07-05 12:46:07 +0000 +++ b/storage/ndb/include/logger/LogHandler.hpp 2012-06-26 14:23:32 +0000 @@ -108,22 +108,7 @@ public: * @return the footer. */ const char* getDefaultFooter() const; - - /** - * Returns the date and time format used by ctime(). - * - * @return the date and time format. - */ - const char* getDateTimeFormat() const; - - /** - * Sets the date and time format. It needs to have the same arguments - * a ctime(). - * - * @param pFormat the date and time format. - */ - void setDateTimeFormat(const char* pFormat); - + /** * Returns the error code. */ @@ -233,7 +218,6 @@ private: LogHandler* operator = (const LogHandler&); bool operator == (const LogHandler&); - const char* m_pDateTimeFormat; int m_errorCode; char* m_errorStr; === modified file 'storage/ndb/include/logger/Logger.hpp' --- a/storage/ndb/include/logger/Logger.hpp 2011-02-01 23:27:25 +0000 +++ b/storage/ndb/include/logger/Logger.hpp 2012-06-26 13:03:52 +0000 @@ -153,11 +153,11 @@ public: bool createEventLogHandler(const char* source_name); /** - * Create a default handler that logs to a file called logger.log. + * Create a default handler which writes to the specified file name. * * @return true if successful. */ - bool createFileHandler(char* filename= 0); + bool createFileHandler(char* filename); /** * Remove the default file handler. @@ -185,16 +185,6 @@ public: bool addHandler(LogHandler* pHandler); /** - * Add a new handler - * - * @param logstring string describing the handler to add - * @param err OS errno in event of error - * @param len max length of errStr buffer - * @param errStr logger error string in event of error - */ - bool addHandler(const BaseString &logstring, int *err, int len, char* errStr); - - /** * Remove a log handler. * * @param pHandler log handler to remove. === modified file 'storage/ndb/src/common/logger/LogHandler.cpp' --- a/storage/ndb/src/common/logger/LogHandler.cpp 2011-10-21 12:36:44 +0000 +++ b/storage/ndb/src/common/logger/LogHandler.cpp 2012-06-26 14:23:32 +0000 @@ -24,7 +24,6 @@ // PUBLIC // LogHandler::LogHandler() : - m_pDateTimeFormat("%d-%.2d-%.2d %.2d:%.2d:%.2d"), m_errorCode(0), m_errorStr(NULL) { @@ -113,17 +112,6 @@ LogHandler::getDefaultFooter() const return "\n"; } -const char* -LogHandler::getDateTimeFormat() const -{ - return m_pDateTimeFormat; -} - -void -LogHandler::setDateTimeFormat(const char* pFormat) -{ - m_pDateTimeFormat = (char*)pFormat; -} char* LogHandler::getTimeAsString(char* pStr) const @@ -132,7 +120,7 @@ LogHandler::getTimeAsString(char* pStr) tm_now = ::localtime(&m_now); //uses the "current" timezone BaseString::snprintf(pStr, MAX_DATE_TIME_HEADER_LENGTH, - m_pDateTimeFormat, + "%d-%.2d-%.2d %.2d:%.2d:%.2d", tm_now->tm_year + 1900, tm_now->tm_mon + 1, //month is [0,11]. +1 -> [1,12] tm_now->tm_mday, === modified file 'storage/ndb/src/common/logger/Logger.cpp' --- a/storage/ndb/src/common/logger/Logger.cpp 2011-10-21 12:36:44 +0000 +++ b/storage/ndb/src/common/logger/Logger.cpp 2012-06-26 14:23:32 +0000 @@ -130,8 +130,7 @@ Logger::createFileHandler(char*filename) if (m_pFileHandler) return true; // Ok, already exist - LogHandler* log_handler = filename ? new FileLogHandler(filename) - : new FileLogHandler(); + LogHandler* log_handler = new FileLogHandler(filename); if (!log_handler) return false; @@ -210,64 +209,6 @@ Logger::addHandler(LogHandler* pHandler) return true; } -bool -Logger::addHandler(const BaseString &logstring, int *err, int len, char* errStr) { - Vector logdest; - DBUG_ENTER("Logger::addHandler"); - - logstring.split(logdest, ";"); - - for(unsigned i = 0; i < logdest.size(); i++) { - DBUG_PRINT("info",("adding: %s",logdest[i].c_str())); - - Vector v_type_args; - logdest[i].split(v_type_args, ":", 2); - - BaseString type(v_type_args[0]); - BaseString params; - if(v_type_args.size() >= 2) - params = v_type_args[1]; - - LogHandler *handler = NULL; - -#ifndef _WIN32 - if(type == "SYSLOG") - { - handler = new SysLogHandler(); - } else -#endif - if(type == "FILE") - handler = new FileLogHandler(); - else if(type == "CONSOLE") - handler = new ConsoleLogHandler(); - - if(handler == NULL) - { - BaseString::snprintf(errStr,len,"Could not create log destination: %s", - logdest[i].c_str()); - DBUG_RETURN(false); - } - - if(!handler->parseParams(params)) - { - *err= handler->getErrorCode(); - if(handler->getErrorStr()) - strncpy(errStr, handler->getErrorStr(), len); - delete handler; - DBUG_RETURN(false); - } - - if (!addHandler(handler)) - { - BaseString::snprintf(errStr,len,"Could not add log destination: %s", - logdest[i].c_str()); - delete handler; - DBUG_RETURN(false); - } - } - - DBUG_RETURN(true); -} bool Logger::removeHandler(LogHandler* pHandler) === modified file 'storage/ndb/src/mgmsrv/MgmtSrvr.cpp' --- a/storage/ndb/src/mgmsrv/MgmtSrvr.cpp 2012-03-19 12:09:39 +0000 +++ b/storage/ndb/src/mgmsrv/MgmtSrvr.cpp 2012-06-26 14:23:32 +0000 @@ -48,6 +48,9 @@ #include #include #include +#include +#include +#include #include #include @@ -579,6 +582,71 @@ MgmtSrvr::start() void +MgmtSrvr::configure_eventlogger(const BaseString& logdestination) const +{ + // Close old log handlers before creating the new + g_eventLogger->close(); + + Vector logdestinations; + logdestination.split(logdestinations, ";"); + + for(unsigned i = 0; i < logdestinations.size(); i++) + { + // Extract type(everything left of colon) + Vector v_type_params; + logdestinations[i].split(v_type_params, ":", 2); + BaseString type(v_type_params[0]); + + // Extract params(everything right of colon) + BaseString params; + if(v_type_params.size() >= 2) + params = v_type_params[1]; + + LogHandler *handler = NULL; + if(type == "FILE") + { + char *default_file_name= NdbConfig_ClusterLogFileName(_ownNodeId); + handler = new FileLogHandler(default_file_name); + free(default_file_name); + } + else if(type == "CONSOLE") + { + handler = new ConsoleLogHandler(); + } +#ifndef _WIN32 + else if(type == "SYSLOG") + { + handler = new SysLogHandler(); + } +#endif + if(handler == NULL) + { + ndbout_c("INTERNAL ERROR: Could not create log handler for: '%s'", + logdestinations[i].c_str()); + continue; + } + + if(!handler->parseParams(params)) + { + ndbout_c("Failed to parse parameters for log handler: '%s', error: %d '%s'", + logdestinations[i].c_str(), handler->getErrorCode(), handler->getErrorStr()); + delete handler; + continue; + } + + if (!g_eventLogger->addHandler(handler)) + { + ndbout_c("INTERNAL ERROR: Could not add %s log handler", handler->handler_type()); + g_eventLogger->error("INTERNAL ERROR: Could not add %s log handler", + handler->handler_type()); + delete handler; + continue; + } + } +} + + +void MgmtSrvr::setClusterLog(const Config* config) { DBUG_ASSERT(_ownNodeId); @@ -615,21 +683,7 @@ MgmtSrvr::setClusterLog(const Config* co logdest_configured = false; } - g_eventLogger->close(); - - int err= 0; - char errStr[100]= {0}; - if(!g_eventLogger->addHandler(logdest, &err, sizeof(errStr), errStr)) { - ndbout << "Warning: could not add log destination '" - << logdest.c_str() << "'. Reason: "; - if(err) - ndbout << strerror(err); - if(err && errStr[0]!='\0') - ndbout << ", "; - if(errStr[0]!='\0') - ndbout << errStr; - ndbout << endl; - } + configure_eventlogger(logdest); if (logdest_configured == false && m_opts.non_interactive) === modified file 'storage/ndb/src/mgmsrv/MgmtSrvr.hpp' --- a/storage/ndb/src/mgmsrv/MgmtSrvr.hpp 2011-09-14 13:49:19 +0000 +++ b/storage/ndb/src/mgmsrv/MgmtSrvr.hpp 2012-06-26 14:23:32 +0000 @@ -304,6 +304,7 @@ public: private: void config_changed(NodeId, const Config*); void setClusterLog(const Config* conf); + void configure_eventlogger(const BaseString& logdestination) const; public: /** === modified file 'storage/ndb/src/ndbapi/NdbScanOperation.cpp' --- a/storage/ndb/src/ndbapi/NdbScanOperation.cpp 2012-06-21 15:24:52 +0000 +++ b/storage/ndb/src/ndbapi/NdbScanOperation.cpp 2012-06-26 11:05:35 +0000 @@ -27,6 +27,8 @@ #define DEBUG_NEXT_RESULT 0 +static const int Err_scanAlreadyComplete = 4120; + NdbScanOperation::NdbScanOperation(Ndb* aNdb, NdbOperation::Type aType) : NdbOperation(aNdb, aType), m_transConnection(NULL) @@ -1888,6 +1890,15 @@ NdbScanOperation::nextResultNdbRecord(co if(theError.code) { + if (theError.code == Err_scanAlreadyComplete) + { + /** + * The scan is already complete. There must be a bug in the api + * application such that is calls nextResult()/nextResultNdbRecord() + * again after getting return value 1 (meaning end of scan). + */ + return -1; + } goto err4; } @@ -1933,8 +1944,9 @@ NdbScanOperation::nextResultNdbRecord(co { /** * No completed & no sent -> EndOfData + * Make sure user gets error if he tries again. */ - theError.code= -1; // make sure user gets error if he tries again + theError.code= Err_scanAlreadyComplete; return 1; } @@ -3684,7 +3696,7 @@ NdbIndexScanOperation::next_result_order } else { - theError.code= -1; + theError.code= Err_scanAlreadyComplete; return 1; // End-of-file } } === modified file 'storage/ndb/src/ndbapi/ndberror.c' --- a/storage/ndb/src/ndbapi/ndberror.c 2012-03-05 09:38:49 +0000 +++ b/storage/ndb/src/ndbapi/ndberror.c 2012-06-26 11:05:35 +0000 @@ -627,6 +627,7 @@ ErrorBundle ErrorCodes[] = { { 4116, DMEC, AE, "Operation was not defined correctly, probably missing a key" }, { 4117, DMEC, AE, "Could not start transporter, configuration error"}, { 4118, DMEC, AE, "Parameter error in API call" }, + { 4120, DMEC, AE, "Scan already complete" }, { 4300, DMEC, AE, "Tuple Key Type not correct" }, { 4301, DMEC, AE, "Fragment Type not correct" }, { 4302, DMEC, AE, "Minimum Load Factor not correct" }, === modified file 'storage/ndb/test/ndbapi/testScan.cpp' --- a/storage/ndb/test/ndbapi/testScan.cpp 2012-04-24 14:41:37 +0000 +++ b/storage/ndb/test/ndbapi/testScan.cpp 2012-06-26 12:33:15 +0000 @@ -24,6 +24,7 @@ #include "ScanFunctions.hpp" #include #include +#include const NdbDictionary::Table * getTable(Ndb* pNdb, int i){ @@ -1682,6 +1683,99 @@ runBug13394788(NDBT_Context* ctx, NDBT_S return NDBT_OK; } +/** + * This is a regression test for bug #11748194 "TRANSACTION OBJECT CREATED + * AND UNRELEASED BY EXTRA CALL TO NEXTRESULT()". + * If a transaction made an extra call to nextResult() after getting + * end-of-scan from nextResult(), the API would leak transaction objects. + */ +static int +runExtraNextResult(NDBT_Context* ctx, NDBT_Step* step) +{ + const NdbDictionary::Table * pTab = ctx->getTab(); + // Fill table with 10 rows. + HugoTransactions hugoTrans(*pTab); + Ndb* const ndb = GETNDB(step); + hugoTrans.loadTable(ndb, 10); + // Read MaxNoOfConcurrentTransactions configuration value. + Uint32 maxTrans = 0; + NdbConfig conf; + require(conf.getProperty(conf.getMasterNodeId(), + NODE_TYPE_DB, + CFG_DB_NO_TRANSACTIONS, + &maxTrans)); + require(maxTrans > 0); + + /** + * The bug causes each scan to leak one object. + */ + int result = NDBT_OK; + Uint32 i = 0; + while (i < maxTrans+1) + { + NdbTransaction* const trans = ndb->startTransaction(); + if (trans == NULL) + { + g_err << "ndb->startTransaction() gave unexpected error : " + << ndb->getNdbError() << " in the " << i << "th iteration." <getNdbScanOperation(pTab); + if (scan == NULL) + { + g_err << "trans->getNdbScanOperation() gave unexpected error : " + << trans->getNdbError() << " in the " << i + << "th iteration." <readTuples(NdbOperation::LM_CommittedRead) == 0); + require(scan->getValue(0u) != 0); + require(trans->execute(NoCommit) == 0); + + // Scan table until end. + int scanResult; + do + { + // Fetch new batch. + scanResult = scan->nextResult(true); + while (scanResult == 0) + { + // Iterate over batch. + scanResult = scan->nextResult(false); + } + } while (scanResult == 0 || scanResult == 2); + + /** + * Do extra nextResult. This is the application error that triggers the + * bug. + */ + scanResult = scan->nextResult(true); + require(scanResult < 0); + // Here we got the undefined error code -1. So check for that too. + // if (trans->getNdbError().code != 4120 + if (scan->getNdbError().code != 4120 + && result == NDBT_OK) + { + g_err << "scan->nextResult() gave unexpected error : " + << scan->getNdbError() << " in the " << i << "th iteration." + << endl; + result = NDBT_FAILED; + } + i++; + } + ndb->closeTransaction(trans); + } // while (i < maxTrans+1) + + // Delete table rows. + require(UtilTransactions(*ctx->getTab()).clearTable(ndb) == 0); + return result; +} + NDBT_TESTSUITE(testScan); TESTCASE("ScanRead", "Verify scan requirement: It should be possible "\ @@ -2247,6 +2341,11 @@ TESTCASE("Bug13394788", "") FINALIZER(createOrderedPkIndex_Drop); FINALIZER(runClearTable); } +TESTCASE("extraNextResultBug11748194", + "Regression test for bug #11748194") +{ + INITIALIZER(runExtraNextResult); +} NDBT_TESTSUITE_END(testScan); int main(int argc, const char** argv){ === modified file 'storage/ndb/test/run-test/daily-basic-tests.txt' --- a/storage/ndb/test/run-test/daily-basic-tests.txt 2012-06-25 11:35:54 +0000 +++ b/storage/ndb/test/run-test/daily-basic-tests.txt 2012-06-26 11:05:35 +0000 @@ -1871,3 +1871,7 @@ max-time: 300 cmd: testBasic args: -n LeakApiConnectObjects T1 +max-time: 300 +cmd: testScan +args: -n extraNextResultBug11748194 T1 + === modified file 'storage/ndb/tools/ndb_error_reporter' --- a/storage/ndb/tools/ndb_error_reporter 2011-07-05 12:46:07 +0000 +++ b/storage/ndb/tools/ndb_error_reporter 2012-06-26 14:23:32 +0000 @@ -81,6 +81,17 @@ foreach my $node (@nodes) system 'scp -p '.$recurse.$config_username.config($node,'host'). ':'.config($node,'datadir')."/ndb_".$node."* ". "$reportdir/\n"; + + # Extract cluster log name from LogDestination(if any) + foreach my $file_handler (grep(s/^FILE://i, split(/;/, config($node, 'LogDestination')))) + { + foreach my $file_name (grep(s/^filename=//i, split(/,/, $file_handler))) + { + print " Copying cluster log from '$file_name' on node $node...\n"; + system 'scp -p '.$config_username.config($node,'host'). + ':'.$file_name.". $reportdir/\n"; + } + } } print "\n\n Copying configuration file...\n\n\t$config_file\n\n"; No bundle (reason: useless for push emails).