summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--BUILD/SETUP.sh11
-rw-r--r--client/client_priv.h2
-rw-r--r--client/mysqldump.c61
-rw-r--r--client/mysqltest.c225
-rw-r--r--cmd-line-utils/libedit/np/vis.c71
-rw-r--r--configure.in13
-rw-r--r--include/m_ctype.h5
-rw-r--r--include/my_sys.h2
-rw-r--r--include/my_time.h14
-rw-r--r--include/mysql.h1
-rw-r--r--innobase/dict/dict0dict.c61
-rw-r--r--innobase/include/dict0dict.h12
-rw-r--r--innobase/include/os0file.h23
-rw-r--r--innobase/include/sync0arr.h4
-rw-r--r--innobase/include/ut0byte.h19
-rw-r--r--innobase/os/os0file.c82
-rw-r--r--innobase/row/row0ins.c35
-rw-r--r--innobase/row/row0sel.c26
-rw-r--r--innobase/srv/srv0srv.c28
-rw-r--r--innobase/srv/srv0start.c13
-rw-r--r--innobase/sync/sync0arr.c15
-rw-r--r--innobase/trx/trx0rec.c30
-rw-r--r--innobase/ut/ut0byte.c48
-rw-r--r--libmysql/libmysql.c74
-rw-r--r--libmysql/libmysql.def1
-rw-r--r--libmysql/manager.c2
-rw-r--r--myisam/myisam_ftdump.c2
-rw-r--r--myisam/myisamchk.c2
-rw-r--r--myisam/myisampack.c34
-rw-r--r--myisam/rt_test.c3
-rw-r--r--mysql-test/ndb/ndb_range_bounds.pl138
-rw-r--r--mysql-test/ndb/ndbcluster.sh2
-rw-r--r--mysql-test/r/ctype_sjis.result6
-rw-r--r--mysql-test/r/ctype_uca.result30
-rw-r--r--mysql-test/r/ctype_utf8.result9
-rw-r--r--mysql-test/r/func_test.result9
-rw-r--r--mysql-test/r/grant2.result27
-rw-r--r--mysql-test/r/innodb-lock.result34
-rw-r--r--mysql-test/r/mysqltest.result23
-rw-r--r--mysql-test/r/ndb_basic.result19
-rw-r--r--mysql-test/r/ndb_index_ordered.result18
-rw-r--r--mysql-test/r/ndb_lock.result35
-rw-r--r--mysql-test/r/ps.result35
-rw-r--r--mysql-test/r/ps_10nestset.result19
-rw-r--r--mysql-test/r/ps_1general.result2
-rw-r--r--mysql-test/r/rpl_commit_after_flush.result13
-rw-r--r--mysql-test/r/union.result78
-rw-r--r--mysql-test/t/ctype_sjis.test9
-rw-r--r--mysql-test/t/ctype_uca.test29
-rw-r--r--mysql-test/t/ctype_utf8.test9
-rw-r--r--mysql-test/t/func_test.test13
-rw-r--r--mysql-test/t/grant2.test44
-rw-r--r--mysql-test/t/innodb-lock-master.opt1
-rw-r--r--mysql-test/t/innodb-lock.test57
-rw-r--r--mysql-test/t/mysqltest.test78
-rw-r--r--mysql-test/t/ndb_basic.test13
-rw-r--r--mysql-test/t/ndb_index_ordered.test5
-rw-r--r--mysql-test/t/ndb_lock.test29
-rw-r--r--mysql-test/t/ps.test25
-rw-r--r--mysql-test/t/ps_10nestset.test35
-rw-r--r--mysql-test/t/ps_11bugs.test2
-rw-r--r--mysql-test/t/rpl_commit_after_flush.test17
-rw-r--r--mysql-test/t/union.test55
-rw-r--r--mysys/hash.c57
-rw-r--r--mysys/my_bitmap.c4
-rw-r--r--mysys/my_gethwaddr.c2
-rw-r--r--mysys/thr_lock.c12
-rw-r--r--ndb/examples/select_all/select_all.cpp2
-rw-r--r--ndb/include/kernel/BlockNumbers.h6
-rw-r--r--ndb/include/kernel/GlobalSignalNumbers.h198
-rw-r--r--ndb/include/kernel/LogLevel.hpp1
-rw-r--r--ndb/include/kernel/ndb_limits.h10
-rw-r--r--ndb/include/kernel/signaldata/ArbitSignalData.hpp12
-rw-r--r--ndb/include/kernel/signaldata/AttrInfo.hpp3
-rw-r--r--ndb/include/kernel/signaldata/DictTabInfo.hpp2
-rw-r--r--ndb/include/kernel/signaldata/DihContinueB.hpp3
-rw-r--r--ndb/include/kernel/signaldata/KeyInfo.hpp1
-rw-r--r--ndb/include/kernel/signaldata/NdbfsContinueB.hpp3
-rw-r--r--ndb/include/kernel/signaldata/ScanFrag.hpp6
-rw-r--r--ndb/include/kernel/signaldata/ScanTab.hpp24
-rw-r--r--ndb/include/kernel/signaldata/SignalData.hpp166
-rw-r--r--ndb/include/kernel/signaldata/TcContinueB.hpp4
-rw-r--r--ndb/include/kernel/signaldata/TcKeyConf.hpp3
-rw-r--r--ndb/include/kernel/signaldata/TuxBound.hpp1
-rw-r--r--ndb/include/kernel/signaldata/UpgradeStartup.hpp2
-rw-r--r--ndb/include/kernel/trigger_definitions.h12
-rw-r--r--ndb/include/mgmapi/mgmapi.h158
-rw-r--r--ndb/include/mgmcommon/LocalConfig.hpp4
-rw-r--r--ndb/include/ndb_global.h3
-rw-r--r--ndb/include/ndb_types.h2
-rw-r--r--ndb/include/ndbapi/Ndb.hpp5
-rw-r--r--ndb/include/ndbapi/NdbConnection.hpp20
-rw-r--r--ndb/include/ndbapi/NdbIndexScanOperation.hpp53
-rw-r--r--ndb/include/ndbapi/NdbOperation.hpp15
-rw-r--r--ndb/include/ndbapi/NdbReceiver.hpp7
-rw-r--r--ndb/include/ndbapi/NdbResultSet.hpp12
-rw-r--r--ndb/include/ndbapi/NdbScanOperation.hpp5
-rw-r--r--ndb/include/portlib/NdbCondition.h62
-rw-r--r--ndb/include/portlib/PortDefs.h40
-rw-r--r--ndb/include/portlib/prefetch.h4
-rw-r--r--ndb/include/util/BaseString.hpp6
-rw-r--r--ndb/include/util/basestring_vsnprintf.h29
-rw-r--r--ndb/src/common/debugger/DebuggerNames.cpp13
-rw-r--r--ndb/src/common/debugger/EventLogger.cpp217
-rw-r--r--ndb/src/common/debugger/signaldata/ContinueB.cpp4
-rw-r--r--ndb/src/common/debugger/signaldata/CopyGCI.cpp12
-rw-r--r--ndb/src/common/debugger/signaldata/CreateTrig.cpp28
-rw-r--r--ndb/src/common/debugger/signaldata/DihContinueB.cpp5
-rw-r--r--ndb/src/common/debugger/signaldata/Makefile.am3
-rw-r--r--ndb/src/common/debugger/signaldata/MasterLCP.cpp8
-rw-r--r--ndb/src/common/debugger/signaldata/NdbfsContinueB.cpp5
-rw-r--r--ndb/src/common/debugger/signaldata/ScanFrag.cpp42
-rw-r--r--ndb/src/common/debugger/signaldata/ScanTab.cpp11
-rw-r--r--ndb/src/common/debugger/signaldata/SignalDataPrint.cpp10
-rw-r--r--ndb/src/common/debugger/signaldata/SignalNames.cpp2
-rw-r--r--ndb/src/common/debugger/signaldata/TcKeyConf.cpp42
-rw-r--r--ndb/src/common/logger/FileLogHandler.cpp4
-rw-r--r--ndb/src/common/logger/LogHandler.cpp4
-rw-r--r--ndb/src/common/logger/Logger.cpp2
-rw-r--r--ndb/src/common/logger/listtest/LogHandlerListUnitTest.cpp4
-rw-r--r--ndb/src/common/logger/loggertest/LoggerUnitTest.cpp2
-rw-r--r--ndb/src/common/mgmcommon/ConfigRetriever.cpp16
-rw-r--r--ndb/src/common/mgmcommon/LocalConfig.cpp49
-rw-r--r--ndb/src/common/portlib/NdbDaemon.c2
-rw-r--r--ndb/src/common/portlib/NdbMem.c1
-rw-r--r--ndb/src/common/portlib/NdbSleep.c2
-rw-r--r--ndb/src/common/portlib/NdbThread.c6
-rw-r--r--ndb/src/common/portlib/memtest.c8
-rw-r--r--ndb/src/common/transporter/OSE_Receiver.cpp2
-rw-r--r--ndb/src/common/transporter/OSE_Transporter.cpp4
-rw-r--r--ndb/src/common/transporter/TCP_Transporter.cpp2
-rw-r--r--ndb/src/common/transporter/Transporter.cpp2
-rw-r--r--ndb/src/common/transporter/perftest/perfTransporterTest.cpp4
-rw-r--r--ndb/src/common/transporter/priotest/prioTransporterTest.cpp4
-rw-r--r--ndb/src/common/util/BaseString.cpp25
-rw-r--r--ndb/src/common/util/ConfigValues.cpp7
-rw-r--r--ndb/src/common/util/File.cpp4
-rw-r--r--ndb/src/common/util/Makefile.am2
-rw-r--r--ndb/src/common/util/NdbErrHnd.cpp38
-rw-r--r--ndb/src/common/util/NdbOut.cpp6
-rw-r--r--ndb/src/common/util/OutputStream.cpp4
-rw-r--r--ndb/src/common/util/Properties.cpp26
-rw-r--r--ndb/src/common/util/SimpleProperties.cpp2
-rw-r--r--ndb/src/common/util/basestring_vsnprintf.c37
-rw-r--r--ndb/src/common/util/socket_io.cpp8
-rw-r--r--ndb/src/cw/cpcd/APIService.cpp4
-rw-r--r--ndb/src/cw/cpcd/CPCD.cpp8
-rw-r--r--ndb/src/cw/cpcd/Process.cpp8
-rw-r--r--ndb/src/kernel/blocks/ERROR_codes.txt4
-rw-r--r--ndb/src/kernel/blocks/backup/Backup.cpp6
-rw-r--r--ndb/src/kernel/blocks/backup/restore/Restore.cpp17
-rw-r--r--ndb/src/kernel/blocks/backup/restore/Restore.hpp2
-rw-r--r--ndb/src/kernel/blocks/backup/restore/consumer_restore.cpp2
-rw-r--r--ndb/src/kernel/blocks/dbacc/Dbacc.hpp8
-rw-r--r--ndb/src/kernel/blocks/dbacc/DbaccMain.cpp28
-rw-r--r--ndb/src/kernel/blocks/dbdih/DbdihMain.cpp36
-rw-r--r--ndb/src/kernel/blocks/dblqh/Dblqh.hpp7
-rw-r--r--ndb/src/kernel/blocks/dblqh/DblqhMain.cpp122
-rw-r--r--ndb/src/kernel/blocks/dbtc/Dbtc.hpp22
-rw-r--r--ndb/src/kernel/blocks/dbtc/DbtcMain.cpp346
-rw-r--r--ndb/src/kernel/blocks/dbtup/Dbtup.hpp16
-rw-r--r--ndb/src/kernel/blocks/dbtup/DbtupDebug.cpp6
-rw-r--r--ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp60
-rw-r--r--ndb/src/kernel/blocks/dbtup/DbtupIndex.cpp9
-rw-r--r--ndb/src/kernel/blocks/dbtup/DbtupLCP.cpp3
-rw-r--r--ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp24
-rw-r--r--ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp54
-rw-r--r--ndb/src/kernel/blocks/dbtux/Dbtux.hpp203
-rw-r--r--ndb/src/kernel/blocks/dbtux/DbtuxCmp.cpp66
-rw-r--r--ndb/src/kernel/blocks/dbtux/DbtuxDebug.cpp66
-rw-r--r--ndb/src/kernel/blocks/dbtux/DbtuxGen.cpp4
-rw-r--r--ndb/src/kernel/blocks/dbtux/DbtuxMaint.cpp18
-rw-r--r--ndb/src/kernel/blocks/dbtux/DbtuxMeta.cpp18
-rw-r--r--ndb/src/kernel/blocks/dbtux/DbtuxNode.cpp430
-rw-r--r--ndb/src/kernel/blocks/dbtux/DbtuxScan.cpp210
-rw-r--r--ndb/src/kernel/blocks/dbtux/DbtuxSearch.cpp82
-rw-r--r--ndb/src/kernel/blocks/dbtux/DbtuxTree.cpp404
-rw-r--r--ndb/src/kernel/blocks/dbtux/Times.txt42
-rw-r--r--ndb/src/kernel/blocks/dbutil/DbUtil.cpp1
-rw-r--r--ndb/src/kernel/blocks/ndbcntr/NdbcntrInit.cpp6
-rw-r--r--ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp12
-rw-r--r--ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp4
-rw-r--r--ndb/src/kernel/blocks/ndbfs/Filename.cpp22
-rw-r--r--ndb/src/kernel/blocks/qmgr/QmgrMain.cpp19
-rw-r--r--ndb/src/kernel/blocks/suma/Suma.cpp5
-rw-r--r--ndb/src/kernel/error/ErrorReporter.cpp10
-rw-r--r--ndb/src/kernel/main.cpp2
-rw-r--r--ndb/src/kernel/vm/ClusterConfiguration.cpp8
-rw-r--r--ndb/src/kernel/vm/Configuration.cpp14
-rw-r--r--ndb/src/kernel/vm/SignalCounter.hpp2
-rw-r--r--ndb/src/kernel/vm/SimulatedBlock.cpp24
-rw-r--r--ndb/src/kernel/vm/SimulatedBlock.hpp4
-rw-r--r--ndb/src/mgmapi/mgmapi.cpp42
-rw-r--r--ndb/src/mgmclient/CommandInterpreter.cpp103
-rw-r--r--ndb/src/mgmclient/main.cpp2
-rw-r--r--ndb/src/mgmsrv/CommandInterpreter.cpp1
-rw-r--r--ndb/src/mgmsrv/Config.cpp3
-rw-r--r--ndb/src/mgmsrv/ConfigInfo.cpp28
-rw-r--r--ndb/src/mgmsrv/InitConfigFileParser.cpp24
-rw-r--r--ndb/src/mgmsrv/MgmtSrvr.cpp4
-rw-r--r--ndb/src/mgmsrv/Services.cpp17
-rw-r--r--ndb/src/mgmsrv/SignalQueue.cpp3
-rw-r--r--ndb/src/mgmsrv/main.cpp5
-rw-r--r--ndb/src/ndbapi/Ndb.cpp11
-rw-r--r--ndb/src/ndbapi/NdbApiSignal.cpp2
-rw-r--r--ndb/src/ndbapi/NdbBlob.cpp6
-rw-r--r--ndb/src/ndbapi/NdbConnection.cpp140
-rw-r--r--ndb/src/ndbapi/NdbDictionaryImpl.cpp9
-rw-r--r--ndb/src/ndbapi/NdbIndexOperation.cpp41
-rw-r--r--ndb/src/ndbapi/NdbOperation.cpp10
-rw-r--r--ndb/src/ndbapi/NdbOperationDefine.cpp28
-rw-r--r--ndb/src/ndbapi/NdbOperationExec.cpp57
-rw-r--r--ndb/src/ndbapi/NdbOperationInt.cpp4
-rw-r--r--ndb/src/ndbapi/NdbOperationSearch.cpp3
-rw-r--r--ndb/src/ndbapi/NdbReceiver.cpp14
-rw-r--r--ndb/src/ndbapi/NdbScanOperation.cpp377
-rw-r--r--ndb/src/ndbapi/Ndbif.cpp14
-rw-r--r--ndb/src/ndbapi/Ndbinit.cpp11
-rw-r--r--ndb/src/ndbapi/Ndblist.cpp14
-rw-r--r--ndb/src/ndbapi/ndberror.c19
-rw-r--r--ndb/test/include/HugoOperations.hpp12
-rw-r--r--ndb/test/include/HugoTransactions.hpp4
-rw-r--r--ndb/test/include/NDBT_ResultRow.hpp5
-rw-r--r--ndb/test/include/NDBT_Test.hpp8
-rw-r--r--ndb/test/include/UtilTransactions.hpp19
-rw-r--r--ndb/test/ndbapi/asyncGenerator.cpp2
-rw-r--r--ndb/test/ndbapi/bulk_copy.cpp2
-rw-r--r--ndb/test/ndbapi/cdrserver.cpp34
-rw-r--r--ndb/test/ndbapi/flexAsynch.cpp6
-rw-r--r--ndb/test/ndbapi/flexBench.cpp8
-rw-r--r--ndb/test/ndbapi/flexHammer.cpp6
-rw-r--r--ndb/test/ndbapi/flexScan.cpp6
-rw-r--r--ndb/test/ndbapi/flexTT.cpp12
-rw-r--r--ndb/test/ndbapi/flex_bench_mysql.cpp14
-rw-r--r--ndb/test/ndbapi/interpreterInTup.cpp4
-rw-r--r--ndb/test/ndbapi/testBasic.cpp138
-rw-r--r--ndb/test/ndbapi/testBlobs.cpp2
-rw-r--r--ndb/test/ndbapi/testDataBuffers.cpp4
-rw-r--r--ndb/test/ndbapi/testDict.cpp8
-rw-r--r--ndb/test/ndbapi/testIndex.cpp56
-rw-r--r--ndb/test/ndbapi/testNdbApi.cpp2
-rw-r--r--ndb/test/ndbapi/testNodeRestart.cpp179
-rw-r--r--ndb/test/ndbapi/testOIBasic.cpp248
-rw-r--r--ndb/test/ndbapi/testOperations.cpp10
-rw-r--r--ndb/test/ndbapi/testReadPerf.cpp6
-rw-r--r--ndb/test/ndbapi/testRestartGci.cpp4
-rw-r--r--ndb/test/ndbapi/testScanInterpreter.cpp2
-rw-r--r--ndb/test/ndbapi/testScanPerf.cpp4
-rw-r--r--ndb/test/ndbapi/testTimeout.cpp22
-rw-r--r--ndb/test/ndbapi/testTransactions.cpp8
-rw-r--r--ndb/test/ndbapi/userInterface.cpp2
-rw-r--r--ndb/test/run-test/daily-devel-tests.txt24
-rw-r--r--ndb/test/src/HugoCalculator.cpp2
-rw-r--r--ndb/test/src/HugoOperations.cpp102
-rw-r--r--ndb/test/src/HugoTransactions.cpp19
-rw-r--r--ndb/test/src/NDBT_ResultRow.cpp6
-rw-r--r--ndb/test/src/NDBT_Table.cpp6
-rw-r--r--ndb/test/src/NDBT_Test.cpp20
-rw-r--r--ndb/test/src/NdbBackup.cpp4
-rw-r--r--ndb/test/src/NdbGrep.cpp4
-rw-r--r--ndb/test/src/UtilTransactions.cpp287
-rw-r--r--ndb/test/tools/transproxy.cpp4
-rw-r--r--ndb/tools/listTables.cpp4
-rw-r--r--ndb/tools/waiter.cpp8
-rw-r--r--regex/regcomp.c2
-rw-r--r--regex/regcomp.ih2
-rw-r--r--scripts/Makefile.am1
-rw-r--r--scripts/make_binary_distribution.sh4
-rw-r--r--scripts/mysqlhotcopy.sh8
-rw-r--r--sql-common/client.c2
-rw-r--r--sql-common/my_time.c72
-rw-r--r--sql/examples/ha_archive.cc5
-rw-r--r--sql/examples/ha_example.cc4
-rw-r--r--sql/examples/ha_tina.cc8
-rw-r--r--sql/field.cc33
-rw-r--r--sql/ha_innodb.cc122
-rw-r--r--sql/ha_myisam.cc18
-rw-r--r--sql/ha_ndbcluster.cc585
-rw-r--r--sql/ha_ndbcluster.h9
-rw-r--r--sql/handler.cc38
-rw-r--r--sql/item.cc141
-rw-r--r--sql/item.h16
-rw-r--r--sql/item_cmpfunc.cc4
-rw-r--r--sql/item_cmpfunc.h2
-rw-r--r--sql/item_func.cc13
-rw-r--r--sql/item_strfunc.cc39
-rw-r--r--sql/item_timefunc.cc11
-rw-r--r--sql/lock.cc10
-rw-r--r--sql/log_event.h2
-rw-r--r--sql/mysql_priv.h13
-rw-r--r--sql/mysqld.cc12
-rw-r--r--sql/opt_range.cc2
-rw-r--r--sql/protocol.cc7
-rw-r--r--sql/set_var.cc4
-rw-r--r--sql/sql_acl.cc47
-rw-r--r--sql/sql_base.cc19
-rw-r--r--sql/sql_class.h50
-rw-r--r--sql/sql_help.cc2
-rw-r--r--sql/sql_lex.cc12
-rw-r--r--sql/sql_parse.cc24
-rw-r--r--sql/sql_prepare.cc25
-rw-r--r--sql/sql_select.cc32
-rw-r--r--sql/sql_show.cc49
-rw-r--r--sql/sql_string.cc3
-rw-r--r--sql/sql_table.cc2
-rw-r--r--sql/sql_union.cc40
-rw-r--r--sql/sql_yacc.yy16
-rw-r--r--sql/table.h1
-rw-r--r--sql/time.cc59
-rw-r--r--strings/CHARSET_INFO.txt230
-rw-r--r--strings/Makefile.am2
-rw-r--r--strings/ctype-mb.c89
-rw-r--r--strings/ctype-sjis.c36
-rw-r--r--strings/ctype-uca.c55
-rw-r--r--strings/ctype-ucs2.c166
-rw-r--r--strings/ctype-utf8.c289
-rw-r--r--strings/xml.c7
-rw-r--r--tests/client_test.c181
318 files changed, 7213 insertions, 3674 deletions
diff --git a/BUILD/SETUP.sh b/BUILD/SETUP.sh
index aa6b412d73b..f8baf317e72 100644
--- a/BUILD/SETUP.sh
+++ b/BUILD/SETUP.sh
@@ -6,6 +6,7 @@ fi
just_print=
just_configure=
+full_debug=
while test $# -gt 0
do
case "$1" in
@@ -21,6 +22,7 @@ Any other options will be passed directly to configure.
Note: this script is intended for internal use by MySQL developers.
EOF
+ --with-debug=full ) full_debug="=full"; shift ;;
* ) break ;;
esac
done
@@ -48,7 +50,8 @@ fast_cflags="-O3 -fno-omit-frame-pointer"
# this is one is for someone who thinks 1% speedup is worth not being
# able to backtrace
reckless_cflags="-O3 -fomit-frame-pointer "
-debug_cflags="-DUNIV_MUST_NOT_INLINE -DEXTRA_DEBUG -DFORCE_INIT_OF_VARS -DSAFEMALLOC -DPEDANTIC_SAFEMALLOC -DSAFE_MUTEX -O1 -Wuninitialized"
+
+debug_cflags="-DUNIV_MUST_NOT_INLINE -DEXTRA_DEBUG -DFORCE_INIT_OF_VARS -DSAFEMALLOC -DPEDANTIC_SAFEMALLOC -DSAFE_MUTEX"
base_cxxflags="-felide-constructors -fno-exceptions -fno-rtti"
@@ -62,7 +65,11 @@ sparc_configs=""
# and unset local_infile_configs
local_infile_configs="--enable-local-infile"
-debug_configs="--with-debug"
+debug_configs="--with-debug$full_debug"
+if [ -z "$full_debug" ]
+then
+ debug_cflags="$debug_cflags -O1 -Wuninitialized"
+fi
if gmake --version > /dev/null 2>&1
then
diff --git a/client/client_priv.h b/client/client_priv.h
index 328c051905c..f16ec0e802b 100644
--- a/client/client_priv.h
+++ b/client/client_priv.h
@@ -45,5 +45,5 @@ enum options_client
OPT_COMPATIBLE, OPT_RECONNECT, OPT_DELIMITER, OPT_SECURE_AUTH,
OPT_OPEN_FILES_LIMIT, OPT_SET_CHARSET, OPT_CREATE_OPTIONS,
OPT_START_POSITION, OPT_STOP_POSITION, OPT_START_DATETIME, OPT_STOP_DATETIME,
- OPT_SIGINT_IGNORE
+ OPT_SIGINT_IGNORE, OPT_HEXBLOB
};
diff --git a/client/mysqldump.c b/client/mysqldump.c
index 56505afd235..1686278096b 100644
--- a/client/mysqldump.c
+++ b/client/mysqldump.c
@@ -81,7 +81,8 @@ static my_bool verbose=0,tFlag=0,cFlag=0,dFlag=0,quick= 1, extended_insert= 1,
opt_alldbs=0,opt_create_db=0,opt_first_slave=0,opt_set_charset,
opt_autocommit=0,opt_master_data,opt_disable_keys=1,opt_xml=0,
opt_delete_master_logs=0, tty_password=0,
- opt_single_transaction=0, opt_comments= 0, opt_compact= 0;
+ opt_single_transaction=0, opt_comments= 0, opt_compact= 0,
+ opt_hex_blob=0;
static ulong opt_max_allowed_packet, opt_net_buffer_length;
static MYSQL mysql_connection,*sock=0;
static char insert_pat[12 * 1024],*opt_password=0,*current_user=0,
@@ -316,6 +317,8 @@ static struct my_option my_long_options[] =
{"comments", 'i', "Write additional information.",
(gptr*) &opt_comments, (gptr*) &opt_comments, 0, GET_BOOL, NO_ARG,
1, 0, 0, 0, 0, 0},
+ {"hex-blob", OPT_HEXBLOB, "Dump BLOBs in HEX. this mode does not work with extended-insert",
+ (gptr*) &opt_hex_blob, (gptr*) &opt_hex_blob, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
};
@@ -1507,6 +1510,7 @@ static void dumpTable(uint numFields, char *table)
for (i = 0; i < mysql_num_fields(res); i++)
{
+ int is_blob;
if (!(field = mysql_fetch_field(res)))
{
sprintf(query,"%s: Not enough fields from table %s! Aborting.\n",
@@ -1515,6 +1519,17 @@ static void dumpTable(uint numFields, char *table)
error= EX_CONSCHECK;
goto err;
}
+
+ /*
+ 63 is my_charset_bin. If charsetnr is not 63,
+ we have not a BLOB but a TEXT column.
+ we'll dump it in hex only BLOB columns.
+ */
+ is_blob= (opt_hex_blob && field->charsetnr == 63 &&
+ (field->type == FIELD_TYPE_BLOB ||
+ field->type == FIELD_TYPE_LONG_BLOB ||
+ field->type == FIELD_TYPE_MEDIUM_BLOB ||
+ field->type == FIELD_TYPE_TINY_BLOB)) ? 1 : 0;
if (extended_insert)
{
ulong length = lengths[i];
@@ -1535,12 +1550,28 @@ static void dumpTable(uint numFields, char *table)
error= EX_EOM;
goto err;
}
- dynstr_append(&extended_row,"'");
- extended_row.length +=
- mysql_real_escape_string(&mysql_connection,
- &extended_row.str[extended_row.length],row[i],length);
- extended_row.str[extended_row.length]='\0';
- dynstr_append(&extended_row,"'");
+ if (opt_hex_blob && is_blob)
+ {
+ ulong counter;
+ unsigned char *ptr= row[i];
+ dynstr_append(&extended_row, "0x");
+ for (counter = 0; counter < lengths[i]; counter++)
+ {
+ char xx[3];
+ sprintf(xx, "%02X", ptr[counter]);
+ dynstr_append(&extended_row, xx);
+ }
+ }
+ else
+ {
+ dynstr_append(&extended_row,"'");
+ extended_row.length +=
+ mysql_real_escape_string(&mysql_connection,
+ &extended_row.str[extended_row.length],
+ row[i],length);
+ extended_row.str[extended_row.length]='\0';
+ dynstr_append(&extended_row,"'");
+ }
}
else
{
@@ -1591,8 +1622,20 @@ static void dumpTable(uint numFields, char *table)
print_quoted_xml(md_result_file, row[i], lengths[i]);
fputs("</field>\n", md_result_file);
}
- else
- unescape(md_result_file, row[i], lengths[i]);
+ else if (opt_hex_blob && is_blob)
+ { /* sakaik got this idea. */
+ ulong counter;
+ char xx[4];
+ unsigned char *ptr= row[i];
+ fputs("0x", md_result_file);
+ for (counter = 0; counter < lengths[i]; counter++)
+ {
+ sprintf(xx, "%02X", ptr[counter]);
+ fputs(xx, md_result_file);
+ }
+ }
+ else
+ unescape(md_result_file, row[i], lengths[i]);
}
else
{
diff --git a/client/mysqltest.c b/client/mysqltest.c
index d2d110c7954..7a42cd54ca6 100644
--- a/client/mysqltest.c
+++ b/client/mysqltest.c
@@ -58,13 +58,6 @@
#include <stdarg.h>
#include <sys/stat.h>
#include <violite.h>
-#ifdef HAVE_SYS_PARAM_H
-#include <sys/param.h>
-#endif
-
-#ifndef MAXPATHLEN
-#define MAXPATHLEN 256
-#endif
#define MAX_QUERY 131072
#define MAX_VAR_NAME 256
@@ -102,6 +95,38 @@ enum {OPT_MANAGER_USER=256,OPT_MANAGER_HOST,OPT_MANAGER_PASSWD,
OPT_SSL_SSL, OPT_SSL_KEY, OPT_SSL_CERT, OPT_SSL_CA, OPT_SSL_CAPATH,
OPT_SSL_CIPHER};
+/* ************************************************************************ */
+/*
+ A line that starts with !$ or $S, and the list of error codes to
+ --error are stored in an internal array of structs. This struct can
+ hold numeric SQL error codes or SQLSTATE codes as strings. The
+ element next to the last active element in the list is set to type
+ ERR_EMPTY. When an SQL statement return an error we use this list to
+ check if this is an expected error.
+*/
+
+enum match_err_type
+{
+ ERR_EMPTY= 0,
+ ERR_ERRNO,
+ ERR_SQLSTATE
+};
+
+typedef struct
+{
+ enum match_err_type type;
+ union
+ {
+ uint errnum;
+ char sqlstate[SQLSTATE_LENGTH+1]; /* \0 terminated string */
+ } code;
+} match_err;
+
+static match_err global_expected_errno[MAX_EXPECTED_ERRORS];
+static uint global_expected_errors;
+
+/* ************************************************************************ */
+
static int record = 0, opt_sleep=0;
static char *db = 0, *pass=0;
const char* user = 0, *host = 0, *unix_sock = 0, *opt_basedir="./";
@@ -131,8 +156,8 @@ static int *cur_block, *block_stack_end;
static int block_stack[BLOCK_STACK_DEPTH];
static int block_ok_stack[BLOCK_STACK_DEPTH];
-static uint global_expected_errno[MAX_EXPECTED_ERRORS], global_expected_errors;
-static CHARSET_INFO *charset_info= &my_charset_latin1;
+static CHARSET_INFO *charset_info= &my_charset_latin1; /* Default charset */
+static char *charset_name = "latin1"; /* Default character set name */
static int embedded_server_arg_count=0;
static char *embedded_server_args[MAX_SERVER_ARGS];
@@ -245,6 +270,7 @@ Q_EXEC, Q_DELIMITER,
Q_DISPLAY_VERTICAL_RESULTS, Q_DISPLAY_HORIZONTAL_RESULTS,
Q_QUERY_VERTICAL, Q_QUERY_HORIZONTAL,
Q_START_TIMER, Q_END_TIMER,
+Q_CHARACTER_SET,
Q_UNKNOWN, /* Unknown command. */
Q_COMMENT, /* Comments, ignored. */
@@ -257,7 +283,7 @@ struct st_query
char *query, *query_buf,*first_argument,*end;
int first_word_len;
my_bool abort_on_error, require_file;
- uint expected_errno[MAX_EXPECTED_ERRORS];
+ match_err expected_errno[MAX_EXPECTED_ERRORS];
uint expected_errors;
char record_file[FN_REFLEN];
enum enum_commands type;
@@ -325,6 +351,7 @@ const char *command_names[]=
"query_horizontal",
"start_timer",
"end_timer",
+ "character_set",
0
};
@@ -346,6 +373,7 @@ int dyn_string_cmp(DYNAMIC_STRING* ds, const char *fname);
void reject_dump(const char *record_file, char *buf, int size);
int close_connection(struct st_query* q);
+static void set_charset(struct st_query*);
VAR* var_get(const char *var_name, const char** var_name_end, my_bool raw,
my_bool ignore_not_existing);
int eval_expr(VAR* v, const char *p, const char** p_end);
@@ -1246,25 +1274,58 @@ static void get_file_name(char *filename, struct st_query* q)
p[0]=0;
}
+static void set_charset(struct st_query* q)
+{
+ char* charset_name= q->first_argument;
+ char* tmp;
+
+ if (!charset_name || !*charset_name)
+ die("Missing charset name in 'character_set'\n");
+ /* Remove end space */
+ tmp= charset_name;
+ while (*tmp && !my_isspace(charset_info,*tmp))
+ tmp++;
+ *tmp= 0;
-static uint get_ints(uint *to,struct st_query* q)
+ charset_info= get_charset_by_csname(charset_name,MY_CS_PRIMARY,MYF(MY_WME));
+ if (!charset_info)
+ abort_not_supported_test();
+}
+
+static uint get_errcodes(match_err *to,struct st_query* q)
{
- char* p=q->first_argument;
- long val;
- uint count=0;
- DBUG_ENTER("get_ints");
+ char* p= q->first_argument;
+ uint count= 0;
+ DBUG_ENTER("get_errcodes");
if (!*p)
die("Missing argument in %s\n", q->query);
- for (; (p=str2int(p,10,(long) INT_MIN, (long) INT_MAX, &val)) ; p++)
+ do
{
+ if (*p == 'S')
+ {
+ /* SQLSTATE string */
+ int i;
+ p++;
+ for (i = 0; my_isalnum(charset_info, *p) && i < SQLSTATE_LENGTH; p++, i++)
+ to[count].code.sqlstate[i]= *p;
+ to[count].code.sqlstate[i]= '\0';
+ to[count].type= ERR_SQLSTATE;
+ }
+ else
+ {
+ long val;
+ p=str2int(p,10,(long) INT_MIN, (long) INT_MAX, &val);
+ if (p == NULL)
+ die("Invalid argument in %s\n", q->query);
+ to[count].code.errnum= (uint) val;
+ to[count].type= ERR_ERRNO;
+ }
count++;
- *to++= (uint) val;
- if (*p != ',')
- break;
- }
- *to++=0; /* End of data */
+ } while (*(p++) == ',');
+
+ to[count].type= ERR_EMPTY; /* End of data */
DBUG_RETURN(count);
}
@@ -1590,7 +1651,7 @@ int do_connect(struct st_query* q)
if (opt_compress)
mysql_options(&next_con->mysql,MYSQL_OPT_COMPRESS,NullS);
mysql_options(&next_con->mysql, MYSQL_OPT_LOCAL_INFILE, 0);
- mysql_options(&next_con->mysql, MYSQL_SET_CHARSET_NAME, "latin1");
+ mysql_options(&next_con->mysql, MYSQL_SET_CHARSET_NAME, charset_name);
#ifdef HAVE_OPENSSL
if (opt_use_ssl)
@@ -1736,6 +1797,7 @@ int read_line(char* buf, int size)
c= my_getc(*cur_file);
if (feof(*cur_file))
{
+ found_eof:
if ((*cur_file) != stdin)
my_fclose(*cur_file, MYF(0));
cur_file--;
@@ -1845,7 +1907,39 @@ int read_line(char* buf, int size)
}
if (!no_save)
- *p++= c;
+ {
+ /* Could be a multibyte character */
+ /* This code is based on the code in "sql_load.cc" */
+#ifdef USE_MB
+ int charlen = my_mbcharlen(charset_info, c);
+ /* We give up if multibyte character is started but not */
+ /* completed before we pass buf_end */
+ if ((charlen > 1) && (p + charlen) <= buf_end)
+ {
+ int i;
+ char* mb_start = p;
+
+ *p++ = c;
+
+ for (i= 1; i < charlen; i++)
+ {
+ if (feof(*cur_file))
+ goto found_eof; /* FIXME: could we just break here?! */
+ c= my_getc(*cur_file);
+ *p++ = c;
+ }
+ if (! my_ismbchar(charset_info, mb_start, p))
+ {
+ /* It was not a multiline char, push back the characters */
+ /* We leave first 'c', i.e. pretend it was a normal char */
+ while (p > mb_start)
+ my_ungetc(*--p);
+ }
+ }
+ else
+#endif
+ *p++= c;
+ }
}
*p= 0; /* Always end with \0 */
DBUG_RETURN(feof(*cur_file));
@@ -1857,7 +1951,6 @@ static char read_query_buf[MAX_QUERY];
int read_query(struct st_query** q_ptr)
{
char *p = read_query_buf, * p1 ;
- int expected_errno;
struct st_query* q;
DBUG_ENTER("read_query");
@@ -1907,13 +2000,25 @@ int read_query(struct st_query** q_ptr)
p++;
if (*p == '$')
{
- expected_errno= 0;
- p++;
- for (; my_isdigit(charset_info, *p); p++)
- expected_errno = expected_errno * 10 + *p - '0';
- q->expected_errno[0] = expected_errno;
- q->expected_errno[1] = 0;
- q->expected_errors=1;
+ int expected_errno= 0;
+ p++;
+ for (; my_isdigit(charset_info, *p); p++)
+ expected_errno = expected_errno * 10 + *p - '0';
+ q->expected_errno[0].code.errnum = expected_errno;
+ q->expected_errno[0].type= ERR_ERRNO;
+ q->expected_errno[1].type= ERR_EMPTY;
+ q->expected_errors=1;
+ }
+ else if (*p == 'S') /* SQLSTATE */
+ {
+ int i;
+ p++;
+ for (i = 0; my_isalnum(charset_info, *p) && i < SQLSTATE_LENGTH; p++, i++)
+ q->expected_errno[0].code.sqlstate[i]= *p;
+ q->expected_errno[0].code.sqlstate[i]= '\0';
+ q->expected_errno[0].type= ERR_SQLSTATE;
+ q->expected_errno[1].type= ERR_EMPTY;
+ q->expected_errors=1;
}
}
@@ -2105,10 +2210,9 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
embedded_server_arg_count=1;
embedded_server_args[0]= (char*) "";
}
- embedded_server_args[embedded_server_arg_count++]=
- my_strdup(argument, MYF(MY_FAE));
- if (embedded_server_arg_count == MAX_SERVER_ARGS ||
- !embedded_server_args[embedded_server_arg_count-1])
+ if (embedded_server_arg_count == MAX_SERVER_ARGS-1 ||
+ !(embedded_server_args[embedded_server_arg_count++]=
+ my_strdup(argument, MYF(MY_FAE))))
{
die("Can't use server argument");
}
@@ -2166,7 +2270,7 @@ char* safe_str_append(char* buf, const char* str, int size)
void str_to_file(const char* fname, char* str, int size)
{
int fd;
- char buff[MAXPATHLEN];
+ char buff[FN_REFLEN];
if (!test_if_hard_path(fname))
{
strxmov(buff, opt_basedir, fname, NullS);
@@ -2300,7 +2404,7 @@ int run_query(MYSQL* mysql, struct st_query* q, int flags)
if (flags & QUERY_SEND)
{
got_error_on_send= mysql_send_query(mysql, query, query_len);
- if (got_error_on_send && !q->expected_errno[0])
+ if (got_error_on_send && q->expected_errno[0].type == ERR_EMPTY)
die("At line %u: unable to send query '%s' (mysql_errno=%d , errno=%d)",
start_lineno, query, mysql_errno(mysql), errno);
}
@@ -2332,7 +2436,10 @@ int run_query(MYSQL* mysql, struct st_query* q, int flags)
{
for (i=0 ; (uint) i < q->expected_errors ; i++)
{
- if ((q->expected_errno[i] == mysql_errno(mysql)))
+ if (((q->expected_errno[i].type == ERR_ERRNO) &&
+ (q->expected_errno[i].code.errnum == mysql_errno(mysql))) ||
+ ((q->expected_errno[i].type == ERR_SQLSTATE) &&
+ (strcmp(q->expected_errno[i].code.sqlstate,mysql_sqlstate(mysql)) == 0)))
{
if (i == 0 && q->expected_errors == 1)
{
@@ -2346,7 +2453,9 @@ int run_query(MYSQL* mysql, struct st_query* q, int flags)
dynstr_append_mem(ds,"\n",1);
}
/* Don't log error if we may not get an error */
- else if (q->expected_errno[0] != 0)
+ else if (q->expected_errno[0].type == ERR_SQLSTATE ||
+ (q->expected_errno[0].type == ERR_ERRNO &&
+ q->expected_errno[0].code.errnum != 0))
dynstr_append(ds,"Got one of the listed errors\n");
goto end; /* Ok */
}
@@ -2362,8 +2471,12 @@ int run_query(MYSQL* mysql, struct st_query* q, int flags)
dynstr_append_mem(ds,"\n",1);
if (i)
{
- verbose_msg("query '%s' failed with wrong errno %d instead of %d...",
- q->query, mysql_errno(mysql), q->expected_errno[0]);
+ if (q->expected_errno[0].type == ERR_ERRNO)
+ verbose_msg("query '%s' failed with wrong errno %d instead of %d...",
+ q->query, mysql_errno(mysql), q->expected_errno[0].code.errnum);
+ else
+ verbose_msg("query '%s' failed with wrong sqlstate %s instead of %s...",
+ q->query, mysql_sqlstate(mysql), q->expected_errno[0].code.sqlstate);
error= 1;
goto end;
}
@@ -2383,11 +2496,22 @@ int run_query(MYSQL* mysql, struct st_query* q, int flags)
}*/
}
- if (q->expected_errno[0])
+ if (q->expected_errno[0].type == ERR_ERRNO &&
+ q->expected_errno[0].code.errnum != 0)
{
- error = 1;
+ /* Error code we wanted was != 0, i.e. not an expected success */
verbose_msg("query '%s' succeeded - should have failed with errno %d...",
- q->query, q->expected_errno[0]);
+ q->query, q->expected_errno[0].code.errnum);
+ error = 1;
+ goto end;
+ }
+ else if (q->expected_errno[0].type == ERR_SQLSTATE &&
+ strcmp(q->expected_errno[0].code.sqlstate,"00000") != 0)
+ {
+ /* SQLSTATE we wanted was != "00000", i.e. not an expected success */
+ verbose_msg("query '%s' succeeded - should have failed with sqlstate %s...",
+ q->query, q->expected_errno[0].code.sqlstate);
+ error = 1;
goto end;
}
@@ -2678,7 +2802,7 @@ int main(int argc, char **argv)
if (opt_compress)
mysql_options(&cur_con->mysql,MYSQL_OPT_COMPRESS,NullS);
mysql_options(&cur_con->mysql, MYSQL_OPT_LOCAL_INFILE, 0);
- mysql_options(&cur_con->mysql, MYSQL_SET_CHARSET_NAME, "latin1");
+ mysql_options(&cur_con->mysql, MYSQL_SET_CHARSET_NAME, charset_name);
#ifdef HAVE_OPENSSL
if (opt_use_ssl)
@@ -2818,7 +2942,7 @@ int main(int argc, char **argv)
require_file=0;
break;
case Q_ERROR:
- global_expected_errors=get_ints(global_expected_errno,q);
+ global_expected_errors=get_errcodes(global_expected_errno,q);
break;
case Q_REQUIRE:
get_file_name(save_file,q);
@@ -2863,6 +2987,9 @@ int main(int argc, char **argv)
timer_output();
got_end_timer= TRUE;
break;
+ case Q_CHARACTER_SET:
+ set_charset(q);
+ break;
default: processed = 0; break;
}
}
@@ -2979,10 +3106,10 @@ static void timer_output(void)
{
if (timer_file)
{
- char buf[1024];
+ char buf[32], *end;
ulonglong timer= timer_now() - timer_start;
- sprintf(buf,"%llu",timer);
- str_to_file(timer_file,buf,strlen(buf));
+ end= longlong2str(timer, buf, 10);
+ str_to_file(timer_file,buf, (int) (end-buf));
}
}
diff --git a/cmd-line-utils/libedit/np/vis.c b/cmd-line-utils/libedit/np/vis.c
index db42443800b..e8f5c195f10 100644
--- a/cmd-line-utils/libedit/np/vis.c
+++ b/cmd-line-utils/libedit/np/vis.c
@@ -63,7 +63,7 @@ __weak_alias(vis,_vis)
#include <limits.h>
#include <stdio.h>
#include <string.h>
-
+#include <assert.h>
#undef BELL
#if defined(__STDC__)
#define BELL '\a'
@@ -79,22 +79,24 @@ __weak_alias(vis,_vis)
#define MAXEXTRAS 5
-#define MAKEEXTRALIST(flag, extra, orig) \
-do { \
- const char *o = orig; \
- char *e; \
- while (*o++) \
- continue; \
- extra = alloca((size_t)((o - orig) + MAXEXTRAS)); \
- for (o = orig, e = extra; (*e++ = *o++) != '\0';) \
- continue; \
- e--; \
- if (flag & VIS_SP) *e++ = ' '; \
- if (flag & VIS_TAB) *e++ = '\t'; \
- if (flag & VIS_NL) *e++ = '\n'; \
- if ((flag & VIS_NOSLASH) == 0) *e++ = '\\'; \
- *e = '\0'; \
-} while (/*CONSTCOND*/0)
+char *MAKEEXTRALIST(unsigned int flag, const char *orig)
+{
+ const char *o = orig;
+ char *e, *extra;
+ while (*o++)
+ continue;
+ extra = (char*) malloc((size_t)((o - orig) + MAXEXTRAS));
+ assert(extra);
+ for (o = orig, e = extra; (*e++ = *o++) != '\0';)
+ continue;
+ e--;
+ if (flag & VIS_SP) *e++ = ' ';
+ if (flag & VIS_TAB) *e++ = '\t';
+ if (flag & VIS_NL) *e++ = '\n';
+ if ((flag & VIS_NOSLASH) == 0) *e++ = '\\';
+ *e = '\0';
+ return extra;
+}
/*
@@ -198,15 +200,16 @@ svis(dst, c, flag, nextc, extra)
int c, flag, nextc;
const char *extra;
{
- char *nextra;
+ char *nextra, *to_be_freed;
_DIAGASSERT(dst != NULL);
_DIAGASSERT(extra != NULL);
- MAKEEXTRALIST(flag, nextra, extra);
+ nextra= to_be_freed= MAKEEXTRALIST(flag, extra);
if (flag & VIS_HTTPSTYLE)
HVIS(dst, c, flag, nextc, nextra);
else
SVIS(dst, c, flag, nextc, nextra);
*dst = '\0';
+ free(to_be_freed);
return(dst);
}
@@ -235,12 +238,12 @@ strsvis(dst, src, flag, extra)
{
char c;
char *start;
- char *nextra;
+ char *nextra, *to_be_freed;
_DIAGASSERT(dst != NULL);
_DIAGASSERT(src != NULL);
_DIAGASSERT(extra != NULL);
- MAKEEXTRALIST(flag, nextra, extra);
+ nextra= to_be_freed= MAKEEXTRALIST(flag, extra);
if (flag & VIS_HTTPSTYLE) {
for (start = dst; (c = *src++) != '\0'; /* empty */)
HVIS(dst, c, flag, *src, nextra);
@@ -249,6 +252,7 @@ strsvis(dst, src, flag, extra)
SVIS(dst, c, flag, *src, nextra);
}
*dst = '\0';
+ free(to_be_freed);
return (dst - start);
}
@@ -263,12 +267,12 @@ strsvisx(dst, src, len, flag, extra)
{
char c;
char *start;
- char *nextra;
+ char *nextra, *to_be_freed;
_DIAGASSERT(dst != NULL);
_DIAGASSERT(src != NULL);
_DIAGASSERT(extra != NULL);
- MAKEEXTRALIST(flag, nextra, extra);
+ nextra= to_be_freed= MAKEEXTRALIST(flag, extra);
if (flag & VIS_HTTPSTYLE) {
for (start = dst; len > 0; len--) {
@@ -282,6 +286,7 @@ strsvisx(dst, src, len, flag, extra)
}
}
*dst = '\0';
+ free(to_be_freed);
return (dst - start);
}
@@ -295,16 +300,18 @@ vis(dst, c, flag, nextc)
int c, flag, nextc;
{
- char *extra;
+ char *extra, *to_be_freed;
_DIAGASSERT(dst != NULL);
- MAKEEXTRALIST(flag, extra, "");
+ extra= to_be_freed= MAKEEXTRALIST(flag, "");
+
if (flag & VIS_HTTPSTYLE)
HVIS(dst, c, flag, nextc, extra);
else
SVIS(dst, c, flag, nextc, extra);
*dst = '\0';
+ free(to_be_freed);
return (dst);
}
@@ -326,9 +333,12 @@ strvis(dst, src, flag)
int flag;
{
char *extra;
+ int tmp;
- MAKEEXTRALIST(flag, extra, "");
- return (strsvis(dst, src, flag, extra));
+ extra= MAKEEXTRALIST(flag, "");
+ tmp= strsvis(dst, src, flag, extra);
+ free(extra);
+ return tmp;
}
@@ -340,8 +350,11 @@ strvisx(dst, src, len, flag)
int flag;
{
char *extra;
+ int tmp;
- MAKEEXTRALIST(flag, extra, "");
- return (strsvisx(dst, src, len, flag, extra));
+ extra= MAKEEXTRALIST(flag, "");
+ tmp= strsvisx(dst, src, len, flag, extra);
+ free(extra);
+ return tmp;
}
#endif
diff --git a/configure.in b/configure.in
index b06fc35b23f..810f6c31c49 100644
--- a/configure.in
+++ b/configure.in
@@ -15,7 +15,7 @@ SHARED_LIB_VERSION=14:0:0
# ndb version
NDB_VERSION_MAJOR=3
NDB_VERSION_MINOR=5
-NDB_VERSION_BUILD=2
+NDB_VERSION_BUILD=3
NDB_VERSION_STATUS=""
# Set all version vars based on $VERSION. How do we do this more elegant ?
@@ -44,12 +44,12 @@ do
case $host_os in
netware* | modesto*)
echo "$i/errmsg.sys: $i/errmsg.txt
- \$(top_builddir)/extra/comp_err.linux -C\$(srcdir)/charsets/ \$^ $i/errmsg.sys" \
+ \$(top_builddir)/extra/comp_err.linux -C\$(srcdir)/charsets/ $i/errmsg.txt $i/errmsg.sys" \
>> $AVAILABLE_LANGUAGES_ERRORS_RULES
;;
*)
echo "$i/errmsg.sys: $i/errmsg.txt
- \$(top_builddir)/extra/comp_err -C\$(srcdir)/charsets/ \$^ $i/errmsg.sys" \
+ \$(top_builddir)/extra/comp_err -C\$(srcdir)/charsets/ $i/errmsg.txt $i/errmsg.sys" \
>> $AVAILABLE_LANGUAGES_ERRORS_RULES
;;
esac
@@ -967,12 +967,16 @@ esac
MAX_C_OPTIMIZE="-O3"
MAX_CXX_OPTIMIZE="-O3"
-# workaround for Sun Forte/x86 see BUG#4681
case $SYSTEM_TYPE-$MACHINE_TYPE-$ac_cv_prog_gcc in
+# workaround for Sun Forte/x86 see BUG#4681
*solaris*-i?86-no)
CFLAGS="$CFLAGS -DBIG_TABLES"
CXXFLAGS="$CXXFLAGS -DBIG_TABLES"
;;
+# workaround for Sun Forte compile problem for ndb
+ *solaris2.10*-sparc-no)
+ ndb_cxxflags_fix="$ndb_cxxflags_fix -instances=static"
+ ;;
*) ;;
esac
@@ -1140,6 +1144,7 @@ dnl Is this the right match for DEC OSF on alpha?
# gethostbyname_r is deprecated and doesn't work ok on OSF1
CFLAGS="$CFLAGS -DUNDEF_HAVE_GETHOSTBYNAME_R"
CXXFLAGS="$CXXFLAGS -DUNDEF_HAVE_GETHOSTBYNAME_R"
+ ndb_cxxflags_fix="$ndb_cxxflags_fix -I/usr/include.dtk"
;;
*netware*)
# No need for curses library so set it to null
diff --git a/include/m_ctype.h b/include/m_ctype.h
index 1f42b514a1b..ddc21070547 100644
--- a/include/m_ctype.h
+++ b/include/m_ctype.h
@@ -365,6 +365,11 @@ uint my_instr_mb(struct charset_info_st *,
const char *s, uint s_length,
my_match_t *match, uint nmatch);
+int my_wildcmp_unicode(CHARSET_INFO *cs,
+ const char *str, const char *str_end,
+ const char *wildstr, const char *wildend,
+ int escape, int w_one, int w_many,
+ MY_UNICASE_INFO **weights);
extern my_bool my_parse_charset_xml(const char *bug, uint len,
int (*add)(CHARSET_INFO *cs));
diff --git a/include/my_sys.h b/include/my_sys.h
index 271e0ea0bcb..01a7482e4d0 100644
--- a/include/my_sys.h
+++ b/include/my_sys.h
@@ -726,7 +726,7 @@ extern void my_free_lock(byte *ptr,myf flags);
#endif
#define alloc_root_inited(A) ((A)->min_malloc != 0)
#define ALLOC_ROOT_MIN_BLOCK_SIZE (MALLOC_OVERHEAD + sizeof(USED_MEM) + 8)
-#define clear_alloc_root(A) do { (A)->free= (A)->used= (A)->pre_alloc= 0; } while(0)
+#define clear_alloc_root(A) do { (A)->free= (A)->used= (A)->pre_alloc= 0; (A)->min_malloc=0;} while(0)
extern void init_alloc_root(MEM_ROOT *mem_root, uint block_size,
uint pre_alloc_size);
extern gptr alloc_root(MEM_ROOT *mem_root,unsigned int Size);
diff --git a/include/my_time.h b/include/my_time.h
index d4dbe459c3b..dab17904b2d 100644
--- a/include/my_time.h
+++ b/include/my_time.h
@@ -60,6 +60,20 @@ my_system_gmt_sec(const MYSQL_TIME *t, long *my_timezone, bool *in_dst_time_gap)
void set_zero_time(MYSQL_TIME *tm);
+/*
+ Required buffer length for my_time_to_str, my_date_to_str,
+ my_datetime_to_str and TIME_to_string functions. Note, that the
+ caller is still responsible to check that given TIME structure
+ has values in valid ranges, otherwise size of the buffer could
+ be not enough.
+*/
+#define MAX_DATE_STRING_REP_LENGTH 30
+
+int my_time_to_str(const MYSQL_TIME *l_time, char *to);
+int my_date_to_str(const MYSQL_TIME *l_time, char *to);
+int my_datetime_to_str(const MYSQL_TIME *l_time, char *to);
+int my_TIME_to_str(const MYSQL_TIME *l_time, char *to);
+
C_MODE_END
#endif /* _my_time_h_ */
diff --git a/include/mysql.h b/include/mysql.h
index cf5af6ce189..1c886020fdb 100644
--- a/include/mysql.h
+++ b/include/mysql.h
@@ -506,6 +506,7 @@ char * STDCALL mysql_odbc_escape_string(MYSQL *mysql,
unsigned long *length));
void STDCALL myodbc_remove_escape(MYSQL *mysql,char *name);
unsigned int STDCALL mysql_thread_safe(void);
+my_bool STDCALL mysql_embedded(void);
MYSQL_MANAGER* STDCALL mysql_manager_init(MYSQL_MANAGER* con);
MYSQL_MANAGER* STDCALL mysql_manager_connect(MYSQL_MANAGER* con,
const char* host,
diff --git a/innobase/dict/dict0dict.c b/innobase/dict/dict0dict.c
index fd98538d2ad..c3d0d8d9ac1 100644
--- a/innobase/dict/dict0dict.c
+++ b/innobase/dict/dict0dict.c
@@ -53,6 +53,30 @@ rw_lock_t dict_operation_lock; /* table create, drop, etc. reserve
/* Identifies generated InnoDB foreign key names */
static char dict_ibfk[] = "_ibfk_";
+/**********************************************************************
+Compares NUL-terminated UTF-8 strings case insensitively.
+
+NOTE: the prototype of this function is copied from ha_innodb.cc! If you change
+this function, you MUST change also the prototype here! */
+extern
+int
+innobase_strcasecmp(
+/*================*/
+ /* out: 0 if a=b, <0 if a<b, >1 if a>b */
+ const char* a, /* in: first string to compare */
+ const char* b); /* in: second string to compare */
+
+/**********************************************************************
+Makes all characters in a NUL-terminated UTF-8 string lower case.
+
+NOTE: the prototype of this function is copied from ha_innodb.cc! If you change
+this function, you MUST change also the prototype here! */
+extern
+void
+innobase_casedn_str(
+/*================*/
+ char* a); /* in/out: string to put in lower case */
+
/**************************************************************************
Adds a column to the data dictionary hash table. */
static
@@ -2066,7 +2090,7 @@ dict_foreign_find_index(
break;
}
- if (0 != ut_cmp_in_lower_case(columns[i],
+ if (0 != innobase_strcasecmp(columns[i],
col_name)) {
break;
}
@@ -2244,7 +2268,7 @@ dict_foreign_add_to_cache(
Scans from pointer onwards. Stops if is at the start of a copy of
'string' where characters are compared without case sensitivity. Stops
also at '\0'. */
-static
+
const char*
dict_scan_to(
/*=========*/
@@ -2436,7 +2460,7 @@ dict_scan_col(
col = dict_table_get_nth_col(table, i);
- if (0 == ut_cmp_in_lower_case(col->name, *name)) {
+ if (0 == innobase_strcasecmp(col->name, *name)) {
/* Found */
*success = TRUE;
@@ -2528,30 +2552,19 @@ dict_scan_table_name(
table_name_len = strlen(table_name);
+ /* Copy database_name, '/', table_name, '\0' */
ref = mem_heap_alloc(heap, database_name_len + table_name_len + 2);
-
-#ifdef __WIN__
- ut_cpy_in_lower_case(ref, database_name, database_name_len);
-#else
+ memcpy(ref, database_name, database_name_len);
+ ref[database_name_len] = '/';
+ memcpy(ref + database_name_len + 1, table_name, table_name_len + 1);
+#ifndef __WIN__
if (srv_lower_case_table_names) {
- ut_cpy_in_lower_case(ref, database_name, database_name_len);
- } else {
- memcpy(ref, database_name, database_name_len);
+#endif /* !__WIN__ */
+ /* The table name is always put to lower case on Windows. */
+ innobase_casedn_str(ref);
+#ifndef __WIN__
}
-#endif
- (ref)[database_name_len] = '/';
-
-#ifdef __WIN__
- ut_cpy_in_lower_case(ref + database_name_len + 1,
- table_name, table_name_len + 1);
-#else
- if (srv_lower_case_table_names) {
- ut_cpy_in_lower_case(ref + database_name_len + 1,
- table_name, table_name_len + 1);
- } else {
- strcpy(ref + database_name_len + 1, table_name);
- }
-#endif
+#endif /* !__WIN__ */
*success = TRUE;
*ref_name = ref;
diff --git a/innobase/include/dict0dict.h b/innobase/include/dict0dict.h
index 4dbbd5b4886..ca632691450 100644
--- a/innobase/include/dict0dict.h
+++ b/innobase/include/dict0dict.h
@@ -891,6 +891,18 @@ dict_tables_have_same_db(
const char* name2); /* in: table name in the form
dbname '/' tablename */
+/*************************************************************************
+Scans from pointer onwards. Stops if is at the start of a copy of
+'string' where characters are compared without case sensitivity. Stops
+also at '\0'. */
+
+const char*
+dict_scan_to(
+/*=========*/
+ /* out: scanned up to this */
+ const char* ptr, /* in: scan from */
+ const char* string);/* in: look for this */
+
/* Buffers for storing detailed information about the latest foreign key
and unique key errors */
extern FILE* dict_foreign_err_file;
diff --git a/innobase/include/os0file.h b/innobase/include/os0file.h
index f1647c47bce..d1439faf29f 100644
--- a/innobase/include/os0file.h
+++ b/innobase/include/os0file.h
@@ -14,6 +14,7 @@ Created 10/21/1995 Heikki Tuuri
#ifndef __WIN__
#include <dirent.h>
#include <sys/stat.h>
+#include <time.h>
#endif
extern ibool os_do_not_call_flush_at_each_write;
@@ -142,12 +143,15 @@ bigger than 4000 bytes */
#define OS_FILE_MAX_PATH 4000
/* Struct used in fetching information of a file in a directory */
-typedef struct os_file_stat_struct os_file_stat_t;
struct os_file_stat_struct{
- char name[OS_FILE_MAX_PATH]; /* path to a file */
- os_file_type_t type; /* file type */
- ib_longlong size; /* file size */
+ char name[OS_FILE_MAX_PATH]; /* path to a file */
+ os_file_type_t type; /* file type */
+ ib_longlong size; /* file size */
+ time_t ctime; /* creation time */
+ time_t mtime; /* modification time */
+ time_t atime; /* access time */
};
+typedef struct os_file_stat_struct os_file_stat_t;
#ifdef __WIN__
typedef HANDLE os_file_dir_t; /* directory stream */
@@ -686,5 +690,14 @@ no pending io operations. */
ibool
os_aio_all_slots_free(void);
/*=======================*/
- /* out: TRUE if all free */
+
+/***********************************************************************
+This function returns information about the specified file */
+ibool
+os_file_get_status(
+/*===============*/
+ /* out: TRUE if stat information found */
+ const char* path, /* in: pathname of the file */
+ os_file_stat_t* stat_info); /* information of a file in a directory */
+
#endif
diff --git a/innobase/include/sync0arr.h b/innobase/include/sync0arr.h
index 92691d5fdd9..fecd910683e 100644
--- a/innobase/include/sync0arr.h
+++ b/innobase/include/sync0arr.h
@@ -97,9 +97,11 @@ sync_arr_wake_threads_if_sema_free(void);
/**************************************************************************
Prints warnings of long semaphore waits to stderr. */
-void
+ibool
sync_array_print_long_waits(void);
/*=============================*/
+ /* out: TRUE if fatal semaphore wait threshold
+ was exceeded */
/************************************************************************
Validates the integrity of the wait array. Checks
that the number of reserved cells equals the count variable. */
diff --git a/innobase/include/ut0byte.h b/innobase/include/ut0byte.h
index fed6a23d144..a62c2e2e318 100644
--- a/innobase/include/ut0byte.h
+++ b/innobase/include/ut0byte.h
@@ -229,25 +229,6 @@ ut_bit_set_nth(
ulint a, /* in: ulint */
ulint n, /* in: nth bit requested */
ibool val); /* in: value for the bit to set */
-/****************************************************************
-Copies a string to a memory location, setting characters to lower case. */
-
-void
-ut_cpy_in_lower_case(
-/*=================*/
- char* dest, /* in: destination */
- const char* source, /* in: source */
- ulint len); /* in: string length */
-/****************************************************************
-Compares two strings when converted to lower case. */
-
-int
-ut_cmp_in_lower_case(
-/*=================*/
- /* out: -1, 0, 1 if str1 < str2, str1 == str2,
- str1 > str2, respectively */
- const char* str1, /* in: string1 */
- const char* str2); /* in: string2 */
#ifndef UNIV_NONINL
#include "ut0byte.ic"
diff --git a/innobase/os/os0file.c b/innobase/os/os0file.c
index 1040283f85e..3276aaddca2 100644
--- a/innobase/os/os0file.c
+++ b/innobase/os/os0file.c
@@ -2010,6 +2010,11 @@ try_again:
return(TRUE);
}
+
+ fprintf(stderr,
+"InnoDB: Error: tried to read %lu bytes at offset %lu %lu.\n"
+"InnoDB: Was only able to read %ld.\n", (ulong)n, (ulong)offset_high,
+ (ulong)offset, (long)ret);
#endif
#ifdef __WIN__
error_handling:
@@ -2354,6 +2359,83 @@ os_file_status(
#endif
}
+/***********************************************************************
+This function returns information about the specified file */
+
+ibool
+os_file_get_status(
+/*===========*/
+ /* out: TRUE if stat information found */
+ const char* path, /* in: pathname of the file */
+ os_file_stat_t* stat_info) /* information of a file in a directory */
+{
+#ifdef __WIN__
+ int ret;
+ struct _stat statinfo;
+
+ ret = _stat(path, &statinfo);
+ if (ret && (errno == ENOENT || errno == ENOTDIR)) {
+ /* file does not exist */
+
+ return(FALSE);
+ } else if (ret) {
+ /* file exists, but stat call failed */
+
+ os_file_handle_error_no_exit(0, path, "stat");
+
+ return(FALSE);
+ }
+ if (_S_IFDIR & statinfo.st_mode) {
+ stat_info->type = OS_FILE_TYPE_DIR;
+ } else if (_S_IFREG & statinfo.st_mode) {
+ stat_info->type = OS_FILE_TYPE_FILE;
+ } else {
+ stat_info_>type = OS_FILE_TYPE_UNKNOWN;
+ }
+
+ stat_info->ctime = statinfo.st_ctime;
+ stat_info->atime = statinfo.st_atime;
+ stat_info->mtime = statinfo.st_mtime;
+ stat_info->size = statinfo.st_size;
+
+ return(TRUE);
+#else
+ int ret;
+ struct stat statinfo;
+
+ ret = stat(path, &statinfo);
+
+ if (ret && (errno == ENOENT || errno == ENOTDIR)) {
+ /* file does not exist */
+
+ return(FALSE);
+ } else if (ret) {
+ /* file exists, but stat call failed */
+
+ os_file_handle_error_no_exit(0, path, "stat");
+
+ return(FALSE);
+ }
+
+ if (S_ISDIR(statinfo.st_mode)) {
+ stat_info->type = OS_FILE_TYPE_DIR;
+ } else if (S_ISLNK(statinfo.st_mode)) {
+ stat_info->type = OS_FILE_TYPE_LINK;
+ } else if (S_ISREG(statinfo.st_mode)) {
+ stat_info->type = OS_FILE_TYPE_FILE;
+ } else {
+ stat_info->type = OS_FILE_TYPE_UNKNOWN;
+ }
+
+ stat_info->ctime = statinfo.st_ctime;
+ stat_info->atime = statinfo.st_atime;
+ stat_info->mtime = statinfo.st_mtime;
+ stat_info->size = statinfo.st_size;
+
+ return(TRUE);
+#endif
+}
+
/* path name separator character */
#ifdef __WIN__
# define OS_FILE_PATH_SEPARATOR '\\'
diff --git a/innobase/row/row0ins.c b/innobase/row/row0ins.c
index 7b0beb9d183..c9c784403c8 100644
--- a/innobase/row/row0ins.c
+++ b/innobase/row/row0ins.c
@@ -50,6 +50,15 @@ innobase_invalidate_query_cache(
ulint full_name_len); /* in: full name length where also the null
chars count */
+/**********************************************************************
+This function returns true if SQL-query in the current thread
+is either REPLACE or LOAD DATA INFILE REPLACE.
+NOTE that /mysql/innobase/row/row0ins.c must contain the
+prototype for this function ! */
+
+ibool
+innobase_query_is_replace(void);
+/*===========================*/
/*************************************************************************
Creates an insert node struct. */
@@ -1482,9 +1491,9 @@ row_ins_scan_sec_index_for_duplicate(
ulint err = DB_SUCCESS;
ibool moved;
mtr_t mtr;
- trx_t *trx;
- ibool success;
-
+ trx_t* trx;
+ const char* ptr;
+
n_unique = dict_index_get_n_unique(index);
/* If the secondary index is unique, but one of the fields in the
@@ -1523,9 +1532,8 @@ row_ins_scan_sec_index_for_duplicate(
trx = thr_get_trx(thr);
ut_ad(trx);
- dict_accept(*trx->mysql_query_str, "REPLACE", &success);
- if (success) {
+ if (innobase_query_is_replace()) {
/* The manual defines the REPLACE semantics that it
is either an INSERT or DELETE(s) for duplicate key
@@ -1605,7 +1613,7 @@ row_ins_duplicate_error_in_clust(
page_t* page;
ulint n_unique;
trx_t* trx = thr_get_trx(thr);
- ibool success;
+ const char* ptr;
UT_NOT_USED(mtr);
@@ -1639,10 +1647,7 @@ row_ins_duplicate_error_in_clust(
sure that in roll-forward we get the same duplicate
errors as in original execution */
- dict_accept(*trx->mysql_query_str, "REPLACE",
- &success);
-
- if (success) {
+ if (innobase_query_is_replace()) {
/* The manual defines the REPLACE semantics
that it is either an INSERT or DELETE(s)
@@ -1683,15 +1688,9 @@ row_ins_duplicate_error_in_clust(
/* The manual defines the REPLACE semantics that it
is either an INSERT or DELETE(s) for duplicate key
+ INSERT. Therefore, we should take X-lock for
- duplicates.
- */
-
- /* Is the first word in MySQL query REPLACE ? */
-
- dict_accept(*trx->mysql_query_str, "REPLACE",
- &success);
+ duplicates. */
- if (success) {
+ if (innobase_query_is_replace()) {
err = row_ins_set_exclusive_rec_lock(
LOCK_REC_NOT_GAP,
diff --git a/innobase/row/row0sel.c b/innobase/row/row0sel.c
index 3ff94c8f238..740241fa210 100644
--- a/innobase/row/row0sel.c
+++ b/innobase/row/row0sel.c
@@ -2794,7 +2794,7 @@ row_search_for_mysql(
rec_t* index_rec;
rec_t* clust_rec;
rec_t* old_vers;
- ulint err;
+ ulint err = DB_SUCCESS;
ibool moved;
ibool cons_read_requires_clust_rec;
ibool was_lock_wait;
@@ -3203,26 +3203,20 @@ rec_loop:
if (prebuilt->select_lock_type != LOCK_NONE
&& set_also_gap_locks) {
- /* Try to place a lock on the index record */
+ /* Try to place a lock on the index record */
- /* If innodb_locks_unsafe_for_binlog option is used,
- we lock only the record, i.e. next-key locking is
- not used.
- */
- if ( srv_locks_unsafe_for_binlog )
- {
- err = sel_set_rec_lock(rec, index,
- prebuilt->select_lock_type,
- LOCK_REC_NOT_GAP, thr);
- }
- else
+ /* If innodb_locks_unsafe_for_binlog option is used,
+ we do not lock gaps. Supremum record is really
+ a gap and therefore we do not set locks there. */
+
+ if ( srv_locks_unsafe_for_binlog == FALSE )
{
- err = sel_set_rec_lock(rec, index,
+ err = sel_set_rec_lock(rec, index,
prebuilt->select_lock_type,
LOCK_ORDINARY, thr);
}
-
- if (err != DB_SUCCESS) {
+
+ if (err != DB_SUCCESS) {
goto lock_wait_or_error;
}
diff --git a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c
index d913d77fdfc..b8d03cfab5f 100644
--- a/innobase/srv/srv0srv.c
+++ b/innobase/srv/srv0srv.c
@@ -951,7 +951,13 @@ retry:
trx->op_info = "sleeping before joining InnoDB queue";
- os_thread_sleep(50000);
+ /* Peter Zaitsev suggested that we take the sleep away
+ altogether. But the sleep may be good in pathological
+ situations of lots of thread switches. Simply put some
+ threads aside for a while to reduce the number of thread
+ switches. */
+
+ os_thread_sleep(10000);
trx->op_info = "";
@@ -1814,7 +1820,8 @@ srv_error_monitor_thread(
/* in: a dummy parameter required by
os_thread_create */
{
- ulint cnt = 0;
+ /* number of successive fatal timeouts observed */
+ ulint fatal_cnt = 0;
dulint old_lsn;
dulint new_lsn;
@@ -1827,8 +1834,6 @@ srv_error_monitor_thread(
loop:
srv_error_monitor_active = TRUE;
- cnt++;
-
/* Try to track a strange bug reported by Harald Fuchs and others,
where the lsn seems to decrease at times */
@@ -1855,7 +1860,20 @@ loop:
srv_refresh_innodb_monitor_stats();
}
- sync_array_print_long_waits();
+ if (sync_array_print_long_waits()) {
+ fatal_cnt++;
+ if (fatal_cnt > 5) {
+
+ fprintf(stderr,
+"InnoDB: Error: semaphore wait has lasted > %lu seconds\n"
+"InnoDB: We intentionally crash the server, because it appears to be hung.\n",
+ srv_fatal_semaphore_wait_threshold);
+
+ ut_error;
+ }
+ } else {
+ fatal_cnt = 0;
+ }
/* Flush stderr so that a database user gets the output
to possible MySQL error file */
diff --git a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c
index 8e48034e09c..9709f5235de 100644
--- a/innobase/srv/srv0start.c
+++ b/innobase/srv/srv0start.c
@@ -95,6 +95,19 @@ static char* srv_monitor_file_name;
#define SRV_N_PENDING_IOS_PER_THREAD OS_AIO_N_PENDING_IOS_PER_THREAD
#define SRV_MAX_N_PENDING_SYNC_IOS 100
+
+/* Avoid warnings when using purify */
+
+#ifdef HAVE_purify
+static int inno_bcmp(register const char *s1, register const char *s2,
+ register uint len)
+{
+ while (len-- != 0 && *s1++ == *s2++) ;
+ return len+1;
+}
+#define memcmp(A,B,C) inno_bcmp((A),(B),(C))
+#endif
+
/*************************************************************************
Reads the data files and their sizes from a character string given in
the .cnf file. */
diff --git a/innobase/sync/sync0arr.c b/innobase/sync/sync0arr.c
index e5285cb7ebf..198ef49ca9f 100644
--- a/innobase/sync/sync0arr.c
+++ b/innobase/sync/sync0arr.c
@@ -894,15 +894,18 @@ sync_arr_wake_threads_if_sema_free(void)
/**************************************************************************
Prints warnings of long semaphore waits to stderr. */
-void
+ibool
sync_array_print_long_waits(void)
/*=============================*/
+ /* out: TRUE if fatal semaphore wait threshold
+ was exceeded */
{
sync_cell_t* cell;
ibool old_val;
ibool noticed = FALSE;
ulint i;
ulint fatal_timeout = srv_fatal_semaphore_wait_threshold;
+ ibool fatal = FALSE;
for (i = 0; i < sync_primary_wait_array->n_cells; i++) {
@@ -919,13 +922,7 @@ sync_array_print_long_waits(void)
if (cell->wait_object != NULL
&& difftime(time(NULL), cell->reservation_time)
> fatal_timeout) {
-
- fprintf(stderr,
-"InnoDB: Error: semaphore wait has lasted > %lu seconds\n"
-"InnoDB: We intentionally crash the server, because it appears to be hung.\n",
- fatal_timeout);
-
- ut_error;
+ fatal = TRUE;
}
}
@@ -953,6 +950,8 @@ sync_array_print_long_waits(void)
fprintf(stderr,
"InnoDB: ###### Diagnostic info printed to the standard error stream\n");
}
+
+ return(fatal);
}
/**************************************************************************
diff --git a/innobase/trx/trx0rec.c b/innobase/trx/trx0rec.c
index ba93c6de2bd..fe429d1cc62 100644
--- a/innobase/trx/trx0rec.c
+++ b/innobase/trx/trx0rec.c
@@ -1258,7 +1258,7 @@ trx_undo_prev_version_build(
ibool dummy_extern;
byte* buf;
ulint err;
- ulint i;
+
#ifdef UNIV_SYNC_DEBUG
ut_ad(rw_lock_own(&(purge_sys->latch), RW_LOCK_SHARED));
#endif /* UNIV_SYNC_DEBUG */
@@ -1363,7 +1363,18 @@ trx_undo_prev_version_build(
}
if (row_upd_changes_field_size_or_external(rec, index, update)) {
-
+ ulint* ext_vect;
+ ulint n_ext_vect;
+
+ /* We have to set the appropriate extern storage bits in the
+ old version of the record: the extern bits in rec for those
+ fields that update does NOT update, as well as the the bits for
+ those fields that update updates to become externally stored
+ fields. Store the info to ext_vect: */
+
+ ext_vect = mem_alloc(sizeof(ulint) * rec_get_n_fields(rec));
+ n_ext_vect = btr_push_update_extern_fields(ext_vect, rec,
+ update);
entry = row_rec_to_index_entry(ROW_COPY_DATA, index, rec,
heap);
row_upd_index_replace_new_col_vals(entry, index, update, heap);
@@ -1371,6 +1382,11 @@ trx_undo_prev_version_build(
buf = mem_heap_alloc(heap, rec_get_converted_size(entry));
*old_vers = rec_convert_dtuple_to_rec(buf, entry);
+
+ /* Now set the extern bits in the old version of the record */
+ rec_set_field_extern_bits(*old_vers, ext_vect, n_ext_vect,
+ NULL);
+ mem_free(ext_vect);
} else {
buf = mem_heap_alloc(heap, rec_get_size(rec));
@@ -1379,15 +1395,5 @@ trx_undo_prev_version_build(
row_upd_rec_in_place(*old_vers, update);
}
- for (i = 0; i < upd_get_n_fields(update); i++) {
-
- if (upd_get_nth_field(update, i)->extern_storage) {
-
- rec_set_nth_field_extern_bit(*old_vers,
- upd_get_nth_field(update, i)->field_no,
- TRUE, NULL);
- }
- }
-
return(DB_SUCCESS);
}
diff --git a/innobase/ut/ut0byte.c b/innobase/ut/ut0byte.c
index 8764103dc36..cc83aacc90b 100644
--- a/innobase/ut/ut0byte.c
+++ b/innobase/ut/ut0byte.c
@@ -29,51 +29,3 @@ ut_dulint_sort(dulint* arr, dulint* aux_arr, ulint low, ulint high)
UT_SORT_FUNCTION_BODY(ut_dulint_sort, arr, aux_arr, low, high,
ut_dulint_cmp);
}
-
-/****************************************************************
-Copies a string to a memory location, setting characters to lower case. */
-
-void
-ut_cpy_in_lower_case(
-/*=================*/
- char* dest, /* in: destination */
- const char* source, /* in: source */
- ulint len) /* in: string length */
-{
- ulint i;
-
- for (i = 0; i < len; i++) {
- dest[i] = tolower(source[i]);
- }
-}
-
-/****************************************************************
-Compares two strings when converted to lower case. */
-
-int
-ut_cmp_in_lower_case(
-/*=================*/
- /* out: -1, 0, 1 if str1 < str2, str1 == str2,
- str1 > str2, respectively */
- const char* str1, /* in: string1 */
- const char* str2) /* in: string2 */
-{
- for (;;) {
- int c1, c2;
- if (!*str1) {
- return(*str2 ? -1 : 0);
- } else if (!*str2) {
- return 1;
- }
- c1 = tolower(*str1++);
- c2 = tolower(*str2++);
- if (c1 < c2) {
- return(-1);
- }
- if (c1 > c2) {
- return(1);
- }
- }
-
- return(0);
-}
diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c
index ef926e2f93d..6a67697169a 100644
--- a/libmysql/libmysql.c
+++ b/libmysql/libmysql.c
@@ -1516,6 +1516,16 @@ uint STDCALL mysql_thread_safe(void)
#endif
}
+
+my_bool STDCALL mysql_embedded(void)
+{
+#ifdef EMBEDDED_LIBRARY
+ return 1;
+#else
+ return 0;
+#endif
+}
+
/****************************************************************************
Some support functions
****************************************************************************/
@@ -1534,6 +1544,40 @@ void my_net_local_init(NET *net)
}
/*
+ This function is used to create HEX string that you
+ can use in a SQL statement in of the either ways:
+ INSERT INTO blob_column VALUES (0xAABBCC); (any MySQL version)
+ INSERT INTO blob_column VALUES (X'AABBCC'); (4.1 and higher)
+
+ The string in "from" is encoded to a HEX string.
+ The result is placed in "to" and a terminating null byte is appended.
+
+ The string pointed to by "from" must be "length" bytes long.
+ You must allocate the "to" buffer to be at least length*2+1 bytes long.
+ Each character needs two bytes, and you need room for the terminating
+ null byte. When mysql_hex_string() returns, the contents of "to" will
+ be a null-terminated string. The return value is the length of the
+ encoded string, not including the terminating null character.
+
+ The return value does not contain any leading 0x or a leading X' and
+ trailing '. The caller must supply whichever of those is desired.
+*/
+
+ulong mysql_hex_string(char *to, const char *from, ulong length)
+{
+ char *to0= to;
+ const char *end;
+
+ for (end= from + length; from < end; from++)
+ {
+ *to++= _dig_vec_upper[((unsigned char) *from) >> 4];
+ *to++= _dig_vec_upper[((unsigned char) *from) & 0x0F];
+ }
+ *to= '\0';
+ return (ulong) (to-to0);
+}
+
+/*
Add escape characters to a string (blob?) to make it suitable for a insert
to should at least have place for length*2+1 chars
Returns the length of the to string
@@ -3221,12 +3265,12 @@ static void read_binary_time(MYSQL_TIME *tm, uchar **pos)
tm->second_part= (length > 8) ? (ulong) sint4korr(to+8) : 0;
tm->year= tm->month= 0;
- tm->time_type= MYSQL_TIMESTAMP_TIME;
*pos+= length;
}
else
set_zero_time(tm);
+ tm->time_type= MYSQL_TIMESTAMP_TIME;
}
static void read_binary_datetime(MYSQL_TIME *tm, uchar **pos)
@@ -3251,12 +3295,12 @@ static void read_binary_datetime(MYSQL_TIME *tm, uchar **pos)
else
tm->hour= tm->minute= tm->second= 0;
tm->second_part= (length > 7) ? (ulong) sint4korr(to+7) : 0;
- tm->time_type= MYSQL_TIMESTAMP_DATETIME;
*pos+= length;
}
else
set_zero_time(tm);
+ tm->time_type= MYSQL_TIMESTAMP_DATETIME;
}
static void read_binary_date(MYSQL_TIME *tm, uchar **pos)
@@ -3273,12 +3317,12 @@ static void read_binary_date(MYSQL_TIME *tm, uchar **pos)
tm->hour= tm->minute= tm->second= 0;
tm->second_part= 0;
tm->neg= 0;
- tm->time_type= MYSQL_TIMESTAMP_DATE;
*pos+= length;
}
else
set_zero_time(tm);
+ tm->time_type= MYSQL_TIMESTAMP_DATE;
}
@@ -3556,28 +3600,8 @@ static void fetch_datetime_with_conversion(MYSQL_BIND *param,
Convert time value to string and delegate the rest to
fetch_string_with_conversion:
*/
- char buff[25];
- uint length;
-
- switch (time->time_type) {
- case MYSQL_TIMESTAMP_DATE:
- length= my_sprintf(buff,(buff, "%04d-%02d-%02d",
- time->year, time->month, time->day));
- break;
- case MYSQL_TIMESTAMP_DATETIME:
- length= my_sprintf(buff,(buff, "%04d-%02d-%02d %02d:%02d:%02d",
- time->year, time->month, time->day,
- time->hour, time->minute, time->second));
- break;
- case MYSQL_TIMESTAMP_TIME:
- length= my_sprintf(buff, (buff, "%02d:%02d:%02d",
- time->hour, time->minute, time->second));
- break;
- default:
- length= 0;
- buff[0]='\0';
- break;
- }
+ char buff[MAX_DATE_STRING_REP_LENGTH];
+ uint length= my_TIME_to_str(time, buff);
/* Resort to string conversion */
fetch_string_with_conversion(param, (char *)buff, length);
break;
diff --git a/libmysql/libmysql.def b/libmysql/libmysql.def
index 38ac9505e4b..bc91e90a41c 100644
--- a/libmysql/libmysql.def
+++ b/libmysql/libmysql.def
@@ -144,3 +144,4 @@ EXPORTS
mysql_rpl_probe
mysql_rpl_query_type
mysql_slave_query
+ mysql_embedded
diff --git a/libmysql/manager.c b/libmysql/manager.c
index f030eb17889..631bfa26cb2 100644
--- a/libmysql/manager.c
+++ b/libmysql/manager.c
@@ -237,7 +237,7 @@ int STDCALL mysql_manager_fetch_line(MYSQL_MANAGER* con, char* res_buf,
char* res_buf_end=res_buf+res_buf_size;
char* net_buf=(char*) con->net.read_pos, *net_buf_end;
int res_buf_shift=RES_BUF_SHIFT;
- uint num_bytes;
+ ulong num_bytes;
if (res_buf_size<RES_BUF_SHIFT)
{
diff --git a/myisam/myisam_ftdump.c b/myisam/myisam_ftdump.c
index 8219c19848a..54b2cc77965 100644
--- a/myisam/myisam_ftdump.c
+++ b/myisam/myisam_ftdump.c
@@ -68,7 +68,7 @@ int main(int argc,char *argv[])
struct { MI_INFO *info; } aio0, *aio=&aio0; /* for GWS_IN_USE */
MY_INIT(argv[0]);
- if (error=handle_options(&argc, &argv, my_long_options, get_one_option))
+ if ((error= handle_options(&argc, &argv, my_long_options, get_one_option)))
exit(error);
if (count || dump)
verbose=0;
diff --git a/myisam/myisamchk.c b/myisam/myisamchk.c
index 9a2fde8fb89..648e29e1e9e 100644
--- a/myisam/myisamchk.c
+++ b/myisam/myisamchk.c
@@ -1695,7 +1695,7 @@ err:
static my_bool not_killed= 0;
-volatile my_bool *killed_ptr(MI_CHECK *param)
+volatile my_bool *killed_ptr(MI_CHECK *param __attribute__((unused)))
{
return &not_killed; /* always NULL */
}
diff --git a/myisam/myisampack.c b/myisam/myisampack.c
index 0bbf2721cb3..b4b4169965d 100644
--- a/myisam/myisampack.c
+++ b/myisam/myisampack.c
@@ -111,6 +111,8 @@ typedef struct st_isam_mrg {
uint ref_length;
uint max_blob_length;
my_off_t records;
+ /* true if at least one source file has at least one disabled index */
+ my_bool src_file_has_indexes_disabled;
} PACK_MRG_INFO;
@@ -413,10 +415,15 @@ static bool open_isam_files(PACK_MRG_INFO *mrg,char **names,uint count)
mrg->current=0;
mrg->file=(MI_INFO**) my_malloc(sizeof(MI_INFO*)*count,MYF(MY_FAE));
mrg->free_file=1;
+ mrg->src_file_has_indexes_disabled= 0;
for (i=0; i < count ; i++)
{
if (!(mrg->file[i]=open_isam_file(names[i],O_RDONLY)))
goto error;
+
+ mrg->src_file_has_indexes_disabled|= ((mrg->file[i]->s->state.key_map !=
+ (((ulonglong) 1) <<
+ mrg->file[i]->s->base. keys) - 1));
}
/* Check that files are identical */
for (j=0 ; j < count-1 ; j++)
@@ -2043,12 +2050,21 @@ static int save_state(MI_INFO *isam_file,PACK_MRG_INFO *mrg,my_off_t new_length,
share->state.dellink= HA_OFFSET_ERROR;
share->state.split=(ha_rows) mrg->records;
share->state.version=(ulong) time((time_t*) 0);
- share->state.key_map=0;
+ if (share->state.key_map != (1ULL << share->base.keys) - 1)
+ {
+ /*
+ Some indexes are disabled, cannot use current key_file_length value
+ as an estimate of upper bound of index file size. Use packed data file
+ size instead.
+ */
+ share->state.state.key_file_length= new_length;
+ }
/*
- Don't save key_file_length here, keep key_file_length of original file
- so "myisamchk -rq" can use this value (this is necessary because index
- size cannot be easily calculated for fulltext keys)
+ If there are no disabled indexes, keep key_file_length value from
+ original file so "myisamchk -rq" can use this value (this is necessary
+ because index size cannot be easily calculated for fulltext keys)
*/
+ share->state.key_map=0;
for (key=0 ; key < share->base.keys ; key++)
share->state.key_root[key]= HA_OFFSET_ERROR;
for (key=0 ; key < share->state.header.max_block_size ; key++)
@@ -2057,8 +2073,7 @@ static int save_state(MI_INFO *isam_file,PACK_MRG_INFO *mrg,my_off_t new_length,
share->changed=1; /* Force write of header */
share->state.open_count=0;
share->global_changed=0;
- VOID(my_chsize(share->kfile, share->state.state.key_file_length, 0,
- MYF(0)));
+ VOID(my_chsize(share->kfile, share->base.keystart, 0, MYF(0)));
if (share->base.keys)
isamchk_neaded=1;
DBUG_RETURN(mi_state_info_write(share->kfile,&share->state,1+2));
@@ -2081,7 +2096,12 @@ static int save_state_mrg(File file,PACK_MRG_INFO *mrg,my_off_t new_length,
state.state.del=0;
state.state.empty=0;
state.state.records=state.split=(ha_rows) mrg->records;
- state.state.key_file_length=isam_file->s->base.keystart;
+ /* See comment above in save_state about key_file_length handling. */
+ if (mrg->src_file_has_indexes_disabled)
+ {
+ isam_file->s->state.state.key_file_length=
+ max(isam_file->s->state.state.key_file_length, new_length);
+ }
state.dellink= HA_OFFSET_ERROR;
state.version=(ulong) time((time_t*) 0);
state.key_map=0;
diff --git a/myisam/rt_test.c b/myisam/rt_test.c
index 5e883e223b3..4f04aa11fce 100644
--- a/myisam/rt_test.c
+++ b/myisam/rt_test.c
@@ -425,6 +425,7 @@ static void create_record1(char *record,uint rownr)
}
}
+#ifdef NOT_USED
static void create_record0(char *record,uint rownr)
{
@@ -447,6 +448,8 @@ static void create_record0(char *record,uint rownr)
}
}
+#endif
+
static void create_record(char *record,uint rownr)
{
int i;
diff --git a/mysql-test/ndb/ndb_range_bounds.pl b/mysql-test/ndb/ndb_range_bounds.pl
new file mode 100644
index 00000000000..75b7f8a33e1
--- /dev/null
+++ b/mysql-test/ndb/ndb_range_bounds.pl
@@ -0,0 +1,138 @@
+#
+# test range scan bounds
+# output to mysql-test/t/ndb_range_bounds.test
+#
+# give option --all to generate all cases
+#
+
+use strict;
+use integer;
+use Getopt::Long;
+
+my $opt_all = 0;
+my $opt_cnt = 5;
+GetOptions("all" => \$opt_all, "cnt=i" => \$opt_cnt)
+ or die "options are: --all --cnt=N";
+
+my $table = 't';
+
+print <<EOF;
+--source include/have_ndb.inc
+
+--disable_warnings
+drop table if exists $table;
+--enable_warnings
+
+# test range scan bounds
+# generated by mysql-test/ndb/ndb_range_bounds.pl
+# all selects must return 0
+
+EOF
+
+sub cut ($$@) {
+ my($op, $key, @v) = @_;
+ $op = '==' if $op eq '=';
+ my(@w);
+ eval "\@w = grep(\$_ $op $key, \@v)";
+ $@ and die $@;
+ return @w;
+}
+
+sub mkdummy (\@) {
+ my ($val) = @_;
+ return {
+ 'dummy' => 1,
+ 'exp' => '9 = 9',
+ 'cnt' => scalar @$val,
+ };
+}
+
+sub mkone ($$$\@) {
+ my($col, $op, $key, $val) = @_;
+ my $cnt = scalar cut($op, $key, @$val);
+ return {
+ 'exp' => "$col $op $key",
+ 'cnt' => $cnt,
+ };
+}
+
+sub mktwo ($$$$$\@) {
+ my($col, $op1, $key1, $op2, $key2, $val) = @_;
+ my $cnt = scalar cut($op2, $key2, cut($op1, $key1, @$val));
+ return {
+ 'exp' => "$col $op1 $key1 and $col $op2 $key2",
+ 'cnt' => $cnt,
+ };
+}
+
+sub mkall ($$$\@) {
+ my($col, $key1, $key2, $val) = @_;
+ my @a = ();
+ my $p = mkdummy(@$val);
+ push(@a, $p) if $opt_all;
+ my @ops = qw(< <= = >= >);
+ for my $op (@ops) {
+ my $p = mkone($col, $op, $key1, @$val);
+ push(@a, $p) if $opt_all || $p->{cnt} != 0;
+ }
+ my @ops1 = $opt_all ? @ops : qw(= >= >);
+ my @ops2 = $opt_all ? @ops : qw(<= <);
+ for my $op1 (@ops1) {
+ for my $op2 (@ops2) {
+ my $p = mktwo($col, $op1, $key1, $op2, $key2, @$val);
+ push(@a, $p) if $opt_all || $p->{cnt} != 0;
+ }
+ }
+ return \@a;
+}
+
+for my $nn ("bcd", "") {
+ my %nn;
+ for my $x (qw(b c d)) {
+ $nn{$x} = $nn =~ /$x/ ? "not null" : "null";
+ }
+ print <<EOF;
+create table $table (
+ a int primary key,
+ b int $nn{b},
+ c int $nn{c},
+ d int $nn{d},
+ index (b, c, d)
+) engine=ndb;
+EOF
+ my @val = (0..($opt_cnt-1));
+ my $v0 = 0;
+ for my $v1 (@val) {
+ for my $v2 (@val) {
+ for my $v3 (@val) {
+ print "insert into $table values($v0, $v1, $v2, $v3);\n";
+ $v0++;
+ }
+ }
+ }
+ my $key1 = 1;
+ my $key2 = 3;
+ my $a1 = mkall('b', $key1, $key2, @val);
+ my $a2 = mkall('c', $key1, $key2, @val);
+ my $a3 = mkall('d', $key1, $key2, @val);
+ for my $p1 (@$a1) {
+ my $cnt1 = $p1->{cnt} * @val * @val;
+ print "select count(*) - $cnt1 from $table";
+ print " where $p1->{exp};\n";
+ for my $p2 (@$a2) {
+ my $cnt2 = $p1->{cnt} * $p2->{cnt} * @val;
+ print "select count(*) - $cnt2 from $table";
+ print " where $p1->{exp} and $p2->{exp};\n";
+ for my $p3 (@$a3) {
+ my $cnt3 = $p1->{cnt} * $p2->{cnt} * $p3->{cnt};
+ print "select count(*) - $cnt3 from $table";
+ print " where $p1->{exp} and $p2->{exp} and $p3->{exp};\n";
+ }
+ }
+ }
+ print <<EOF;
+drop table $table;
+EOF
+}
+
+# vim: set sw=2:
diff --git a/mysql-test/ndb/ndbcluster.sh b/mysql-test/ndb/ndbcluster.sh
index 7485e42923e..294d32ac4be 100644
--- a/mysql-test/ndb/ndbcluster.sh
+++ b/mysql-test/ndb/ndbcluster.sh
@@ -205,7 +205,7 @@ if [ -f "$fs_ndb/$pidfile" ] ; then
fi
done
kill_pids=$new_kill_pid
- if [ "$kill_pids" == "" ] ; then
+ if [ -z "$kill_pids" ] ; then
break
fi
sleep 1
diff --git a/mysql-test/r/ctype_sjis.result b/mysql-test/r/ctype_sjis.result
index 1e3e28784a5..26a45dd28e8 100644
--- a/mysql-test/r/ctype_sjis.result
+++ b/mysql-test/r/ctype_sjis.result
@@ -41,3 +41,9 @@ C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF
select hex(CONVERT(@utf84 USING sjis));
hex(CONVERT(@utf84 USING sjis))
D0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF
+create table t1 (a char(10) character set sjis);
+insert into t1 values (0x878A);
+select hex(a) from t1;
+hex(a)
+878A
+drop table t1;
diff --git a/mysql-test/r/ctype_uca.result b/mysql-test/r/ctype_uca.result
index 7e4a03e96cc..90681795513 100644
--- a/mysql-test/r/ctype_uca.result
+++ b/mysql-test/r/ctype_uca.result
@@ -1,5 +1,35 @@
DROP TABLE IF EXISTS t1;
set names utf8;
+set collation_connection=utf8_unicode_ci;
+select 'a' = 'a', 'a' = 'a ', 'a ' = 'a';
+'a' = 'a' 'a' = 'a ' 'a ' = 'a'
+1 1 1
+select 'a\t' = 'a' , 'a\t' < 'a' , 'a\t' > 'a';
+'a\t' = 'a' 'a\t' < 'a' 'a\t' > 'a'
+0 1 0
+select 'a\t' = 'a ', 'a\t' < 'a ', 'a\t' > 'a ';
+'a\t' = 'a ' 'a\t' < 'a ' 'a\t' > 'a '
+0 1 0
+select 'a' = 'a\t', 'a' < 'a\t', 'a' > 'a\t';
+'a' = 'a\t' 'a' < 'a\t' 'a' > 'a\t'
+0 0 1
+select 'a ' = 'a\t', 'a ' < 'a\t', 'a ' > 'a\t';
+'a ' = 'a\t' 'a ' < 'a\t' 'a ' > 'a\t'
+0 0 1
+select 'a a' > 'a', 'a \t' < 'a';
+'a a' > 'a' 'a \t' < 'a'
+1 1
+CREATE TABLE t (
+c char(20) NOT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
+INSERT INTO t VALUES ('a'),('ab'),('aba');
+ALTER TABLE t ADD INDEX (c);
+SELECT c FROM t WHERE c LIKE 'a%';
+c
+a
+ab
+aba
+DROP TABLE t;
create table t1 (c1 char(10) character set utf8 collate utf8_bin);
insert into t1 values ('A'),('a');
insert into t1 values ('B'),('b');
diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result
index 2e8bbc8fa92..e65eb96cb68 100644
--- a/mysql-test/r/ctype_utf8.result
+++ b/mysql-test/r/ctype_utf8.result
@@ -63,6 +63,15 @@ select 'A' like 'a' collate utf8_bin;
select _utf8 0xD0B0D0B1D0B2 like concat(_utf8'%',_utf8 0xD0B1,_utf8 '%');
_utf8 0xD0B0D0B1D0B2 like concat(_utf8'%',_utf8 0xD0B1,_utf8 '%')
1
+select convert(_latin1'Günter André' using utf8) like CONVERT(_latin1'GÜNTER%' USING utf8);
+convert(_latin1'Günter André' using utf8) like CONVERT(_latin1'GÜNTER%' USING utf8)
+1
+select CONVERT(_koi8r'×ÁÓÑ' USING utf8) LIKE CONVERT(_koi8r'÷áóñ' USING utf8);
+CONVERT(_koi8r'×ÁÓÑ' USING utf8) LIKE CONVERT(_koi8r'÷áóñ' USING utf8)
+1
+select CONVERT(_koi8r'÷áóñ' USING utf8) LIKE CONVERT(_koi8r'×ÁÓÑ' USING utf8);
+CONVERT(_koi8r'÷áóñ' USING utf8) LIKE CONVERT(_koi8r'×ÁÓÑ' USING utf8)
+1
SELECT 'a' = 'a ';
'a' = 'a '
1
diff --git a/mysql-test/r/func_test.result b/mysql-test/r/func_test.result
index c3fe1de15db..8a28312b348 100644
--- a/mysql-test/r/func_test.result
+++ b/mysql-test/r/func_test.result
@@ -174,3 +174,12 @@ SELECT GREATEST(d,d) FROM t1 WHERE k=2;
GREATEST(d,d)
NULL
DROP TABLE t1;
+select 1197.90 mod 50;
+1197.90 mod 50
+47.90
+select 5.1 mod 3, 5.1 mod -3, -5.1 mod 3, -5.1 mod -3;
+5.1 mod 3 5.1 mod -3 -5.1 mod 3 -5.1 mod -3
+2.1 2.1 -2.1 -2.1
+select 5 mod 3, 5 mod -3, -5 mod 3, -5 mod -3;
+5 mod 3 5 mod -3 -5 mod 3 -5 mod -3
+2 2 -2 -2
diff --git a/mysql-test/r/grant2.result b/mysql-test/r/grant2.result
index 31e506d2679..a31fa2ac3dc 100644
--- a/mysql-test/r/grant2.result
+++ b/mysql-test/r/grant2.result
@@ -1,6 +1,9 @@
SET NAMES binary;
+drop database if exists mysqltest;
delete from mysql.user where user like 'mysqltest\_%';
delete from mysql.db where user like 'mysqltest\_%';
+delete from mysql.tables_priv where user like 'mysqltest\_%';
+delete from mysql.columns_priv where user like 'mysqltest\_%';
flush privileges;
grant all privileges on `my\_%`.* to mysqltest_1@localhost with grant option;
select current_user();
@@ -25,3 +28,27 @@ ERROR 42000: There is no such grant defined for user 'mysqltest_3' on host 'loca
delete from mysql.user where user like 'mysqltest\_%';
delete from mysql.db where user like 'mysqltest\_%';
flush privileges;
+create database mysqltest;
+grant INSERT, SELECT on mysqltest.* to mysqltest_1@localhost;
+flush privileges;
+use mysqltest;
+create table t1 (id int primary key, data varchar(255));
+show grants for current_user();
+Grants for mysqltest_1@localhost
+GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost'
+GRANT SELECT, INSERT ON `mysqltest`.* TO 'mysqltest_1'@'localhost'
+use mysqltest;
+insert into t1 values (1, 'I can''t change it!');
+update t1 set data='I can change it!' where id = 1;
+ERROR 42000: Access denied for user 'mysqltest_1'@'localhost' to database 'mysqltest'
+insert into t1 values (1, 'XXX') on duplicate key update data= 'I can change it!';
+ERROR 42000: Access denied for user 'mysqltest_1'@'localhost' to database 'mysqltest'
+select * from t1;
+id data
+1 I can't change it!
+drop table t1;
+drop database mysqltest;
+use test;
+delete from mysql.user where user like 'mysqltest\_%';
+delete from mysql.db where user like 'mysqltest\_%';
+flush privileges;
diff --git a/mysql-test/r/innodb-lock.result b/mysql-test/r/innodb-lock.result
index cf00adb30ae..407a85ed038 100644
--- a/mysql-test/r/innodb-lock.result
+++ b/mysql-test/r/innodb-lock.result
@@ -1,4 +1,8 @@
+select @@innodb_table_locks;
+@@innodb_table_locks
+1
drop table if exists t1;
+set @@innodb_table_locks=1;
create table t1 (id integer, x integer) engine=INNODB;
insert into t1 values(0, 0);
set autocommit=0;
@@ -20,3 +24,33 @@ id x
0 2
commit;
drop table t1;
+set @@innodb_table_locks=0;
+create table t1 (id integer primary key, x integer) engine=INNODB;
+insert into t1 values(0, 0),(1,1),(2,2);
+commit;
+SELECT * from t1 where id = 0 FOR UPDATE;
+id x
+0 0
+set autocommit=0;
+set @@innodb_table_locks=0;
+lock table t1 write;
+update t1 set x=10 where id = 2;
+SELECT * from t1 where id = 2;
+id x
+2 2
+UPDATE t1 set x=3 where id = 2;
+commit;
+SELECT * from t1;
+id x
+0 0
+1 1
+2 3
+commit;
+unlock tables;
+commit;
+select * from t1;
+id x
+0 0
+1 1
+2 10
+drop table t1;
diff --git a/mysql-test/r/mysqltest.result b/mysql-test/r/mysqltest.result
new file mode 100644
index 00000000000..4e30d5bc110
--- /dev/null
+++ b/mysql-test/r/mysqltest.result
@@ -0,0 +1,23 @@
+select otto from (select 1 as otto) as t1;
+otto
+1
+select otto from (select 1 as otto) as t1;
+otto
+1
+select otto from (select 1 as otto) as t1;
+otto
+1
+select friedrich from (select 1 as otto) as t1;
+ERROR 42S22: Unknown column 'friedrich' in 'field list'
+select friedrich from (select 1 as otto) as t1;
+ERROR 42S22: Unknown column 'friedrich' in 'field list'
+select otto from (select 1 as otto) as t1;
+otto
+1
+select otto from (select 1 as otto) as t1;
+otto
+1
+select friedrich from (select 1 as otto) as t1;
+ERROR 42S22: Unknown column 'friedrich' in 'field list'
+select friedrich from (select 1 as otto) as t1;
+ERROR 42S22: Unknown column 'friedrich' in 'field list'
diff --git a/mysql-test/r/ndb_basic.result b/mysql-test/r/ndb_basic.result
index 9f8dcf3610a..abe1b98b536 100644
--- a/mysql-test/r/ndb_basic.result
+++ b/mysql-test/r/ndb_basic.result
@@ -395,3 +395,22 @@ b attr1
9413 9412
drop table test.t1, t2;
drop database mysqltest;
+use test;
+create table t1 (a int primary key, b char(0));
+insert into t1 values (1,"");
+insert into t1 values (2,NULL);
+select * from t1 order by a;
+a b
+1
+2 NULL
+select * from t1 order by b;
+a b
+2 NULL
+1
+select * from t1 where b IS NULL;
+a b
+2 NULL
+select * from t1 where b IS NOT NULL;
+a b
+1
+drop table t1;
diff --git a/mysql-test/r/ndb_index_ordered.result b/mysql-test/r/ndb_index_ordered.result
index 2a3050e5dea..2dc260ec43d 100644
--- a/mysql-test/r/ndb_index_ordered.result
+++ b/mysql-test/r/ndb_index_ordered.result
@@ -37,6 +37,24 @@ a b c
1 2 3
2 3 5
3 4 6
+select tt1.* from t1 as tt1, t1 as tt2 use index(b) where tt1.b = tt2.b order by tt1.b;
+a b c
+1 2 3
+2 3 5
+3 4 6
+4 5 8
+5 6 2
+6 7 2
+select a, b, c from t1 where a!=2 and c=6;
+a b c
+3 4 6
+select a, b, c from t1 where a!=2 order by a;
+a b c
+1 2 3
+3 4 6
+4 5 8
+5 6 2
+6 7 2
update t1 set c = 3 where b = 3;
select * from t1 order by a;
a b c
diff --git a/mysql-test/r/ndb_lock.result b/mysql-test/r/ndb_lock.result
index 56661913e22..b8c2c58aac4 100644
--- a/mysql-test/r/ndb_lock.result
+++ b/mysql-test/r/ndb_lock.result
@@ -28,3 +28,38 @@ x y
2 two
3 three
commit;
+drop table t1;
+create table t1 (pk integer not null primary key, u int not null, o int not null,
+unique(u), key(o)) engine = ndb;
+insert into t1 values (1,1,1), (2,2,2), (3,3,3), (4,4,4), (5,5,5);
+lock tables t1 write;
+delete from t1 where pk = 1;
+unlock tables;
+select * from t1 order by pk;
+pk u o
+2 2 2
+3 3 3
+4 4 4
+5 5 5
+insert into t1 values (1,1,1);
+lock tables t1 write;
+delete from t1 where u = 1;
+unlock tables;
+select * from t1 order by pk;
+pk u o
+2 2 2
+3 3 3
+4 4 4
+5 5 5
+insert into t1 values (1,1,1);
+lock tables t1 write;
+delete from t1 where o = 1;
+unlock tables;
+select * from t1 order by pk;
+pk u o
+2 2 2
+3 3 3
+4 4 4
+5 5 5
+insert into t1 values (1,1,1);
+drop table t1;
diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result
index 0aba0c4672e..0950a066e64 100644
--- a/mysql-test/r/ps.result
+++ b/mysql-test/r/ps.result
@@ -375,3 +375,38 @@ rand() cast(rand(10)*@precision as unsigned integer) cast(rand(a)*@precision as
- 9647622201 3845601374 6211931236
drop table t1;
deallocate prepare stmt;
+create database mysqltest1;
+create table t1 (a int);
+create table mysqltest1.t1 (a int);
+select * from t1, mysqltest1.t1;
+a a
+prepare stmt from "select * from t1, mysqltest1.t1";
+execute stmt;
+a a
+execute stmt;
+a a
+execute stmt;
+a a
+drop table t1;
+drop table mysqltest1.t1;
+drop database mysqltest1;
+deallocate prepare stmt;
+select '1.1' as a, '1.2' as a UNION SELECT '2.1', '2.2';
+a a
+1.1 1.2
+2.1 2.2
+prepare stmt from
+"select '1.1' as a, '1.2' as a UNION SELECT '2.1', '2.2'";
+execute stmt;
+a a
+1.1 1.2
+2.1 2.2
+execute stmt;
+a a
+1.1 1.2
+2.1 2.2
+execute stmt;
+a a
+1.1 1.2
+2.1 2.2
+deallocate prepare stmt;
diff --git a/mysql-test/r/ps_10nestset.result b/mysql-test/r/ps_10nestset.result
index 10f0a741b54..68f58a03674 100644
--- a/mysql-test/r/ps_10nestset.result
+++ b/mysql-test/r/ps_10nestset.result
@@ -1,14 +1,11 @@
-use test;
-drop table if exists personnel;
-Warnings:
-Note 1051 Unknown table 'personnel'
-create table personnel (
+drop table if exists t1;
+create table t1 (
id INTEGER AUTO_INCREMENT PRIMARY KEY,
emp CHAR(10) NOT NULL,
salary DECIMAL(6,2) NOT NULL,
l INTEGER NOT NULL,
r INTEGER NOT NULL);
-prepare st_ins from 'insert into personnel set emp = ?, salary = ?, l = ?, r = ?';
+prepare st_ins from 'insert into t1 set emp = ?, salary = ?, l = ?, r = ?';
set @arg_nam= 'Jerry';
set @arg_sal= 1000;
set @arg_l= 1;
@@ -39,7 +36,7 @@ set @arg_sal= 600;
set @arg_l= 9;
set @arg_r= 10;
execute st_ins using @arg_nam, @arg_sal, @arg_l, @arg_r ;
-select * from personnel;
+select * from t1;
id emp salary l r
1 Jerry 1000.00 1 12
2 Bert 900.00 2 3
@@ -47,8 +44,8 @@ id emp salary l r
4 Donna 800.00 5 6
5 Eddie 700.00 7 8
6 Fred 600.00 9 10
-prepare st_raise_base from 'update personnel set salary = salary * ( 1 + ? ) where r - l = 1';
-prepare st_raise_mgr from 'update personnel set salary = salary + ? where r - l > 1';
+prepare st_raise_base from 'update t1 set salary = salary * ( 1 + ? ) where r - l = 1';
+prepare st_raise_mgr from 'update t1 set salary = salary + ? where r - l > 1';
set @arg_percent= .10;
set @arg_amount= 100;
execute st_raise_base using @arg_percent;
@@ -57,7 +54,7 @@ execute st_raise_base using @arg_percent;
execute st_raise_mgr using @arg_amount;
execute st_raise_base using @arg_percent;
execute st_raise_mgr using @arg_amount;
-select * from personnel;
+select * from t1;
id emp salary l r
1 Jerry 1300.00 1 12
2 Bert 1197.90 2 3
@@ -65,4 +62,4 @@ id emp salary l r
4 Donna 1064.80 5 6
5 Eddie 931.70 7 8
6 Fred 798.60 9 10
-drop table personnel;
+drop table t1;
diff --git a/mysql-test/r/ps_1general.result b/mysql-test/r/ps_1general.result
index 6dcdb0feab1..ccf2945d488 100644
--- a/mysql-test/r/ps_1general.result
+++ b/mysql-test/r/ps_1general.result
@@ -184,7 +184,7 @@ f3 int
);
insert into t5( f1, f2, f3) values( 9, 'recreated table', 9);
execute stmt2 ;
-ERROR 42S22: Unknown column 't5.a' in 'field list'
+ERROR 42S22: Unknown column 'test.t5.a' in 'field list'
drop table t5 ;
prepare stmt1 from ' select * from t1 where a <= 2 ' ;
execute stmt1 ;
diff --git a/mysql-test/r/rpl_commit_after_flush.result b/mysql-test/r/rpl_commit_after_flush.result
new file mode 100644
index 00000000000..d3aba779219
--- /dev/null
+++ b/mysql-test/r/rpl_commit_after_flush.result
@@ -0,0 +1,13 @@
+stop slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+start slave;
+create table t1 (a int) engine=innodb;
+begin;
+insert into t1 values(1);
+flush tables with read lock;
+commit;
+unlock tables;
+drop table t1;
diff --git a/mysql-test/r/union.result b/mysql-test/r/union.result
index fbd4f8e11dc..7820cd1d6ff 100644
--- a/mysql-test/r/union.result
+++ b/mysql-test/r/union.result
@@ -1033,3 +1033,81 @@ a
No
aaa,bbb
drop table t1,t2,t3,t4;
+create table t1 as
+(select _latin1'test') union
+(select _latin1'TEST') union
+(select _latin1'TeST');
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `test` char(4) NOT NULL default ''
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+select count(*) from t1;
+count(*)
+1
+drop table t1;
+create table t1 as
+(select _latin1'test' collate latin1_bin) union
+(select _latin1'TEST') union
+(select _latin1'TeST');
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `_latin1'test' collate latin1_bin` char(4) character set latin1 collate latin1_bin NOT NULL default ''
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+select count(*) from t1;
+count(*)
+3
+drop table t1;
+create table t1 as
+(select _latin1'test') union
+(select _latin1'TEST' collate latin1_bin) union
+(select _latin1'TeST');
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `test` char(4) character set latin1 collate latin1_bin NOT NULL default ''
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+select count(*) from t1;
+count(*)
+3
+drop table t1;
+create table t1 as
+(select _latin1'test') union
+(select _latin1'TEST') union
+(select _latin1'TeST' collate latin1_bin);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `test` char(4) character set latin1 collate latin1_bin NOT NULL default ''
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+select count(*) from t1;
+count(*)
+3
+drop table t1;
+create table t2 (
+a char character set latin1 collate latin1_swedish_ci,
+b char character set latin1 collate latin1_bin);
+create table t1 as
+(select a from t2) union
+(select b from t2);
+ERROR HY000: Illegal mix of collations for operation 'UNION'
+create table t1 as
+(select a collate latin1_german1_ci from t2) union
+(select b from t2);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a collate latin1_german1_ci` char(1) character set latin1 collate latin1_german1_ci default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+create table t1 as
+(select a from t2) union
+(select b collate latin1_german1_ci from t2);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` char(1) character set latin1 collate latin1_german1_ci default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+drop table t2;
diff --git a/mysql-test/t/ctype_sjis.test b/mysql-test/t/ctype_sjis.test
index 1dd363c4910..68f4f7010e0 100644
--- a/mysql-test/t/ctype_sjis.test
+++ b/mysql-test/t/ctype_sjis.test
@@ -32,3 +32,12 @@ select hex(CONVERT(@utf81 USING sjis));
select hex(CONVERT(@utf82 USING sjis));
select hex(CONVERT(@utf83 USING sjis));
select hex(CONVERT(@utf84 USING sjis));
+
+#
+# Allow to insert extra CP932 characters
+# into a SJIS column
+#
+create table t1 (a char(10) character set sjis);
+insert into t1 values (0x878A);
+select hex(a) from t1;
+drop table t1;
diff --git a/mysql-test/t/ctype_uca.test b/mysql-test/t/ctype_uca.test
index cbb2bd7ba4b..708a31d637e 100644
--- a/mysql-test/t/ctype_uca.test
+++ b/mysql-test/t/ctype_uca.test
@@ -7,8 +7,35 @@ DROP TABLE IF EXISTS t1;
#
# Test Unicode collations.
#
-
set names utf8;
+
+#
+# Check trailing spaces
+#
+set collation_connection=utf8_unicode_ci;
+
+select 'a' = 'a', 'a' = 'a ', 'a ' = 'a';
+
+select 'a\t' = 'a' , 'a\t' < 'a' , 'a\t' > 'a';
+select 'a\t' = 'a ', 'a\t' < 'a ', 'a\t' > 'a ';
+
+select 'a' = 'a\t', 'a' < 'a\t', 'a' > 'a\t';
+select 'a ' = 'a\t', 'a ' < 'a\t', 'a ' > 'a\t';
+
+select 'a a' > 'a', 'a \t' < 'a';
+
+#
+# Bug #5679 utf8_unicode_ci LIKE--trailing % doesn't equal zero characters
+#
+CREATE TABLE t (
+ c char(20) NOT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
+INSERT INTO t VALUES ('a'),('ab'),('aba');
+ALTER TABLE t ADD INDEX (c);
+SELECT c FROM t WHERE c LIKE 'a%';
+#should find 3 rows but only found 2
+DROP TABLE t;
+
create table t1 (c1 char(10) character set utf8 collate utf8_bin);
#
diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test
index fc6eb88ad68..238cd6daef3 100644
--- a/mysql-test/t/ctype_utf8.test
+++ b/mysql-test/t/ctype_utf8.test
@@ -33,6 +33,14 @@ select 'A' like 'a';
select 'A' like 'a' collate utf8_bin;
select _utf8 0xD0B0D0B1D0B2 like concat(_utf8'%',_utf8 0xD0B1,_utf8 '%');
+# Bug #6040: can't retrieve records with umlaut
+# characters in case insensitive manner.
+# Case insensitive search LIKE comparison
+# was broken for multibyte characters:
+select convert(_latin1'Günter André' using utf8) like CONVERT(_latin1'GÜNTER%' USING utf8);
+select CONVERT(_koi8r'×ÁÓÑ' USING utf8) LIKE CONVERT(_koi8r'÷áóñ' USING utf8);
+select CONVERT(_koi8r'÷áóñ' USING utf8) LIKE CONVERT(_koi8r'×ÁÓÑ' USING utf8);
+
#
# Check the following:
# "a" == "a "
@@ -568,6 +576,7 @@ DROP TABLE t1;
#
# Bug #5723: length(<varchar utf8 field>) returns varying results
#
+--disable_warnings
SET NAMES utf8;
--disable_warnings
CREATE TABLE t1 (
diff --git a/mysql-test/t/func_test.test b/mysql-test/t/func_test.test
index e7bcd81a15e..eb506a58870 100644
--- a/mysql-test/t/func_test.test
+++ b/mysql-test/t/func_test.test
@@ -94,3 +94,16 @@ CREATE TABLE t1 (d varchar(6), k int);
INSERT INTO t1 VALUES (NULL, 2);
SELECT GREATEST(d,d) FROM t1 WHERE k=2;
DROP TABLE t1;
+
+#
+# Bug #6138: mod and doubles
+#
+
+select 1197.90 mod 50;
+select 5.1 mod 3, 5.1 mod -3, -5.1 mod 3, -5.1 mod -3;
+
+#
+# Test for mod and signed integers
+#
+
+select 5 mod 3, 5 mod -3, -5 mod 3, -5 mod -3;
diff --git a/mysql-test/t/grant2.test b/mysql-test/t/grant2.test
index 3a9afa7453b..f86be0c95b9 100644
--- a/mysql-test/t/grant2.test
+++ b/mysql-test/t/grant2.test
@@ -6,13 +6,21 @@ SET NAMES binary;
#
+# prepare playground before tests
+--disable_warnings
+drop database if exists mysqltest;
+--enable_warnings
+delete from mysql.user where user like 'mysqltest\_%';
+delete from mysql.db where user like 'mysqltest\_%';
+delete from mysql.tables_priv where user like 'mysqltest\_%';
+delete from mysql.columns_priv where user like 'mysqltest\_%';
+flush privileges;
+
+
#
# wild_compare fun
#
-delete from mysql.user where user like 'mysqltest\_%';
-delete from mysql.db where user like 'mysqltest\_%';
-flush privileges;
grant all privileges on `my\_%`.* to mysqltest_1@localhost with grant option;
connect (user1,localhost,mysqltest_1,,);
connection user1;
@@ -31,3 +39,33 @@ delete from mysql.user where user like 'mysqltest\_%';
delete from mysql.db where user like 'mysqltest\_%';
flush privileges;
+
+#
+# Bug #6173: One can circumvent missing UPDATE privilege if he has SELECT
+# and INSERT privilege for table with primary key
+#
+create database mysqltest;
+grant INSERT, SELECT on mysqltest.* to mysqltest_1@localhost;
+flush privileges;
+use mysqltest;
+create table t1 (id int primary key, data varchar(255));
+
+connect (mrbad, localhost, mysqltest_1,,);
+connection mrbad;
+show grants for current_user();
+use mysqltest;
+insert into t1 values (1, 'I can''t change it!');
+--error 1044
+update t1 set data='I can change it!' where id = 1;
+# This should not be allowed since it too require UPDATE privilege.
+--error 1044
+insert into t1 values (1, 'XXX') on duplicate key update data= 'I can change it!';
+select * from t1;
+
+connection default;
+drop table t1;
+drop database mysqltest;
+use test;
+delete from mysql.user where user like 'mysqltest\_%';
+delete from mysql.db where user like 'mysqltest\_%';
+flush privileges;
diff --git a/mysql-test/t/innodb-lock-master.opt b/mysql-test/t/innodb-lock-master.opt
new file mode 100644
index 00000000000..403fcde87ed
--- /dev/null
+++ b/mysql-test/t/innodb-lock-master.opt
@@ -0,0 +1 @@
+--innodb-table-lock=1
diff --git a/mysql-test/t/innodb-lock.test b/mysql-test/t/innodb-lock.test
index 33baec32549..2bbbac82ad5 100644
--- a/mysql-test/t/innodb-lock.test
+++ b/mysql-test/t/innodb-lock.test
@@ -1,5 +1,15 @@
-- source include/have_innodb.inc
+#
+# Check and select innodb lock type
+#
+
+select @@innodb_table_locks;
+
+#
+# Testing of explicit table locks with enforced table locks
+#
+
connect (con1,localhost,root,,);
connect (con2,localhost,root,,);
@@ -8,9 +18,11 @@ drop table if exists t1;
--enable_warnings
#
-# Testing of explicit table locks
+# Testing of explicit table locks with enforced table locks
#
+set @@innodb_table_locks=1;
+
connection con1;
create table t1 (id integer, x integer) engine=INNODB;
insert into t1 values(0, 0);
@@ -41,3 +53,46 @@ select * from t1;
commit;
drop table t1;
+
+#
+# Try with old lock method (where LOCK TABLE is ignored by InnoDB)
+#
+
+set @@innodb_table_locks=0;
+
+create table t1 (id integer primary key, x integer) engine=INNODB;
+insert into t1 values(0, 0),(1,1),(2,2);
+commit;
+SELECT * from t1 where id = 0 FOR UPDATE;
+
+connection con2;
+set autocommit=0;
+set @@innodb_table_locks=0;
+
+# The following statement should work becase innodb doesn't check table locks
+lock table t1 write;
+
+connection con1;
+
+# This will be locked by MySQL
+--send
+update t1 set x=10 where id = 2;
+--sleep 2
+
+connection con2;
+
+# Note that we will get a deadlock if we try to select any rows marked
+# for update by con1 !
+
+SELECT * from t1 where id = 2;
+UPDATE t1 set x=3 where id = 2;
+commit;
+SELECT * from t1;
+commit;
+unlock tables;
+
+connection con1;
+reap;
+commit;
+select * from t1;
+drop table t1;
diff --git a/mysql-test/t/mysqltest.test b/mysql-test/t/mysqltest.test
new file mode 100644
index 00000000000..c18dfe1e25c
--- /dev/null
+++ b/mysql-test/t/mysqltest.test
@@ -0,0 +1,78 @@
+
+# ============================================================================
+#
+# Test of mysqltest itself
+#
+# ============================================================================
+
+# ----------------------------------------------------------------------------
+# Positive case(statement)
+# ----------------------------------------------------------------------------
+
+select otto from (select 1 as otto) as t1;
+# expectation = response
+!$0 select otto from (select 1 as otto) as t1;
+--error 0
+select otto from (select 1 as otto) as t1;
+
+# expectation <> response
+-- // !$1054 select otto from (select 1 as otto) as t1;
+-- // --error 1054
+-- // select otto from (select 1 as otto) as t1;
+
+
+# ----------------------------------------------------------------------------
+# Negative case(statement):
+# The dervied table t1 does not contain a column named 'friedrich' .
+# --> ERROR 42S22: Unknown column 'friedrich' in 'field list and
+# --> 1054: Unknown column 'friedrich' in 'field list'
+# ----------------------------------------------------------------------------
+
+# expectation <> response
+#!$0 select friedrich from (select 1 as otto) as t1;
+#--error 0
+#select friedrich from (select 1 as otto) as t1;
+
+# expectation = response
+!$1054 select friedrich from (select 1 as otto) as t1;
+--error 1054
+select friedrich from (select 1 as otto) as t1;
+
+# The following unmasked unsuccessful statement must give
+# 1. mysqltest gives a 'failed'
+# 2. does not produce a r/<test case>.reject file !!!
+# PLEASE uncomment it and check it's effect
+#select friedrich from (select 1 as otto) as t1;
+
+
+# ----------------------------------------------------------------------------
+# Tests for the new feature - SQLSTATE error code matching
+# Positive case(statement)
+# ----------------------------------------------------------------------------
+
+# expectation = response
+!S00000 select otto from (select 1 as otto) as t1;
+
+--error S00000
+select otto from (select 1 as otto) as t1;
+
+# expectation <> response
+#!S42S22 select otto from (select 1 as otto) as t1;
+#--error S42S22
+#select otto from (select 1 as otto) as t1;
+
+
+# ----------------------------------------------------------------------------
+# Negative case(statement)
+# ----------------------------------------------------------------------------
+
+# expectation = response
+!S42S22 select friedrich from (select 1 as otto) as t1;
+--error S42S22
+select friedrich from (select 1 as otto) as t1;
+
+# expectation !=response
+#!S00000 select friedrich from (select 1 as otto) as t1;
+#--error S00000
+#select friedrich from (select 1 as otto) as t1;
+
diff --git a/mysql-test/t/ndb_basic.test b/mysql-test/t/ndb_basic.test
index 5f32a8016bf..e79815bbeb1 100644
--- a/mysql-test/t/ndb_basic.test
+++ b/mysql-test/t/ndb_basic.test
@@ -358,3 +358,16 @@ select b,test.t1.attr1 from test.t1, t2 where test.t1.pk1 < a;
drop table test.t1, t2;
drop database mysqltest;
+#
+# test support of char(0)
+#
+
+use test;
+create table t1 (a int primary key, b char(0));
+insert into t1 values (1,"");
+insert into t1 values (2,NULL);
+select * from t1 order by a;
+select * from t1 order by b;
+select * from t1 where b IS NULL;
+select * from t1 where b IS NOT NULL;
+drop table t1;
diff --git a/mysql-test/t/ndb_index_ordered.test b/mysql-test/t/ndb_index_ordered.test
index 2a94475df13..64291c8ab97 100644
--- a/mysql-test/t/ndb_index_ordered.test
+++ b/mysql-test/t/ndb_index_ordered.test
@@ -23,6 +23,11 @@ select * from t1 where b > 4 order by b;
select * from t1 where b < 4 order by b;
select * from t1 where b <= 4 order by b;
+# Test of reset_bounds
+select tt1.* from t1 as tt1, t1 as tt2 use index(b) where tt1.b = tt2.b order by tt1.b;
+select a, b, c from t1 where a!=2 and c=6;
+select a, b, c from t1 where a!=2 order by a;
+
#
# Here we should add some "explain select" to verify that the ordered index is
# used for these queries.
diff --git a/mysql-test/t/ndb_lock.test b/mysql-test/t/ndb_lock.test
index c0389dced44..39a8655b972 100644
--- a/mysql-test/t/ndb_lock.test
+++ b/mysql-test/t/ndb_lock.test
@@ -39,3 +39,32 @@ commit;
connection con2;
select * from t1 order by x;
commit;
+
+drop table t1;
+
+###
+# Bug#6020
+create table t1 (pk integer not null primary key, u int not null, o int not null,
+ unique(u), key(o)) engine = ndb;
+insert into t1 values (1,1,1), (2,2,2), (3,3,3), (4,4,4), (5,5,5);
+
+lock tables t1 write;
+delete from t1 where pk = 1;
+unlock tables;
+select * from t1 order by pk;
+insert into t1 values (1,1,1);
+
+lock tables t1 write;
+delete from t1 where u = 1;
+unlock tables;
+select * from t1 order by pk;
+insert into t1 values (1,1,1);
+
+lock tables t1 write;
+delete from t1 where o = 1;
+unlock tables;
+select * from t1 order by pk;
+insert into t1 values (1,1,1);
+
+drop table t1;
+
diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test
index 7cbcd50245f..04ab8aa62a8 100644
--- a/mysql-test/t/ps.test
+++ b/mysql-test/t/ps.test
@@ -390,3 +390,28 @@ set @var=3;
execute stmt using @var;
drop table t1;
deallocate prepare stmt;
+
+#
+# A test case for Bug#6050 "EXECUTE stmt reports ambiguous fieldnames with
+# identical tables from different schemata"
+# Check that field name resolving in prepared statements works OK.
+#
+create database mysqltest1;
+create table t1 (a int);
+create table mysqltest1.t1 (a int);
+select * from t1, mysqltest1.t1;
+prepare stmt from "select * from t1, mysqltest1.t1";
+execute stmt;
+execute stmt;
+execute stmt;
+drop table t1;
+drop table mysqltest1.t1;
+drop database mysqltest1;
+deallocate prepare stmt;
+select '1.1' as a, '1.2' as a UNION SELECT '2.1', '2.2';
+prepare stmt from
+"select '1.1' as a, '1.2' as a UNION SELECT '2.1', '2.2'";
+execute stmt;
+execute stmt;
+execute stmt;
+deallocate prepare stmt;
diff --git a/mysql-test/t/ps_10nestset.test b/mysql-test/t/ps_10nestset.test
index 2c6009af9de..d2adaca689e 100644
--- a/mysql-test/t/ps_10nestset.test
+++ b/mysql-test/t/ps_10nestset.test
@@ -8,28 +8,29 @@
# Source: http://kris.koehntopp.de/artikel/sql-self-references (dated 1999)
# Source: http://dbmsmag.com/9603d06.html (dated 1996)
-use test;
-
-drop table if exists personnel;
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
# "Nested Set": This table represents an employee list with a hierarchy tree.
# The tree is not modeled by "parent" links but rather by showing the "left"
# and "right" border of any person's "region". By convention, "l" < "r".
# As it is a tree, these "regions" of two persons A and B are either disjoint,
-# or A's region is completely contained in B's (B is A's boss), or vice versa.
-# See the references for more info.
+# or A's region is completely contained in B's (B.l < A.l < A.r < B.r:
+# B is A's boss), or vice versa.
+# Any other overlaps violate the model. See the references for more info.
-create table personnel (
+create table t1 (
id INTEGER AUTO_INCREMENT PRIMARY KEY,
emp CHAR(10) NOT NULL,
salary DECIMAL(6,2) NOT NULL,
l INTEGER NOT NULL,
r INTEGER NOT NULL);
-prepare st_ins from 'insert into personnel set emp = ?, salary = ?, l = ?, r = ?';
+prepare st_ins from 'insert into t1 set emp = ?, salary = ?, l = ?, r = ?';
# Initial employee list:
-# Jerry ( Bert ( ) Chuck ( Donna ( ) Eddie ( ) Fred ( ) ) )
+# Jerry ( Bert () Chuck ( Donna () Eddie () Fred () ) )
set @arg_nam= 'Jerry'; set @arg_sal= 1000; set @arg_l= 1; set @arg_r= 12;
execute st_ins using @arg_nam, @arg_sal, @arg_l, @arg_r ;
set @arg_nam= 'Bert'; set @arg_sal= 900; set @arg_l= 2; set @arg_r= 3;
@@ -43,11 +44,11 @@ execute st_ins using @arg_nam, @arg_sal, @arg_l, @arg_r ;
set @arg_nam= 'Fred'; set @arg_sal= 600; set @arg_l= 9; set @arg_r= 10;
execute st_ins using @arg_nam, @arg_sal, @arg_l, @arg_r ;
-select * from personnel;
+select * from t1;
# Three successive raises, each one is 100 units for managers, 10 percent for others.
-prepare st_raise_base from 'update personnel set salary = salary * ( 1 + ? ) where r - l = 1';
-prepare st_raise_mgr from 'update personnel set salary = salary + ? where r - l > 1';
+prepare st_raise_base from 'update t1 set salary = salary * ( 1 + ? ) where r - l = 1';
+prepare st_raise_mgr from 'update t1 set salary = salary + ? where r - l > 1';
let $1= 3;
set @arg_percent= .10;
set @arg_amount= 100;
@@ -58,6 +59,14 @@ while ($1)
dec $1;
}
-select * from personnel;
+select * from t1;
+
+# Waiting for the resolution of bug#6138
+# # Now, increase salary to a multiple of 50
+# prepare st_round from 'update t1 set salary = salary + ? - ( salary MOD ? )';
+# set @arg_round= 50;
+# execute st_round using @arg_round, @arg_round;
+#
+# select * from t1;
-drop table personnel;
+drop table t1;
diff --git a/mysql-test/t/ps_11bugs.test b/mysql-test/t/ps_11bugs.test
index d0aeaf265bb..5945b140645 100644
--- a/mysql-test/t/ps_11bugs.test
+++ b/mysql-test/t/ps_11bugs.test
@@ -97,7 +97,7 @@ drop table t1;
# end of bug#1644
-# bug#1677: Prepared statement two-table join returns no rows when one is expected
+# bug#1676: Prepared statement two-table join returns no rows when one is expected
create table t1(
cola varchar(50) not null,
diff --git a/mysql-test/t/rpl_commit_after_flush.test b/mysql-test/t/rpl_commit_after_flush.test
new file mode 100644
index 00000000000..62c89b3aae6
--- /dev/null
+++ b/mysql-test/t/rpl_commit_after_flush.test
@@ -0,0 +1,17 @@
+source include/master-slave.inc;
+source include/have_innodb.inc;
+create table t1 (a int) engine=innodb;
+begin;
+insert into t1 values(1);
+flush tables with read lock;
+commit;
+save_master_pos;
+connection slave;
+sync_with_master;
+# cleanup
+connection master;
+unlock tables;
+drop table t1;
+save_master_pos;
+connection slave;
+sync_with_master;
diff --git a/mysql-test/t/union.test b/mysql-test/t/union.test
index c5e72e85835..6e16a2b02aa 100644
--- a/mysql-test/t/union.test
+++ b/mysql-test/t/union.test
@@ -595,3 +595,58 @@ select a as a from t3 union select "1";
select a as a from t4 union select a from t3;
select a as a from t1 union select a from t4;
drop table t1,t2,t3,t4;
+
+#
+# Bug #6139 UNION doesn't understand collate in the column of second select
+#
+create table t1 as
+(select _latin1'test') union
+(select _latin1'TEST') union
+(select _latin1'TeST');
+show create table t1;
+select count(*) from t1;
+drop table t1;
+
+create table t1 as
+(select _latin1'test' collate latin1_bin) union
+(select _latin1'TEST') union
+(select _latin1'TeST');
+show create table t1;
+select count(*) from t1;
+drop table t1;
+
+create table t1 as
+(select _latin1'test') union
+(select _latin1'TEST' collate latin1_bin) union
+(select _latin1'TeST');
+show create table t1;
+select count(*) from t1;
+drop table t1;
+
+create table t1 as
+(select _latin1'test') union
+(select _latin1'TEST') union
+(select _latin1'TeST' collate latin1_bin);
+show create table t1;
+select count(*) from t1;
+drop table t1;
+
+create table t2 (
+a char character set latin1 collate latin1_swedish_ci,
+b char character set latin1 collate latin1_bin);
+--error 1271
+create table t1 as
+(select a from t2) union
+(select b from t2);
+create table t1 as
+(select a collate latin1_german1_ci from t2) union
+(select b from t2);
+show create table t1;
+drop table t1;
+create table t1 as
+(select a from t2) union
+(select b collate latin1_german1_ci from t2);
+show create table t1;
+drop table t1;
+drop table t2;
+
diff --git a/mysys/hash.c b/mysys/hash.c
index 6f2788ddce7..cf0f1d2dde6 100644
--- a/mysys/hash.c
+++ b/mysys/hash.c
@@ -72,19 +72,48 @@ _hash_init(HASH *hash,CHARSET_INFO *charset,
}
-void hash_free(HASH *hash)
+/*
+ Call hash->free on all elements in hash.
+
+ SYNOPSIS
+ hash_free_elements()
+ hash hash table
+
+ NOTES:
+ Sets records to 0
+*/
+
+static inline void hash_free_elements(HASH *hash)
{
- DBUG_ENTER("hash_free");
if (hash->free)
{
- uint i,records;
HASH_LINK *data=dynamic_element(&hash->array,0,HASH_LINK*);
- for (i=0,records=hash->records ; i < records ; i++)
- (*hash->free)(data[i].data);
- hash->free=0;
+ HASH_LINK *end= data + hash->records;
+ while (data < end)
+ (*hash->free)((data++)->data);
}
- delete_dynamic(&hash->array);
hash->records=0;
+}
+
+
+/*
+ Free memory used by hash.
+
+ SYNOPSIS
+ hash_free()
+ hash the hash to delete elements of
+
+ NOTES: Hash can't be reused wuthing calling hash_init again.
+*/
+
+void hash_free(HASH *hash)
+{
+ DBUG_ENTER("hash_free");
+ DBUG_PRINT("enter",("hash: 0x%lxd",hash));
+
+ hash_free_elements(hash);
+ hash->free= 0;
+ delete_dynamic(&hash->array);
DBUG_VOID_RETURN;
}
@@ -94,21 +123,17 @@ void hash_free(HASH *hash)
SYNOPSIS
hash_reset()
- hash the hash to delete elements of
+ hash the hash to delete elements of
*/
void hash_reset(HASH *hash)
{
DBUG_ENTER("hash_reset");
- if (hash->free)
- {
- HASH_LINK *link= dynamic_element(&hash->array, 0, HASH_LINK*);
- HASH_LINK *end= link + hash->records;
- for (; link < end; ++link)
- (*hash->free)(link->data);
- }
+ DBUG_PRINT("enter",("hash: 0x%lxd",hash));
+
+ hash_free_elements(hash);
reset_dynamic(&hash->array);
- hash->records= 0;
+ /* Set row pointers so that the hash can be reused at once */
hash->blength= 1;
hash->current_record= NO_RECORD;
DBUG_VOID_RETURN;
diff --git a/mysys/my_bitmap.c b/mysys/my_bitmap.c
index 3a09255b0b0..ca75842ffcf 100644
--- a/mysys/my_bitmap.c
+++ b/mysys/my_bitmap.c
@@ -38,7 +38,7 @@
#include <m_string.h>
-inline void bitmap_lock(MY_BITMAP *map)
+static inline void bitmap_lock(MY_BITMAP *map)
{
#ifdef THREAD
if (map->mutex)
@@ -47,7 +47,7 @@ inline void bitmap_lock(MY_BITMAP *map)
}
-inline void bitmap_unlock(MY_BITMAP *map)
+static inline void bitmap_unlock(MY_BITMAP *map)
{
#ifdef THREAD
if (map->mutex)
diff --git a/mysys/my_gethwaddr.c b/mysys/my_gethwaddr.c
index 72f1cb975c4..222abe81933 100644
--- a/mysys/my_gethwaddr.c
+++ b/mysys/my_gethwaddr.c
@@ -107,7 +107,7 @@ my_bool my_gethwaddr(uchar *to __attribute__((unused)))
}
#endif
-#else MAIN
+#else /* MAIN */
int main(int argc __attribute__((unused)),char **argv)
{
uchar mac[6];
diff --git a/mysys/thr_lock.c b/mysys/thr_lock.c
index d9e46fe1beb..d47ca8de183 100644
--- a/mysys/thr_lock.c
+++ b/mysys/thr_lock.c
@@ -552,8 +552,14 @@ int thr_lock(THR_LOCK_DATA *data,enum thr_lock_type lock_type)
!lock->write_wait.data &&
lock->write.data->type == TL_WRITE_ALLOW_WRITE))
{
- /* We have already got a write lock or all locks are
- TL_WRITE_ALLOW_WRITE */
+ /*
+ We have already got a write lock or all locks are
+ TL_WRITE_ALLOW_WRITE
+ */
+ DBUG_PRINT("info", ("write_wait.data: 0x%lx old_type: %d",
+ (ulong) lock->write_wait.data,
+ lock->write.data->type));
+
(*lock->write.last)=data; /* Add to running fifo */
data->prev=lock->write.last;
lock->write.last= &data->next;
@@ -568,6 +574,8 @@ int thr_lock(THR_LOCK_DATA *data,enum thr_lock_type lock_type)
}
else
{
+ DBUG_PRINT("info", ("write_wait.data: 0x%lx",
+ (ulong) lock->write_wait.data));
if (!lock->write_wait.data)
{ /* no scheduled write locks */
if (lock_type == TL_WRITE_CONCURRENT_INSERT &&
diff --git a/ndb/examples/select_all/select_all.cpp b/ndb/examples/select_all/select_all.cpp
index bd25fb60128..24bb1214bd2 100644
--- a/ndb/examples/select_all/select_all.cpp
+++ b/ndb/examples/select_all/select_all.cpp
@@ -98,7 +98,7 @@ void ResultSetContainer::init(NdbDictionary::Dictionary * dict,
// Store all attribute names for the table
for (int i = 0; i < m_cols; i++) {
m_names[i] = new char[255];
- snprintf(m_names[i], 255, "%s", tab->getColumn(i)->getName());
+ BaseString::snprintf(m_names[i], 255, "%s", tab->getColumn(i)->getName());
}
}
diff --git a/ndb/include/kernel/BlockNumbers.h b/ndb/include/kernel/BlockNumbers.h
index e89a82ee0cb..cb3cc697eee 100644
--- a/ndb/include/kernel/BlockNumbers.h
+++ b/ndb/include/kernel/BlockNumbers.h
@@ -20,13 +20,13 @@
#include <kernel_types.h>
#include <RefConvert.hpp>
-// 240
+/* 240 */
#define MIN_API_BLOCK_NO 0x8000
-// 2047
+/* 2047 */
#define API_PACKED 0x07ff
-// 4002
+/* 4002 */
#define API_CLUSTERMGR 0x0FA2
#define BACKUP 0xF4
diff --git a/ndb/include/kernel/GlobalSignalNumbers.h b/ndb/include/kernel/GlobalSignalNumbers.h
index 88acef8c772..9413f4ef56a 100644
--- a/ndb/include/kernel/GlobalSignalNumbers.h
+++ b/ndb/include/kernel/GlobalSignalNumbers.h
@@ -78,7 +78,7 @@ extern const GlobalSignalNumber NO_OF_SIGNAL_NAMES;
#define GSN_SCAN_NEXTREQ 28
#define GSN_SCAN_TABCONF 29
-// 30 unused
+/* 30 unused */
#define GSN_SCAN_TABREF 31
#define GSN_SCAN_TABREQ 32
#define GSN_KEYINFO20 33
@@ -91,42 +91,42 @@ extern const GlobalSignalNumber NO_OF_SIGNAL_NAMES;
#define GSN_TCSEIZEREF 38
#define GSN_TCSEIZEREQ 39
-// 40 unused
-// 41 unused
-// 42 unused
-// 43 unused
-// 44 unused
-// 45 unused
-// 46 unused
-// 47 unused
-// 48 unused
-// 49 unused
-// 50 unused
-// 51 unused
-// 52 unused
-// 53 unused
-// 54 unused
-// 55 unused
-// 56 unused
-// 57 unused
-// 58 unused
-// 59 unused
-// 60 unused
-// 61 unused
-// 62 unused
-// 63 unused
-// 64 unused
-// 65 unused
-// 66 unused
+/* 40 unused */
+/* 41 unused */
+/* 42 unused */
+/* 43 unused */
+/* 44 unused */
+/* 45 unused */
+/* 46 unused */
+/* 47 unused */
+/* 48 unused */
+/* 49 unused */
+/* 50 unused */
+/* 51 unused */
+/* 52 unused */
+/* 53 unused */
+/* 54 unused */
+/* 55 unused */
+/* 56 unused */
+/* 57 unused */
+/* 58 unused */
+/* 59 unused */
+/* 60 unused */
+/* 61 unused */
+/* 62 unused */
+/* 63 unused */
+/* 64 unused */
+/* 65 unused */
+/* 66 unused */
/**
* These are used only by kernel
*/
#define GSN_ACC_ABORTCONF 67
-// 68 unused
-// 69 unused
-// 70 unused
+/* 68 unused */
+/* 69 unused */
+/* 70 unused */
#define GSN_ACC_ABORTREQ 71
#define GSN_ACC_CHECK_SCAN 72
#define GSN_ACC_COMMITCONF 73
@@ -172,42 +172,42 @@ extern const GlobalSignalNumber NO_OF_SIGNAL_NAMES;
#define GSN_API_FAILCONF 113
#define GSN_API_FAILREQ 114
#define GSN_CNTR_START_REQ 115
-// 116 not unused
+/* 116 not unused */
#define GSN_CNTR_START_REF 117
#define GSN_CNTR_START_CONF 118
#define GSN_CNTR_START_REP 119
-// 120 unused
-// 121 unused
-// 122 unused
-// 123 unused
-// 124 unused
+/* 120 unused */
+/* 121 unused */
+/* 122 unused */
+/* 123 unused */
+/* 124 unused */
#define GSN_CHECK_LCP_STOP 125
-#define GSN_CLOSE_COMCONF 126 // local
-#define GSN_CLOSE_COMREQ 127 // local
-#define GSN_CM_ACKADD 128 // distr.
-// 129 unused
-#define GSN_CM_ADD 130 // distr.
-// 131 unused
-// 132 not unused
-// 133 not unused
-#define GSN_CM_HEARTBEAT 134 // distr.
-// 135 unused
-// 136 unused
-// 137 unused
-#define GSN_CM_NODEINFOCONF 138 // distr.
-#define GSN_CM_NODEINFOREF 139 // distr.
-#define GSN_CM_NODEINFOREQ 140 // distr.
-#define GSN_CM_REGCONF 141 // distr.
-#define GSN_CM_REGREF 142 // distr.
-#define GSN_CM_REGREQ 143 // distr.
-// 144 unused
-// 145 unused
-// 146 unused
-#define GSN_CM_ADD_REP 147 // local
-// 148 unused
-// 149 unused
-// 150 unused
-#define GSN_CNTR_WAITREP 151 // distr.
+#define GSN_CLOSE_COMCONF 126 /* local */
+#define GSN_CLOSE_COMREQ 127 /* local */
+#define GSN_CM_ACKADD 128 /* distr. */
+/* 129 unused */
+#define GSN_CM_ADD 130 /* distr. */
+/* 131 unused */
+/* 132 not unused */
+/* 133 not unused */
+#define GSN_CM_HEARTBEAT 134 /* distr. */
+/* 135 unused */
+/* 136 unused */
+/* 137 unused */
+#define GSN_CM_NODEINFOCONF 138 /* distr. */
+#define GSN_CM_NODEINFOREF 139 /* distr. */
+#define GSN_CM_NODEINFOREQ 140 /* distr. */
+#define GSN_CM_REGCONF 141 /* distr. */
+#define GSN_CM_REGREF 142 /* distr. */
+#define GSN_CM_REGREQ 143 /* distr. */
+/* 144 unused */
+/* 145 unused */
+/* 146 unused */
+#define GSN_CM_ADD_REP 147 /* local */
+/* 148 unused */
+/* 149 unused */
+/* 150 unused */
+#define GSN_CNTR_WAITREP 151 /* distr. */
#define GSN_COMMIT 152
#define GSN_COMMIT_FAILCONF 153
#define GSN_COMMIT_FAILREQ 154
@@ -220,7 +220,7 @@ extern const GlobalSignalNumber NO_OF_SIGNAL_NAMES;
#define GSN_COMPLETEREQ 162
#define GSN_CONNECT_REP 163
#define GSN_CONTINUEB 164
-// 165 not unused
+/* 165 not unused */
#define GSN_COPY_ACTIVECONF 166
#define GSN_COPY_ACTIVEREF 167
#define GSN_COPY_ACTIVEREQ 168
@@ -243,9 +243,9 @@ extern const GlobalSignalNumber NO_OF_SIGNAL_NAMES;
#define GSN_DIADDTABCONF 185
#define GSN_DIADDTABREF 186
#define GSN_DIADDTABREQ 187
-// 188 not unused
-// 189 not unused
-// 190 not unused
+/* 188 not unused */
+/* 189 not unused */
+/* 190 not unused */
#define GSN_DICTSTARTCONF 191
#define GSN_DICTSTARTREQ 192
@@ -301,9 +301,9 @@ extern const GlobalSignalNumber NO_OF_SIGNAL_NAMES;
#define GSN_DIH_RESTARTREF 218
#define GSN_DIH_RESTARTREQ 219
-// 220 not unused
-// 221 not unused
-// 222 not unused
+/* 220 not unused */
+/* 221 not unused */
+/* 222 not unused */
#define GSN_EMPTY_LCP_REQ 223
#define GSN_EMPTY_LCP_CONF 224
@@ -315,8 +315,8 @@ extern const GlobalSignalNumber NO_OF_SIGNAL_NAMES;
#define GSN_MASTER_GCPREF 228
#define GSN_MASTER_GCPREQ 229
-// 230 not unused
-// 231 not unused
+/* 230 not unused */
+/* 231 not unused */
#define GSN_DIRELEASECONF 232
#define GSN_DIRELEASEREF 233
@@ -388,8 +388,8 @@ extern const GlobalSignalNumber NO_OF_SIGNAL_NAMES;
#define GSN_LCP_HOLDOPREQ 299
#define GSN_SHRINKCHECK2 301
#define GSN_GET_SCHEMA_INFOREQ 302
-// 303 not unused
-// 304 not unused
+/* 303 not unused */
+/* 304 not unused */
#define GSN_LQH_RESTART_OP 305
#define GSN_LQH_TRANSCONF 306
#define GSN_LQH_TRANSREQ 307
@@ -421,12 +421,12 @@ extern const GlobalSignalNumber NO_OF_SIGNAL_NAMES;
#define GSN_NEXT_SCANREQ 332
#define GSN_NEXTOPERATION 333
-#define GSN_READ_CONFIG_REQ 334 // new name for sizealt, local
-#define GSN_READ_CONFIG_CONF 335 // new name for sizealt, local
+#define GSN_READ_CONFIG_REQ 334 /* new name for sizealt, local */
+#define GSN_READ_CONFIG_CONF 335 /* new name for sizealt, local */
-// 336 unused
-// 337 unused
-// 338 unused
+/* 336 unused */
+/* 337 unused */
+/* 338 unused */
#define GSN_OPEN_COMCONF 339
#define GSN_OPEN_COMREF 340
#define GSN_OPEN_COMREQ 341
@@ -452,7 +452,7 @@ extern const GlobalSignalNumber NO_OF_SIGNAL_NAMES;
#define GSN_TUP_ALLOCREQ 360
#define GSN_TUP_DEALLOCREQ 361
-// 362 not unused
+/* 362 not unused */
#define GSN_TUP_WRITELOG_REQ 363
#define GSN_LQH_WRITELOG_REQ 364
@@ -507,16 +507,16 @@ extern const GlobalSignalNumber NO_OF_SIGNAL_NAMES;
#define GSN_TEST_ORD 407
#define GSN_TESTSIG 408
#define GSN_TIME_SIGNAL 409
-// 410 unused
-// 411 unused
-// 412 unused
+/* 410 unused */
+/* 411 unused */
+/* 412 unused */
#define GSN_TUP_ABORTREQ 414
#define GSN_TUP_ADD_ATTCONF 415
#define GSN_TUP_ADD_ATTRREF 416
#define GSN_TUP_ADD_ATTRREQ 417
#define GSN_TUP_ATTRINFO 418
#define GSN_TUP_COMMITREQ 419
-// 420 unused
+/* 420 unused */
#define GSN_TUP_LCPCONF 421
#define GSN_TUP_LCPREF 422
#define GSN_TUP_LCPREQ 423
@@ -553,8 +553,8 @@ extern const GlobalSignalNumber NO_OF_SIGNAL_NAMES;
#define GSN_STATISTICS_CONF 454
#define GSN_START_ORD 455
-// 456 unused
-// 457 unused
+/* 456 unused */
+/* 457 unused */
#define GSN_EVENT_SUBSCRIBE_REQ 458
#define GSN_EVENT_SUBSCRIBE_CONF 459
@@ -576,7 +576,7 @@ extern const GlobalSignalNumber NO_OF_SIGNAL_NAMES;
#define GSN_CHECKNODEGROUPSREQ 471
#define GSN_CHECKNODEGROUPSCONF 472
-// 473 unused
+/* 473 unused */
#define GSN_ARBIT_PREPREQ 474
#define GSN_ARBIT_PREPCONF 475
#define GSN_ARBIT_PREPREF 476
@@ -612,7 +612,7 @@ extern const GlobalSignalNumber NO_OF_SIGNAL_NAMES;
#define GSN_WAIT_GCP_REF 500
#define GSN_WAIT_GCP_CONF 501
-// 502 not used
+/* 502 not used */
/**
* Trigger and index signals
@@ -732,7 +732,7 @@ extern const GlobalSignalNumber NO_OF_SIGNAL_NAMES;
#define GSN_SUB_STOP_REQ 572
#define GSN_SUB_STOP_REF 573
#define GSN_SUB_STOP_CONF 574
-// 575 unused
+/* 575 unused */
#define GSN_SUB_CREATE_REQ 576
#define GSN_SUB_CREATE_REF 577
#define GSN_SUB_CREATE_CONF 578
@@ -832,7 +832,7 @@ extern const GlobalSignalNumber NO_OF_SIGNAL_NAMES;
#define GSN_GREP_REMOVE_REF 654
#define GSN_GREP_REMOVE_CONF 655
-// Start Global Replication
+/* Start Global Replication */
#define GSN_GREP_REQ 656
/**
@@ -891,8 +891,8 @@ extern const GlobalSignalNumber NO_OF_SIGNAL_NAMES;
#define GSN_TUX_MAINT_CONF 678
#define GSN_TUX_MAINT_REF 679
-// not used 680
-// not used 681
+/* not used 680 */
+/* not used 681 */
/**
* from mgmtsrvr to NDBCNTR
@@ -903,10 +903,10 @@ extern const GlobalSignalNumber NO_OF_SIGNAL_NAMES;
#define GSN_API_VERSION_REQ 697
#define GSN_API_VERSION_CONF 698
-// not used 686
-// not used 687
-// not used 689
-// not used 690
+/* not used 686 */
+/* not used 687 */
+/* not used 689 */
+/* not used 690 */
/**
* SUMA restart protocol
@@ -915,9 +915,9 @@ extern const GlobalSignalNumber NO_OF_SIGNAL_NAMES;
#define GSN_SUMA_HANDOVER_REQ 692
#define GSN_SUMA_HANDOVER_CONF 693
-// not used 694
-// not used 695
-// not used 696
+/* not used 694 */
+/* not used 695 */
+/* not used 696 */
/**
* GREP restart protocol
diff --git a/ndb/include/kernel/LogLevel.hpp b/ndb/include/kernel/LogLevel.hpp
index be0627c98a8..6cfbe44af86 100644
--- a/ndb/include/kernel/LogLevel.hpp
+++ b/ndb/include/kernel/LogLevel.hpp
@@ -47,6 +47,7 @@ public:
LogLevel & operator= (const LogLevel &);
enum EventCategory {
+ llInvalid = -1,
llStartUp = CFG_LOGLEVEL_STARTUP - CFG_MIN_LOGLEVEL,
llShutdown = CFG_LOGLEVEL_SHUTDOWN - CFG_MIN_LOGLEVEL,
llStatistic = CFG_LOGLEVEL_STATISTICS - CFG_MIN_LOGLEVEL,
diff --git a/ndb/include/kernel/ndb_limits.h b/ndb/include/kernel/ndb_limits.h
index 9411a98f091..88fcff22da7 100644
--- a/ndb/include/kernel/ndb_limits.h
+++ b/ndb/include/kernel/ndb_limits.h
@@ -50,7 +50,7 @@
**/
#define MAX_TUPLES_PER_PAGE 8191
#define MAX_TUPLES_BITS 13 /* 13 bits = 8191 tuples per page */
-//#define MAX_NO_OF_TUPLEKEY 16 Not currently used
+/*#define MAX_NO_OF_TUPLEKEY 16 Not currently used */
#define MAX_TABLES 1600
#define MAX_TAB_NAME_SIZE 128
#define MAX_ATTR_NAME_SIZE 32
@@ -108,13 +108,13 @@
/*
* Ordered index constants. Make configurable per index later.
*/
-#define MAX_TTREE_NODE_SIZE 64 // total words in node
-#define MAX_TTREE_PREF_SIZE 4 // words in min prefix
-#define MAX_TTREE_NODE_SLACK 3 // diff between max and min occupancy
+#define MAX_TTREE_NODE_SIZE 64 /* total words in node */
+#define MAX_TTREE_PREF_SIZE 4 /* words in min prefix */
+#define MAX_TTREE_NODE_SLACK 2 /* diff between max and min occupancy */
/*
* Blobs.
*/
-#define NDB_BLOB_HEAD_SIZE 2 // sizeof(NdbBlob::Head) >> 2
+#define NDB_BLOB_HEAD_SIZE 2 /* sizeof(NdbBlob::Head) >> 2 */
#endif
diff --git a/ndb/include/kernel/signaldata/ArbitSignalData.hpp b/ndb/include/kernel/signaldata/ArbitSignalData.hpp
index 271b9920cd0..f255b8dcbbe 100644
--- a/ndb/include/kernel/signaldata/ArbitSignalData.hpp
+++ b/ndb/include/kernel/signaldata/ArbitSignalData.hpp
@@ -54,7 +54,7 @@ public:
}
inline void getText(char *buf, size_t buf_len) const {
- snprintf(buf, buf_len, "%08x%08x", data[0], data[1]);
+ BaseString::snprintf(buf, buf_len, "%08x%08x", data[0], data[1]);
}
/* inline char* getText() const {
@@ -113,19 +113,19 @@ public:
static inline void getErrText(Uint32 code, char* buf, size_t buf_len) {
switch (code) {
case ErrTicket:
- snprintf(buf, buf_len, "invalid arbitrator-ticket");
+ BaseString::snprintf(buf, buf_len, "invalid arbitrator-ticket");
break;
case ErrToomany:
- snprintf(buf, buf_len, "too many requests");
+ BaseString::snprintf(buf, buf_len, "too many requests");
break;
case ErrState:
- snprintf(buf, buf_len, "invalid state");
+ BaseString::snprintf(buf, buf_len, "invalid state");
break;
case ErrTimeout:
- snprintf(buf, buf_len, "timeout");
+ BaseString::snprintf(buf, buf_len, "timeout");
break;
default:
- snprintf(buf, buf_len, "unknown error [code=%u]", code);
+ BaseString::snprintf(buf, buf_len, "unknown error [code=%u]", code);
break;
}
}
diff --git a/ndb/include/kernel/signaldata/AttrInfo.hpp b/ndb/include/kernel/signaldata/AttrInfo.hpp
index 18bd9b22c40..c87470db8b0 100644
--- a/ndb/include/kernel/signaldata/AttrInfo.hpp
+++ b/ndb/include/kernel/signaldata/AttrInfo.hpp
@@ -35,7 +35,8 @@ class AttrInfo {
*/
friend class Dbtc;
friend class Dblqh;
-
+ friend class NdbScanOperation;
+
friend bool printATTRINFO(FILE *, const Uint32 *, Uint32, Uint16);
public:
diff --git a/ndb/include/kernel/signaldata/DictTabInfo.hpp b/ndb/include/kernel/signaldata/DictTabInfo.hpp
index a9a50f19fbc..df0ac988e6e 100644
--- a/ndb/include/kernel/signaldata/DictTabInfo.hpp
+++ b/ndb/include/kernel/signaldata/DictTabInfo.hpp
@@ -38,7 +38,7 @@
offsetof(x, l) }
#define DTIBREAK(x) \
- { DictTabInfo::x, 0, SimpleProperties::InvalidValue, 0, 0 }
+ { DictTabInfo::x, 0, SimpleProperties::InvalidValue, 0, 0, 0 }
class DictTabInfo {
/**
diff --git a/ndb/include/kernel/signaldata/DihContinueB.hpp b/ndb/include/kernel/signaldata/DihContinueB.hpp
index e683b55351c..77ecf360601 100644
--- a/ndb/include/kernel/signaldata/DihContinueB.hpp
+++ b/ndb/include/kernel/signaldata/DihContinueB.hpp
@@ -24,7 +24,8 @@ class DihContinueB {
* Sender(s)/Reciver(s)
*/
friend class Dbdih;
- friend bool printCONTINUEB_DBDIH(FILE * output, const Uint32 * theData, Uint32 len);
+ friend bool printCONTINUEB_DBDIH(FILE * output, const Uint32 * theData,
+ Uint32 len, Uint16);
private:
enum Type {
ZPACK_TABLE_INTO_PAGES = 1,
diff --git a/ndb/include/kernel/signaldata/KeyInfo.hpp b/ndb/include/kernel/signaldata/KeyInfo.hpp
index a4c698f89b2..686f3ae053d 100644
--- a/ndb/include/kernel/signaldata/KeyInfo.hpp
+++ b/ndb/include/kernel/signaldata/KeyInfo.hpp
@@ -26,6 +26,7 @@ class KeyInfo {
friend class DbUtil;
friend class NdbOperation;
friend class NdbScanOperation;
+ friend class NdbIndexScanOperation;
/**
* Reciver(s)
diff --git a/ndb/include/kernel/signaldata/NdbfsContinueB.hpp b/ndb/include/kernel/signaldata/NdbfsContinueB.hpp
index 2d569be721f..6154e5c19b1 100644
--- a/ndb/include/kernel/signaldata/NdbfsContinueB.hpp
+++ b/ndb/include/kernel/signaldata/NdbfsContinueB.hpp
@@ -24,7 +24,8 @@ class NdbfsContinueB {
* Sender(s)/Reciver(s)
*/
friend class Ndbfs;
- friend bool printCONTINUEB_NDBFS(FILE * output, const Uint32 * theData, Uint32 len);
+ friend bool printCONTINUEB_NDBFS(FILE * output, const Uint32 * theData,
+ Uint32 len, Uint16);
private:
enum {
ZSCAN_MEMORYCHANNEL_10MS_DELAY = 0,
diff --git a/ndb/include/kernel/signaldata/ScanFrag.hpp b/ndb/include/kernel/signaldata/ScanFrag.hpp
index d3a89b8dc25..41ea569c45d 100644
--- a/ndb/include/kernel/signaldata/ScanFrag.hpp
+++ b/ndb/include/kernel/signaldata/ScanFrag.hpp
@@ -34,14 +34,16 @@ class ScanFragReq {
friend class Dblqh;
public:
STATIC_CONST( SignalLength = 12 );
-
+
+ friend bool printSCAN_FRAGREQ(FILE *, const Uint32*, Uint32, Uint16);
+
public:
Uint32 senderData;
Uint32 resultRef; // Where to send the result
Uint32 savePointId;
Uint32 requestInfo;
Uint32 tableId;
- Uint32 fragmentNo;
+ Uint32 fragmentNoKeyLen;
Uint32 schemaVersion;
Uint32 transId1;
Uint32 transId2;
diff --git a/ndb/include/kernel/signaldata/ScanTab.hpp b/ndb/include/kernel/signaldata/ScanTab.hpp
index 1acd7ae4736..fb5f18eae9e 100644
--- a/ndb/include/kernel/signaldata/ScanTab.hpp
+++ b/ndb/include/kernel/signaldata/ScanTab.hpp
@@ -55,7 +55,7 @@ private:
* DATA VARIABLES
*/
UintR apiConnectPtr; // DATA 0
- UintR attrLen; // DATA 1
+ UintR attrLenKeyLen; // DATA 1
UintR requestInfo; // DATA 2
UintR tableId; // DATA 3
UintR tableSchemaVersion; // DATA 4
@@ -74,6 +74,7 @@ private:
static Uint8 getHoldLockFlag(const UintR & requestInfo);
static Uint8 getReadCommittedFlag(const UintR & requestInfo);
static Uint8 getRangeScanFlag(const UintR & requestInfo);
+ static Uint8 getKeyinfoFlag(const UintR & requestInfo);
static Uint16 getScanBatch(const UintR & requestInfo);
/**
@@ -85,6 +86,7 @@ private:
static void setHoldLockFlag(UintR & requestInfo, Uint32 flag);
static void setReadCommittedFlag(UintR & requestInfo, Uint32 flag);
static void setRangeScanFlag(UintR & requestInfo, Uint32 flag);
+ static void setKeyinfoFlag(UintR & requestInfo, Uint32 flag);
static void setScanBatch(Uint32& requestInfo, Uint32 sz);
};
@@ -95,12 +97,13 @@ private:
l = Lock mode - 1 Bit 8
h = Hold lock mode - 1 Bit 10
c = Read Committed - 1 Bit 11
+ k = Keyinfo - 1 Bit 12
x = Range Scan (TUX) - 1 Bit 15
b = Scan batch - 10 Bit 16-25 (max 1023)
1111111111222222222233
01234567890123456789012345678901
- ppppppppl hc xbbbbbbbbbb
+ ppppppppl hck xbbbbbbbbbb
*/
#define PARALLELL_SHIFT (0)
@@ -112,6 +115,9 @@ private:
#define HOLD_LOCK_SHIFT (10)
#define HOLD_LOCK_MASK (1)
+#define KEYINFO_SHIFT (12)
+#define KEYINFO_MASK (1)
+
#define READ_COMMITTED_SHIFT (11)
#define READ_COMMITTED_MASK (1)
@@ -206,6 +212,20 @@ ScanTabReq::setScanBatch(Uint32 & requestInfo, Uint32 flag){
requestInfo |= (flag << SCAN_BATCH_SHIFT);
}
+inline
+Uint8
+ScanTabReq::getKeyinfoFlag(const UintR & requestInfo){
+ return (Uint8)((requestInfo >> KEYINFO_SHIFT) & KEYINFO_MASK);
+}
+
+inline
+void
+ScanTabReq::setKeyinfoFlag(UintR & requestInfo, Uint32 flag){
+ ASSERT_BOOL(flag, "ScanTabReq::setKeyinfoFlag");
+ requestInfo |= (flag << KEYINFO_SHIFT);
+}
+
+
/**
*
* SENDER: Dbtc
diff --git a/ndb/include/kernel/signaldata/SignalData.hpp b/ndb/include/kernel/signaldata/SignalData.hpp
index 6e5748217b2..f9d3a6faa64 100644
--- a/ndb/include/kernel/signaldata/SignalData.hpp
+++ b/ndb/include/kernel/signaldata/SignalData.hpp
@@ -20,6 +20,7 @@
#include <ndb_global.h>
#include <ndb_limits.h>
#include <kernel_types.h>
+#include <BaseString.hpp>
#define ASSERT_BOOL(flag, message) assert(flag<=1)
#define ASSERT_RANGE(value, min, max, message) \
@@ -50,4 +51,169 @@
Uint32 getTCErrorCode() { return TCErrorCode; }; \
void setTCErrorCode(Uint32 _s) { TCErrorCode = _s; };
+#define GSN_PRINT_SIGNATURE(f) bool f(FILE *, const Uint32 *, Uint32, Uint16)
+
+GSN_PRINT_SIGNATURE(printTCKEYREQ);
+GSN_PRINT_SIGNATURE(printTCKEYCONF);
+GSN_PRINT_SIGNATURE(printTCKEYREF);
+GSN_PRINT_SIGNATURE(printLQHKEYREQ);
+GSN_PRINT_SIGNATURE(printLQHKEYCONF);
+GSN_PRINT_SIGNATURE(printLQHKEYREF);
+GSN_PRINT_SIGNATURE(printTUPKEYREQ);
+GSN_PRINT_SIGNATURE(printTUPKEYCONF);
+GSN_PRINT_SIGNATURE(printTUPKEYREF);
+GSN_PRINT_SIGNATURE(printTUPCOMMITREQ);
+GSN_PRINT_SIGNATURE(printCONTINUEB);
+GSN_PRINT_SIGNATURE(printFSOPENREQ);
+GSN_PRINT_SIGNATURE(printFSCLOSEREQ);
+GSN_PRINT_SIGNATURE(printFSREADWRITEREQ);
+GSN_PRINT_SIGNATURE(printFSREADWRITEREQ);
+GSN_PRINT_SIGNATURE(printFSREF);
+GSN_PRINT_SIGNATURE(printFSREF);
+GSN_PRINT_SIGNATURE(printFSREF);
+GSN_PRINT_SIGNATURE(printFSREF);
+GSN_PRINT_SIGNATURE(printFSREF);
+GSN_PRINT_SIGNATURE(printFSCONF);
+GSN_PRINT_SIGNATURE(printFSCONF);
+GSN_PRINT_SIGNATURE(printFSCONF);
+GSN_PRINT_SIGNATURE(printFSCONF);
+GSN_PRINT_SIGNATURE(printFSCONF);
+GSN_PRINT_SIGNATURE(printCLOSECOMREQCONF);
+GSN_PRINT_SIGNATURE(printCLOSECOMREQCONF);
+GSN_PRINT_SIGNATURE(printPACKED_SIGNAL);
+GSN_PRINT_SIGNATURE(printPREPFAILREQREF);
+GSN_PRINT_SIGNATURE(printPREPFAILREQREF);
+GSN_PRINT_SIGNATURE(printALTER_TABLE_REQ);
+GSN_PRINT_SIGNATURE(printALTER_TABLE_CONF);
+GSN_PRINT_SIGNATURE(printALTER_TABLE_REF);
+GSN_PRINT_SIGNATURE(printALTER_TAB_REQ);
+GSN_PRINT_SIGNATURE(printALTER_TAB_CONF);
+GSN_PRINT_SIGNATURE(printALTER_TAB_REF);
+GSN_PRINT_SIGNATURE(printCREATE_TRIG_REQ);
+GSN_PRINT_SIGNATURE(printCREATE_TRIG_CONF);
+GSN_PRINT_SIGNATURE(printCREATE_TRIG_REF);
+GSN_PRINT_SIGNATURE(printALTER_TRIG_REQ);
+GSN_PRINT_SIGNATURE(printALTER_TRIG_CONF);
+GSN_PRINT_SIGNATURE(printALTER_TRIG_REF);
+GSN_PRINT_SIGNATURE(printDROP_TRIG_REQ);
+GSN_PRINT_SIGNATURE(printDROP_TRIG_CONF);
+GSN_PRINT_SIGNATURE(printDROP_TRIG_REF);
+GSN_PRINT_SIGNATURE(printFIRE_TRIG_ORD);
+GSN_PRINT_SIGNATURE(printTRIG_ATTRINFO);
+GSN_PRINT_SIGNATURE(printCREATE_INDX_REQ);
+GSN_PRINT_SIGNATURE(printCREATE_INDX_CONF);
+GSN_PRINT_SIGNATURE(printCREATE_INDX_REF);
+GSN_PRINT_SIGNATURE(printDROP_INDX_REQ);
+GSN_PRINT_SIGNATURE(printDROP_INDX_CONF);
+GSN_PRINT_SIGNATURE(printDROP_INDX_REF);
+GSN_PRINT_SIGNATURE(printALTER_INDX_REQ);
+GSN_PRINT_SIGNATURE(printALTER_INDX_CONF);
+GSN_PRINT_SIGNATURE(printALTER_INDX_REF);
+GSN_PRINT_SIGNATURE(printTCINDXREQ);
+GSN_PRINT_SIGNATURE(printTCINDXCONF);
+GSN_PRINT_SIGNATURE(printTCINDXREF);
+GSN_PRINT_SIGNATURE(printINDXKEYINFO);
+GSN_PRINT_SIGNATURE(printINDXATTRINFO);
+GSN_PRINT_SIGNATURE(printFSAPPENDREQ);
+GSN_PRINT_SIGNATURE(printBACKUP_REQ);
+GSN_PRINT_SIGNATURE(printBACKUP_DATA);
+GSN_PRINT_SIGNATURE(printBACKUP_REF);
+GSN_PRINT_SIGNATURE(printBACKUP_CONF);
+GSN_PRINT_SIGNATURE(printABORT_BACKUP_ORD);
+GSN_PRINT_SIGNATURE(printBACKUP_ABORT_REP);
+GSN_PRINT_SIGNATURE(printBACKUP_COMPLETE_REP);
+GSN_PRINT_SIGNATURE(printBACKUP_NF_COMPLETE_REP);
+GSN_PRINT_SIGNATURE(printDEFINE_BACKUP_REQ);
+GSN_PRINT_SIGNATURE(printDEFINE_BACKUP_REF);
+GSN_PRINT_SIGNATURE(printDEFINE_BACKUP_CONF);
+GSN_PRINT_SIGNATURE(printSTART_BACKUP_REQ);
+GSN_PRINT_SIGNATURE(printSTART_BACKUP_REF);
+GSN_PRINT_SIGNATURE(printSTART_BACKUP_CONF);
+GSN_PRINT_SIGNATURE(printBACKUP_FRAGMENT_REQ);
+GSN_PRINT_SIGNATURE(printBACKUP_FRAGMENT_REF);
+GSN_PRINT_SIGNATURE(printBACKUP_FRAGMENT_CONF);
+GSN_PRINT_SIGNATURE(printSTOP_BACKUP_REQ);
+GSN_PRINT_SIGNATURE(printSTOP_BACKUP_REF);
+GSN_PRINT_SIGNATURE(printSTOP_BACKUP_CONF);
+GSN_PRINT_SIGNATURE(printBACKUP_STATUS_REQ);
+GSN_PRINT_SIGNATURE(printBACKUP_STATUS_CONF);
+GSN_PRINT_SIGNATURE(printUTIL_SEQUENCE_REQ);
+GSN_PRINT_SIGNATURE(printUTIL_SEQUENCE_REF);
+GSN_PRINT_SIGNATURE(printUTIL_SEQUENCE_CONF);
+GSN_PRINT_SIGNATURE(printUTIL_PREPARE_REQ);
+GSN_PRINT_SIGNATURE(printUTIL_PREPARE_REF);
+GSN_PRINT_SIGNATURE(printUTIL_PREPARE_CONF);
+GSN_PRINT_SIGNATURE(printUTIL_EXECUTE_REQ);
+GSN_PRINT_SIGNATURE(printUTIL_EXECUTE_REF);
+GSN_PRINT_SIGNATURE(printUTIL_EXECUTE_CONF);
+GSN_PRINT_SIGNATURE(printSCANTABREQ);
+GSN_PRINT_SIGNATURE(printSCANTABCONF);
+GSN_PRINT_SIGNATURE(printSCANTABREF);
+GSN_PRINT_SIGNATURE(printSCANNEXTREQ);
+GSN_PRINT_SIGNATURE(printLQH_FRAG_REQ);
+GSN_PRINT_SIGNATURE(printLQH_FRAG_REF);
+GSN_PRINT_SIGNATURE(printLQH_FRAG_CONF);
+GSN_PRINT_SIGNATURE(printPREP_DROP_TAB_REQ);
+GSN_PRINT_SIGNATURE(printPREP_DROP_TAB_REF);
+GSN_PRINT_SIGNATURE(printPREP_DROP_TAB_CONF);
+GSN_PRINT_SIGNATURE(printDROP_TAB_REQ);
+GSN_PRINT_SIGNATURE(printDROP_TAB_REF);
+GSN_PRINT_SIGNATURE(printDROP_TAB_CONF);
+GSN_PRINT_SIGNATURE(printLCP_FRAG_ORD);
+GSN_PRINT_SIGNATURE(printLCP_FRAG_REP);
+GSN_PRINT_SIGNATURE(printLCP_COMPLETE_REP);
+GSN_PRINT_SIGNATURE(printSTART_LCP_REQ);
+GSN_PRINT_SIGNATURE(printSTART_LCP_CONF);
+GSN_PRINT_SIGNATURE(printMASTER_LCP_REQ);
+GSN_PRINT_SIGNATURE(printMASTER_LCP_REF);
+GSN_PRINT_SIGNATURE(printMASTER_LCP_CONF);
+GSN_PRINT_SIGNATURE(printCOPY_GCI_REQ);
+GSN_PRINT_SIGNATURE(printSYSTEM_ERROR);
+GSN_PRINT_SIGNATURE(printSTART_REC_REQ);
+GSN_PRINT_SIGNATURE(printSTART_REC_CONF);
+GSN_PRINT_SIGNATURE(printNF_COMPLETE_REP);
+GSN_PRINT_SIGNATURE(printSIGNAL_DROPPED_REP);
+GSN_PRINT_SIGNATURE(printFAIL_REP);
+GSN_PRINT_SIGNATURE(printDISCONNECT_REP);
+GSN_PRINT_SIGNATURE(printSUB_CREATE_REQ);
+GSN_PRINT_SIGNATURE(printSUB_CREATE_CONF);
+GSN_PRINT_SIGNATURE(printSUB_START_REQ);
+GSN_PRINT_SIGNATURE(printSUB_START_REF);
+GSN_PRINT_SIGNATURE(printSUB_START_CONF);
+GSN_PRINT_SIGNATURE(printSUB_SYNC_REQ);
+GSN_PRINT_SIGNATURE(printSUB_SYNC_REF);
+GSN_PRINT_SIGNATURE(printSUB_SYNC_CONF);
+GSN_PRINT_SIGNATURE(printSUB_META_DATA);
+GSN_PRINT_SIGNATURE(printSUB_TABLE_DATA);
+GSN_PRINT_SIGNATURE(printSUB_SYNC_CONTINUE_REQ);
+GSN_PRINT_SIGNATURE(printSUB_SYNC_CONTINUE_REF);
+GSN_PRINT_SIGNATURE(printSUB_SYNC_CONTINUE_CONF);
+GSN_PRINT_SIGNATURE(printSUB_GCP_COMPLETE_REP);
+GSN_PRINT_SIGNATURE(printCREATE_FRAGMENTATION_REQ);
+GSN_PRINT_SIGNATURE(printCREATE_FRAGMENTATION_REF);
+GSN_PRINT_SIGNATURE(printCREATE_FRAGMENTATION_CONF);
+GSN_PRINT_SIGNATURE(printUTIL_CREATE_LOCK_REQ);
+GSN_PRINT_SIGNATURE(printUTIL_CREATE_LOCK_REF);
+GSN_PRINT_SIGNATURE(printUTIL_CREATE_LOCK_CONF);
+GSN_PRINT_SIGNATURE(printUTIL_DESTROY_LOCK_REQ);
+GSN_PRINT_SIGNATURE(printUTIL_DESTROY_LOCK_REF);
+GSN_PRINT_SIGNATURE(printUTIL_DESTROY_LOCK_CONF);
+GSN_PRINT_SIGNATURE(printUTIL_LOCK_REQ);
+GSN_PRINT_SIGNATURE(printUTIL_LOCK_REF);
+GSN_PRINT_SIGNATURE(printUTIL_LOCK_CONF);
+GSN_PRINT_SIGNATURE(printUTIL_UNLOCK_REQ);
+GSN_PRINT_SIGNATURE(printUTIL_UNLOCK_REF);
+GSN_PRINT_SIGNATURE(printUTIL_UNLOCK_CONF);
+GSN_PRINT_SIGNATURE(printCNTR_START_REQ);
+GSN_PRINT_SIGNATURE(printCNTR_START_REF);
+GSN_PRINT_SIGNATURE(printCNTR_START_CONF);
+GSN_PRINT_SIGNATURE(printREAD_NODES_CONF);
+GSN_PRINT_SIGNATURE(printTUX_MAINT_REQ);
+GSN_PRINT_SIGNATURE(printACC_LOCKREQ);
+GSN_PRINT_SIGNATURE(printLQH_TRANSCONF);
+GSN_PRINT_SIGNATURE(printSCAN_FRAGREQ);
+
+GSN_PRINT_SIGNATURE(printCONTINUEB_NDBFS);
+GSN_PRINT_SIGNATURE(printCONTINUEB_DBDIH);
+
#endif
diff --git a/ndb/include/kernel/signaldata/TcContinueB.hpp b/ndb/include/kernel/signaldata/TcContinueB.hpp
index 7a093b457e8..85213791b2a 100644
--- a/ndb/include/kernel/signaldata/TcContinueB.hpp
+++ b/ndb/include/kernel/signaldata/TcContinueB.hpp
@@ -42,7 +42,9 @@ private:
ZWAIT_ABORT_ALL = 14,
ZCHECK_SCAN_ACTIVE_FAILED_LQH = 15,
CHECK_WAIT_DROP_TAB_FAILED_LQH = 16,
- TRIGGER_PENDING = 17
+ TRIGGER_PENDING = 17,
+
+ DelayTCKEYCONF = 18
};
};
diff --git a/ndb/include/kernel/signaldata/TcKeyConf.hpp b/ndb/include/kernel/signaldata/TcKeyConf.hpp
index 27ff344f793..277872b990b 100644
--- a/ndb/include/kernel/signaldata/TcKeyConf.hpp
+++ b/ndb/include/kernel/signaldata/TcKeyConf.hpp
@@ -47,7 +47,8 @@ public:
*/
STATIC_CONST( StaticLength = 5 );
STATIC_CONST( OperationLength = 2 );
-
+ STATIC_CONST( SimpleReadBit = (((Uint32)1) << 31) );
+
private:
/**
diff --git a/ndb/include/kernel/signaldata/TuxBound.hpp b/ndb/include/kernel/signaldata/TuxBound.hpp
index 1f256150573..87ce3c3c098 100644
--- a/ndb/include/kernel/signaldata/TuxBound.hpp
+++ b/ndb/include/kernel/signaldata/TuxBound.hpp
@@ -48,7 +48,6 @@ private:
Uint32 tuxScanPtrI;
/*
* Number of words of bound info included after fixed signal data.
- * Starts with 5 unused words (word 0 is length used by LQH).
*/
Uint32 boundAiLength;
};
diff --git a/ndb/include/kernel/signaldata/UpgradeStartup.hpp b/ndb/include/kernel/signaldata/UpgradeStartup.hpp
index badc7ca0e4d..a4450221c59 100644
--- a/ndb/include/kernel/signaldata/UpgradeStartup.hpp
+++ b/ndb/include/kernel/signaldata/UpgradeStartup.hpp
@@ -1,6 +1,8 @@
#ifndef NDB_UPGRADE_STARTUP
#define NDB_UPGRADE_STARTUP
+class Ndbcntr;
+
struct UpgradeStartup {
static void installEXEC(SimulatedBlock*);
diff --git a/ndb/include/kernel/trigger_definitions.h b/ndb/include/kernel/trigger_definitions.h
index 439d65c6c30..7ce74877de4 100644
--- a/ndb/include/kernel/trigger_definitions.h
+++ b/ndb/include/kernel/trigger_definitions.h
@@ -47,11 +47,11 @@ struct TriggerType {
struct TriggerActionTime {
enum Value {
- TA_BEFORE = 0, // Immediate, before operation
- TA_AFTER = 1, // Immediate, after operation
- TA_DEFERRED = 2, // Before commit
- TA_DETACHED = 3, // After commit in a separate transaction, NYI
- TA_CUSTOM = 4 // Hardcoded per TriggerType
+ TA_BEFORE = 0, /* Immediate, before operation */
+ TA_AFTER = 1, /* Immediate, after operation */
+ TA_DEFERRED = 2, /* Before commit */
+ TA_DETACHED = 3, /* After commit in a separate transaction, NYI */
+ TA_CUSTOM = 4 /* Hardcoded per TriggerType */
};
};
@@ -60,7 +60,7 @@ struct TriggerEvent {
TE_INSERT = 0,
TE_DELETE = 1,
TE_UPDATE = 2,
- TE_CUSTOM = 3 // Hardcoded per TriggerType
+ TE_CUSTOM = 3 /* Hardcoded per TriggerType */
};
};
diff --git a/ndb/include/mgmapi/mgmapi.h b/ndb/include/mgmapi/mgmapi.h
index 44307c3e73c..6dcf58b44e2 100644
--- a/ndb/include/mgmapi/mgmapi.h
+++ b/ndb/include/mgmapi/mgmapi.h
@@ -64,32 +64,32 @@ extern "C" {
* NDB Cluster node types
*/
enum ndb_mgm_node_type {
- NDB_MGM_NODE_TYPE_UNKNOWN = -1, /*/< Node type not known*/
- NDB_MGM_NODE_TYPE_API = NODE_TYPE_API, /*/< An application node (API)*/
- NDB_MGM_NODE_TYPE_NDB = NODE_TYPE_DB, /*/< A database node (DB)*/
- NDB_MGM_NODE_TYPE_MGM = NODE_TYPE_MGM, /*/< A management server node (MGM)*/
- NDB_MGM_NODE_TYPE_REP = NODE_TYPE_REP, ///< A replication node
-
- NDB_MGM_NODE_TYPE_MIN = 0, /*/< Min valid value*/
- NDB_MGM_NODE_TYPE_MAX = 3 /*/< Max valid value*/
+ NDB_MGM_NODE_TYPE_UNKNOWN = -1, /*< Node type not known*/
+ NDB_MGM_NODE_TYPE_API = NODE_TYPE_API,/*< An application node (API)*/
+ NDB_MGM_NODE_TYPE_NDB = NODE_TYPE_DB, /*< A database node (DB)*/
+ NDB_MGM_NODE_TYPE_MGM = NODE_TYPE_MGM,/*< A mgmt server node (MGM)*/
+ NDB_MGM_NODE_TYPE_REP = NODE_TYPE_REP,/*< A replication node */
+
+ NDB_MGM_NODE_TYPE_MIN = 0, /*< Min valid value*/
+ NDB_MGM_NODE_TYPE_MAX = 3 /*< Max valid value*/
};
/**
* Database node status
*/
enum ndb_mgm_node_status {
- NDB_MGM_NODE_STATUS_UNKNOWN = 0, ///< Node status not known
- NDB_MGM_NODE_STATUS_NO_CONTACT = 1, ///< No contact with node
- NDB_MGM_NODE_STATUS_NOT_STARTED = 2, ///< Has not run starting protocol
- NDB_MGM_NODE_STATUS_STARTING = 3, ///< Is running starting protocol
- NDB_MGM_NODE_STATUS_STARTED = 4, ///< Running
- NDB_MGM_NODE_STATUS_SHUTTING_DOWN = 5, ///< Is shutting down
- NDB_MGM_NODE_STATUS_RESTARTING = 6, ///< Is restarting
- NDB_MGM_NODE_STATUS_SINGLEUSER = 7, ///< Maintenance mode
- NDB_MGM_NODE_STATUS_RESUME = 8, ///< Resume mode
-
- NDB_MGM_NODE_STATUS_MIN = 0, ///< Min valid value
- NDB_MGM_NODE_STATUS_MAX = 6 ///< Max valid value
+ NDB_MGM_NODE_STATUS_UNKNOWN = 0, /*< Node status not known*/
+ NDB_MGM_NODE_STATUS_NO_CONTACT = 1, /*< No contact with node*/
+ NDB_MGM_NODE_STATUS_NOT_STARTED = 2, /*< Has not run starting protocol*/
+ NDB_MGM_NODE_STATUS_STARTING = 3, /*< Is running starting protocol*/
+ NDB_MGM_NODE_STATUS_STARTED = 4, /*< Running*/
+ NDB_MGM_NODE_STATUS_SHUTTING_DOWN = 5, /*< Is shutting down*/
+ NDB_MGM_NODE_STATUS_RESTARTING = 6, /*< Is restarting*/
+ NDB_MGM_NODE_STATUS_SINGLEUSER = 7, /*< Maintenance mode*/
+ NDB_MGM_NODE_STATUS_RESUME = 8, /*< Resume mode*/
+
+ NDB_MGM_NODE_STATUS_MIN = 0, /*< Min valid value*/
+ NDB_MGM_NODE_STATUS_MAX = 6 /*< Max valid value*/
};
/**
@@ -122,7 +122,10 @@ extern "C" {
/* Service errors - Single User Mode */
NDB_MGM_COULD_NOT_ENTER_SINGLE_USER_MODE = 4001,
- NDB_MGM_COULD_NOT_EXIT_SINGLE_USER_MODE = 4002
+ NDB_MGM_COULD_NOT_EXIT_SINGLE_USER_MODE = 4002,
+
+ /* Usage errors */
+ NDB_MGM_USAGE_ERROR = 5001
};
struct Ndb_Mgm_Error_Msg {
@@ -158,7 +161,11 @@ extern "C" {
{ NDB_MGM_COULD_NOT_ENTER_SINGLE_USER_MODE,
"Could not enter single user mode" },
{ NDB_MGM_COULD_NOT_EXIT_SINGLE_USER_MODE,
- "Could not exit single user mode" }
+ "Could not exit single user mode" },
+
+ /* Usage errors */
+ { NDB_MGM_USAGE_ERROR,
+ "Usage error" }
};
const int ndb_mgm_noOfErrorMsgs =
@@ -168,24 +175,27 @@ extern "C" {
* Structure returned by ndb_mgm_get_status
*/
struct ndb_mgm_node_state {
- int node_id; ///< NDB Cluster node id
- enum ndb_mgm_node_type node_type; ///< Type of NDB Cluster node
- enum ndb_mgm_node_status node_status; ///< State of node
- int start_phase; ///< Start phase.
- ///< @note Start phase is only
- ///< valid if
- ///< node_type is
- ///< NDB_MGM_NODE_TYPE_NDB and
- ///< node_status is
- ///< NDB_MGM_NODE_STATUS_STARTING
- int dynamic_id; ///< Id for heartbeats and
- ///< master take-over
- ///< (only valid for DB nodes)
- int node_group; ///< Node group of node
- ///< (only valid for DB nodes)
- int version; ///< Internal version number
- int connect_count; ///< No of times node has connected
- ///< or disconnected to the mgm srv
+ int node_id; /*< NDB Cluster node id*/
+ enum ndb_mgm_node_type node_type; /*< Type of NDB Cluster node*/
+ enum ndb_mgm_node_status node_status; /*< State of node*/
+ int start_phase; /*< Start phase.
+ *< @note Start phase is only
+ *< valid if
+ *< node_type is
+ *< NDB_MGM_NODE_TYPE_NDB and
+ *< node_status is
+ *< NDB_MGM_NODE_STATUS_STARTING
+ */
+ int dynamic_id; /*< Id for heartbeats and
+ *< master take-over
+ *< (only valid for DB nodes)
+ */
+ int node_group; /*< Node group of node
+ *< (only valid for DB nodes)*/
+ int version; /*< Internal version number*/
+ int connect_count; /*< No of times node has connected
+ *< or disconnected to the mgm srv
+ */
char connect_address[sizeof("000.000.000.000")+1];
};
@@ -193,9 +203,10 @@ extern "C" {
* Cluster status
*/
struct ndb_mgm_cluster_state {
- int no_of_nodes; ///< No of entries in the
- ///< node_states array
- struct ndb_mgm_node_state ///< An array with node_states
+ int no_of_nodes; /*< No of entries in the
+ *< node_states array
+ */
+ struct ndb_mgm_node_state /*< An array with node_states*/
node_states[1];
const char *hostname;
};
@@ -204,17 +215,18 @@ extern "C" {
* Default reply from the server
*/
struct ndb_mgm_reply {
- int return_code; ///< 0 if successful,
- ///< otherwise error code.
- char message[256]; ///< Error or reply message.
+ int return_code; /*< 0 if successful,
+ *< otherwise error code.
+ */
+ char message[256]; /*< Error or reply message.*/
};
/**
* Default information types
*/
enum ndb_mgm_info {
- NDB_MGM_INFO_CLUSTER, ///< ?
- NDB_MGM_INFO_CLUSTERLOG ///< Cluster log
+ NDB_MGM_INFO_CLUSTER, /*< ?*/
+ NDB_MGM_INFO_CLUSTERLOG /*< Cluster log*/
};
/**
@@ -222,39 +234,47 @@ extern "C" {
* (Used only in the development of NDB Cluster.)
*/
enum ndb_mgm_signal_log_mode {
- NDB_MGM_SIGNAL_LOG_MODE_IN, ///< Log receiving signals
- NDB_MGM_SIGNAL_LOG_MODE_OUT, ///< Log sending signals
- NDB_MGM_SIGNAL_LOG_MODE_INOUT, ///< Log both sending/receiving
- NDB_MGM_SIGNAL_LOG_MODE_OFF ///< Log off
+ NDB_MGM_SIGNAL_LOG_MODE_IN, /*< Log receiving signals */
+ NDB_MGM_SIGNAL_LOG_MODE_OUT, /*< Log sending signals*/
+ NDB_MGM_SIGNAL_LOG_MODE_INOUT, /*< Log both sending/receiving*/
+ NDB_MGM_SIGNAL_LOG_MODE_OFF /*< Log off*/
};
/**
* Log severities (used to filter the cluster log)
*/
enum ndb_mgm_clusterlog_level {
- NDB_MGM_CLUSTERLOG_OFF = 0, ///< Cluster log off
- NDB_MGM_CLUSTERLOG_DEBUG = 1, ///< Used in NDB Cluster
- ///< developement
- NDB_MGM_CLUSTERLOG_INFO = 2, ///< Informational messages
- NDB_MGM_CLUSTERLOG_WARNING = 3, ///< Conditions that are not
- ///< error condition, but
- ///< might require handling
- NDB_MGM_CLUSTERLOG_ERROR = 4, ///< Conditions that should be
- ///< corrected
- NDB_MGM_CLUSTERLOG_CRITICAL = 5, ///< Critical conditions, like
- ///< device errors or out of
- ///< resources
- NDB_MGM_CLUSTERLOG_ALERT = 6, ///< A condition that should be
- ///< corrected immediately,
- ///< such as a corrupted system
- NDB_MGM_CLUSTERLOG_ALL = 7 ///< All severities on
+ NDB_MGM_CLUSTERLOG_OFF = 0, /*< Cluster log off*/
+ NDB_MGM_CLUSTERLOG_DEBUG = 1, /*< Used in NDB Cluster
+ *< developement
+ */
+ NDB_MGM_CLUSTERLOG_INFO = 2, /*< Informational messages*/
+ NDB_MGM_CLUSTERLOG_WARNING = 3, /*< Conditions that are not
+ *< error condition, but
+ *< might require handling
+ */
+ NDB_MGM_CLUSTERLOG_ERROR = 4, /*< Conditions that should be
+ *< corrected
+ */
+ NDB_MGM_CLUSTERLOG_CRITICAL = 5, /*< Critical conditions, like
+ *< device errors or out of
+ *< resources
+ */
+ NDB_MGM_CLUSTERLOG_ALERT = 6, /*< A condition that should be
+ *< corrected immediately,
+ *< such as a corrupted system
+ */
+ NDB_MGM_CLUSTERLOG_ALL = 7 /*< All severities on*/
};
/**
* Log categories
*/
enum ndb_mgm_event_category {
- NDB_MGM_ILLEGAL_EVENT_CATEGORY = -1, ///< Invalid
+ /**
+ * Invalid
+ */
+ NDB_MGM_ILLEGAL_EVENT_CATEGORY = -1,
/**
* Events during all kinds of startups
*/
diff --git a/ndb/include/mgmcommon/LocalConfig.hpp b/ndb/include/mgmcommon/LocalConfig.hpp
index c741b35f482..9ceeffdba36 100644
--- a/ndb/include/mgmcommon/LocalConfig.hpp
+++ b/ndb/include/mgmcommon/LocalConfig.hpp
@@ -53,14 +53,14 @@ struct LocalConfig {
void printUsage() const;
void setError(int lineNumber, const char * _msg);
- bool readConnectString(const char *);
+ bool readConnectString(const char *, const char *info);
bool readFile(const char * file, bool &fopenError);
bool parseLine(char * line, int lineNumber);
bool parseNodeId(const char *buf);
bool parseHostName(const char *buf);
bool parseFileName(const char *buf);
- bool parseString(const char *buf, char *line);
+ bool parseString(const char *buf, BaseString &err);
};
#endif // LocalConfig_H
diff --git a/ndb/include/ndb_global.h b/ndb/include/ndb_global.h
index 3ce37a2edee..c128323241a 100644
--- a/ndb/include/ndb_global.h
+++ b/ndb/include/ndb_global.h
@@ -13,6 +13,9 @@
#undef NDB_WIN32
#endif
+#ifdef _AIX
+#undef _H_STRINGS
+#endif
#include <m_string.h>
#include <m_ctype.h>
#include <ndb_types.h>
diff --git a/ndb/include/ndb_types.h b/ndb/include/ndb_types.h
index 87ebd3d6c6b..a2988dbae78 100644
--- a/ndb/include/ndb_types.h
+++ b/ndb/include/ndb_types.h
@@ -33,7 +33,7 @@ typedef unsigned int UintR;
#ifdef __SIZE_TYPE__
typedef __SIZE_TYPE__ UintPtr;
#else
-#include <my_global.h>
+#include <ndb_global.h>
#ifdef HAVE_STDINT_H
#include <stdint.h>
#endif
diff --git a/ndb/include/ndbapi/Ndb.hpp b/ndb/include/ndbapi/Ndb.hpp
index 550d0c0931a..5ec09269695 100644
--- a/ndb/include/ndbapi/Ndb.hpp
+++ b/ndb/include/ndbapi/Ndb.hpp
@@ -881,6 +881,7 @@ class Table;
class BaseString;
class NdbEventOperation;
class NdbBlob;
+class NdbReceiver;
typedef void (* NdbEventCallback)(NdbEventOperation*, Ndb*, void*);
@@ -1612,7 +1613,6 @@ private:
char prefixName[NDB_MAX_INTERNAL_TABLE_LENGTH];
char * prefixEnd;
- //Table* theTable; // The table object
class NdbImpl * theImpl;
class NdbDictionaryImpl* theDictionary;
class NdbGlobalEventBufferHandle* theGlobalEventBufferHandle;
@@ -1698,10 +1698,13 @@ private:
NdbApiSignal* theCommitAckSignal;
+
+#ifdef POORMANSPURIFY
int cfreeSignals;
int cnewSignals;
int cgetSignals;
int creleaseSignals;
+#endif
static void executeMessage(void*, NdbApiSignal *,
struct LinearSectionPtr ptr[3]);
diff --git a/ndb/include/ndbapi/NdbConnection.hpp b/ndb/include/ndbapi/NdbConnection.hpp
index ef4972f205b..92b940e96f7 100644
--- a/ndb/include/ndbapi/NdbConnection.hpp
+++ b/ndb/include/ndbapi/NdbConnection.hpp
@@ -526,9 +526,8 @@ private:
int sendCOMMIT(); // Send a TC_COMMITREQ signal;
void setGCI(int GCI); // Set the global checkpoint identity
- int OpCompleteFailure(); // Operation Completed with success
- int OpCompleteSuccess(); // Operation Completed with success
-
+ int OpCompleteFailure(Uint8 abortoption);
+ int OpCompleteSuccess();
void CompletedOperations(); // Move active ops to list of completed
void OpSent(); // Operation Sent with success
@@ -649,6 +648,18 @@ private:
Uint32 theNodeSequence; // The sequence no of the db node
bool theReleaseOnClose;
+ /**
+ * handle transaction spanning
+ * multiple TC/db nodes
+ *
+ * 1) Bitmask with used nodes
+ * 2) Bitmask with nodes failed during op
+ */
+ Uint32 m_db_nodes[2];
+ Uint32 m_failed_db_nodes[2];
+
+ int report_node_failure(Uint32 id);
+
// Scan operations
bool m_waitForReply;
NdbIndexScanOperation* m_theFirstScanOperation;
@@ -673,6 +684,9 @@ private:
void printState();
#endif
bool checkState_TransId(const Uint32 * transId) const;
+
+ void remove_list(NdbOperation*& head, NdbOperation*);
+ void define_scan_op(NdbIndexScanOperation*);
};
inline
diff --git a/ndb/include/ndbapi/NdbIndexScanOperation.hpp b/ndb/include/ndbapi/NdbIndexScanOperation.hpp
index 82aed04a9fc..66b3fc9d43b 100644
--- a/ndb/include/ndbapi/NdbIndexScanOperation.hpp
+++ b/ndb/include/ndbapi/NdbIndexScanOperation.hpp
@@ -56,27 +56,11 @@ public:
}
/**
- * @name Define Range Scan
- *
- * A range scan is a scan on an ordered index. The operation is on
- * the index table but tuples are returned from the primary table.
- * The index contains all tuples where at least one index key has not
- * null value.
- *
- * A range scan is currently opened via a normal open scan method.
- * Bounds can be defined for each index key. After setting bounds,
- * usual scan methods can be used (get value, interpreter, take over).
- * These operate on the primary table.
- *
- * @{
- */
-
- /**
* Type of ordered index key bound. The values (0-4) will not change
* and can be used explicitly (e.g. they could be computed).
*/
enum BoundType {
- BoundLE = 0, ///< lower bound,
+ BoundLE = 0, ///< lower bound
BoundLT = 1, ///< lower bound, strict
BoundGE = 2, ///< upper bound
BoundGT = 3, ///< upper bound, strict
@@ -86,20 +70,28 @@ public:
/**
* Define bound on index key in range scan.
*
- * Each index key can have lower and/or upper bound, or can be set
- * equal to a value. The bounds can be defined in any order but
- * a duplicate definition is an error.
+ * Each index key can have lower and/or upper bound. Setting the key
+ * equal to a value defines both upper and lower bounds. The bounds
+ * can be defined in any order. Conflicting definitions is an error.
+ *
+ * For equality, it is better to use BoundEQ instead of the equivalent
+ * pair of BoundLE and BoundGE. This is especially true when table
+ * distribution key is an initial part of the index key.
+ *
+ * The sets of lower and upper bounds must be on initial sequences of
+ * index keys. All but possibly the last bound must be non-strict.
+ * So "a >= 2 and b > 3" is ok but "a > 2 and b >= 3" is not.
*
- * The bounds must specify a single range i.e. they are on an initial
- * sequence of index keys and the condition is equality for all but
- * (at most) the last key which has a lower and/or upper bound.
+ * The scan may currently return tuples for which the bounds are not
+ * satisfied. For example, "a <= 2 and b <= 3" scans the index up to
+ * (a=2, b=3) but also returns any (a=1, b=4).
*
* NULL is treated like a normal value which is less than any not-NULL
- * value and equal to another NULL value. To search for NULL use
+ * value and equal to another NULL value. To compare against NULL use
* setBound with null pointer (0).
*
- * An index stores also all-NULL keys (this may become optional).
- * Doing index scan with empty bound set returns all table tuples.
+ * An index stores also all-NULL keys. Doing index scan with empty
+ * bound set returns all table tuples.
*
* @param attrName Attribute name, alternatively:
* @param anAttrId Index column id (starting from 0)
@@ -117,14 +109,19 @@ public:
*/
int setBound(Uint32 anAttrId, int type, const void* aValue, Uint32 len = 0);
- /** @} *********************************************************************/
+ /**
+ * Reset bounds and put operation in list that will be
+ * sent on next execute
+ */
+ int reset_bounds();
+ bool getSorted() const { return m_ordered; }
private:
NdbIndexScanOperation(Ndb* aNdb);
virtual ~NdbIndexScanOperation();
int setBound(const NdbColumnImpl*, int type, const void* aValue, Uint32 len);
- int saveBoundATTRINFO();
+ int insertBOUNDS(Uint32 * data, Uint32 sz);
virtual int equal_impl(const NdbColumnImpl*, const char*, Uint32);
virtual NdbRecAttr* getValue_impl(const NdbColumnImpl*, char*);
diff --git a/ndb/include/ndbapi/NdbOperation.hpp b/ndb/include/ndbapi/NdbOperation.hpp
index a8bd8b9bfea..8e0294e41e6 100644
--- a/ndb/include/ndbapi/NdbOperation.hpp
+++ b/ndb/include/ndbapi/NdbOperation.hpp
@@ -717,6 +717,8 @@ public:
NotDefined ///< Internal for debugging
};
+ LockMode getLockMode() const { return theLockMode; }
+
protected:
/******************************************************************************
* These are the methods used to create and delete the NdbOperation objects.
@@ -749,7 +751,6 @@ protected:
FinalGetValue,
SubroutineExec,
SubroutineEnd,
- SetBound,
WaitResponse,
WaitCommitResponse,
Finished,
@@ -786,11 +787,6 @@ protected:
int receiveTCKEYREF(NdbApiSignal*);
-
- int receiveTRANSID_AI(const Uint32* aDataPtr, Uint32 aDataLength);
- int receiveREAD_CONF(const Uint32* aDataPtr, Uint32 aDataLength);
-
-
int checkMagicNumber(bool b = true); // Verify correct object
int checkState_TransId(NdbApiSignal* aSignal);
@@ -814,8 +810,6 @@ protected:
int branch_col_null(Uint32 type, Uint32 col, Uint32 Label);
// Handle ATTRINFO signals
- int receiveREAD_AI(Uint32* aDataPtr, Uint32 aLength);
-
int insertATTRINFO(Uint32 aData);
int insertATTRINFOloop(const Uint32* aDataPtr, Uint32 aLength);
@@ -894,7 +888,7 @@ protected:
// currently defined
OperationType theOperationType; // Read Request, Update Req......
- Uint8 theLockMode; // Can be set to WRITE if read operation
+ LockMode theLockMode; // Can be set to WRITE if read operation
OperationStatus theStatus; // The status of the operation.
Uint32 theMagicNumber; // Magic number to verify that object
// is correct
@@ -921,9 +915,6 @@ protected:
Uint16 m_keyInfoGSN;
Uint16 m_attrInfoGSN;
- // saveBoundATTRINFO() moves ATTRINFO here when setBound() is ready
- NdbApiSignal* theBoundATTRINFO;
- Uint32 theTotalBoundAI_Len;
// Blobs in this operation
NdbBlob* theBlobList;
diff --git a/ndb/include/ndbapi/NdbReceiver.hpp b/ndb/include/ndbapi/NdbReceiver.hpp
index b7f73bb618d..b95313db274 100644
--- a/ndb/include/ndbapi/NdbReceiver.hpp
+++ b/ndb/include/ndbapi/NdbReceiver.hpp
@@ -19,8 +19,11 @@
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL // Not part of public interface
#include <ndb_types.h>
+#include <ndb_global.h>
class Ndb;
+class NdbConnection;
+
class NdbReceiver
{
friend class Ndb;
@@ -59,6 +62,7 @@ public:
inline void next(NdbReceiver* next) { m_next = next;}
inline NdbReceiver* next() { return m_next; }
+ void setErrorCode(int);
private:
Uint32 theMagicNumber;
Ndb* m_ndb;
@@ -127,7 +131,8 @@ int
NdbReceiver::execTCOPCONF(Uint32 len){
Uint32 tmp = m_received_result_length;
m_expected_result_length = len;
- return (tmp == len ? 1 : 0);
+ assert(!(tmp && !len));
+ return ((bool)len ^ (bool)tmp ? 0 : 1);
}
inline
diff --git a/ndb/include/ndbapi/NdbResultSet.hpp b/ndb/include/ndbapi/NdbResultSet.hpp
index 483e08179c0..478daf8aad2 100644
--- a/ndb/include/ndbapi/NdbResultSet.hpp
+++ b/ndb/include/ndbapi/NdbResultSet.hpp
@@ -138,7 +138,11 @@ public:
*/
int deleteTuple();
int deleteTuple(NdbConnection* takeOverTransaction);
-
+
+ /**
+ * Get underlying operation
+ */
+ NdbOperation* getOperation();
private:
NdbResultSet(NdbScanOperation*);
@@ -149,4 +153,10 @@ private:
NdbScanOperation* m_operation;
};
+inline
+NdbOperation*
+NdbResultSet::getOperation(){
+ return m_operation;
+}
+
#endif
diff --git a/ndb/include/ndbapi/NdbScanOperation.hpp b/ndb/include/ndbapi/NdbScanOperation.hpp
index e8a4408469c..2e4d173ac75 100644
--- a/ndb/include/ndbapi/NdbScanOperation.hpp
+++ b/ndb/include/ndbapi/NdbScanOperation.hpp
@@ -32,6 +32,7 @@
#include <NdbOperation.hpp>
class NdbBlob;
+class NdbResultSet;
/**
* @class NdbScanOperation
@@ -87,12 +88,13 @@ protected:
CursorType m_cursor_type;
NdbScanOperation(Ndb* aNdb);
- ~NdbScanOperation();
+ virtual ~NdbScanOperation();
int nextResult(bool fetchAllowed = true);
virtual void release();
void closeScan();
+ int close_impl(class TransporterFacade*);
// Overloaded methods from NdbCursorOperation
int executeCursor(int ProcessorId);
@@ -119,6 +121,7 @@ protected:
int prepareSendScan(Uint32 TC_ConnectPtr, Uint64 TransactionId);
int fix_receivers(Uint32 parallel);
+ void reset_receivers(Uint32 parallel, Uint32 ordered);
Uint32* m_array; // containing all arrays below
Uint32 m_allocated_receivers;
NdbReceiver** m_receivers; // All receivers
diff --git a/ndb/include/portlib/NdbCondition.h b/ndb/include/portlib/NdbCondition.h
index fb1f2fcd69e..3d959a0db41 100644
--- a/ndb/include/portlib/NdbCondition.h
+++ b/ndb/include/portlib/NdbCondition.h
@@ -26,21 +26,21 @@ extern "C" {
struct NdbCondition;
-/*
-// Create a condition
-//
-// * returnvalue: pointer to the condition structure
-*/
+/**
+ * Create a condition
+ *
+ * returnvalue: pointer to the condition structure
+ */
struct NdbCondition* NdbCondition_Create(void);
-/*
-// Wait for a condition, allows a thread to wait for
-// a condition and atomically releases the associated mutex.
-//
-// * p_cond: pointer to the condition structure
-// * p_mutex: pointer to the mutex structure
-// * returnvalue: 0 = succeeded, 1 = failed
-*/
+/**
+ * Wait for a condition, allows a thread to wait for
+ * a condition and atomically releases the associated mutex.
+ *
+ * p_cond: pointer to the condition structure
+ * p_mutex: pointer to the mutex structure
+ * returnvalue: 0 = succeeded, 1 = failed
+ */
int NdbCondition_Wait(struct NdbCondition* p_cond,
NdbMutex* p_mutex);
@@ -60,29 +60,29 @@ NdbCondition_WaitTimeout(struct NdbCondition* p_cond,
int msec);
-/*
-// Signal a condition
-//
-// * p_cond: pointer to the condition structure
-// * returnvalue: 0 = succeeded, 1 = failed
-*/
+/**
+ * Signal a condition
+ *
+ * p_cond: pointer to the condition structure
+ * returnvalue: 0 = succeeded, 1 = failed
+ */
int NdbCondition_Signal(struct NdbCondition* p_cond);
-/*
-// Broadcast a condition
-//
-// * p_cond: pointer to the condition structure
-// * returnvalue: 0 = succeeded, 1 = failed
-*/
+/**
+ * Broadcast a condition
+ *
+ * p_cond: pointer to the condition structure
+ * returnvalue: 0 = succeeded, 1 = failed
+ */
int NdbCondition_Broadcast(struct NdbCondition* p_cond);
-/*
-// Destroy a condition
-//
-// * p_cond: pointer to the condition structure
-// * returnvalue: 0 = succeeded, 1 = failed
-*/
+/**
+ * Destroy a condition
+ *
+ * p_cond: pointer to the condition structure
+ * returnvalue: 0 = succeeded, 1 = failed
+ */
int NdbCondition_Destroy(struct NdbCondition* p_cond);
#ifdef __cplusplus
diff --git a/ndb/include/portlib/PortDefs.h b/ndb/include/portlib/PortDefs.h
index 5e24e08ec61..b61bb627e65 100644
--- a/ndb/include/portlib/PortDefs.h
+++ b/ndb/include/portlib/PortDefs.h
@@ -28,35 +28,35 @@
struct tms
{
- time_t tms_utime; // user time
- time_t tms_stime; // system time
- time_t tms_cutime; // user time of children
- time_t tms_cstime; // system time of children
+ time_t tms_utime; /* user time */
+ time_t tms_stime; /* system time */
+ time_t tms_cutime; /* user time of children */
+ time_t tms_cstime; /* system time of children */
};
struct timespec
{
- long tv_sec; // Seconds
- long tv_nsec; // Nanoseconds
+ long tv_sec; /* Seconds */
+ long tv_nsec; /* Nanoseconds */
};
#define strcasecmp(a,b) _strcmpi(a,b)
- // Exports a WIN32 getopt function
+/* Exports a WIN32 getopt function */
extern int optind;
extern char *optarg;
int getopt(int, char **, char *opts);
-#endif // NDB_WIN32
+#endif /* NDB_WIN32 */
#ifdef NDB_ALPHA
-#ifdef NDB_GCC // only for NDB_ALPHA
+#ifdef NDB_GCC /* only for NDB_ALPHA */
extern int gnuShouldNotUseRPCC();
#define RPCC() gnuShouldNotUseRPCC();
#else
#ifdef NDB_WIN32
#ifdef __cplusplus
extern "C" {
-#endif //__cplusplus
+#endif /* __cplusplus */
u_int64 __asm(char *, ...);
double __dasm(char *, ...);
float __fasm(char *, ...);
@@ -65,32 +65,32 @@ extern "C" {
int __ADD_ATOMIC_LONG2(void *, int);
#ifdef __cplusplus
};
-#endif //__cplusplus
+#endif /* __cplusplus */
#pragma intrinsic (__asm, __dasm, __fasm)
#pragma intrinsic(_ReleaseSpinLock, _AcquireSpinLock)
#pragma intrinsic(__ADD_ATOMIC_LONG2)
-#endif // NDB_WIN32
+#endif /* NDB_WIN32 */
#define RPCC() ((int)__asm(" rpcc v0;"))
#define MB() __asm(" mb;");
#define WMB() __asm(" wmb;");
#ifdef USE_INITIALSP
#define IS_IP() (__asm(" mov sp,v0;") < IPinitialSP)
-#else // USE_INITIALSP
+#else /* USE_INITIALSP */
#define IS_IP() (((__asm(" rpcc v0;") >> 32) & 0x7) == IP_CPU)
#endif
-#endif //NDB_GCC
-#else // NDB_ALPHA
+#endif /* NDB_GCC */
+#else /* NDB_ALPHA */
#if defined NDB_SPARC
-#define MB() asm ("membar 0x0;"); // LoadLoad
-#define WMB() asm ("membar 0x3;"); // StoreStore
-#else // NDB_SPARC
+#define MB() asm ("membar 0x0;"); /* LoadLoad */
+#define WMB() asm ("membar 0x3;"); /* StoreStore */
+#else /* NDB_SPARC */
#define MB()
#define WMB()
-#endif // NDB_SPARC
+#endif /* NDB_SPARC */
#define IS_IP() (1==1)
extern int shouldNotUseRPCC();
#define RPCC() shouldNotUseRPCC();
-#endif // NDB_ALPHA
+#endif /* NDB_ALPHA */
#endif
diff --git a/ndb/include/portlib/prefetch.h b/ndb/include/portlib/prefetch.h
index d663dd4c40d..729c80bd93e 100644
--- a/ndb/include/portlib/prefetch.h
+++ b/ndb/include/portlib/prefetch.h
@@ -42,7 +42,7 @@ inline void prefetch(void* p)
{
#ifdef NDB_ALPHA
__asm(" ldl r31,0(a0);", p);
-#endif // NDB_ALPHA
+#endif /* NDB_ALPHA */
#ifdef NDB_FORTE6
sparc_prefetch_read_once(p);
#else
@@ -54,7 +54,7 @@ inline void writehint(void* p)
{
#ifdef NDB_ALPHA
__asm(" wh64 (a0);", p);
-#endif // NDB_ALPHA
+#endif /* NDB_ALPHA */
#ifdef NDB_FORTE6
sparc_prefetch_write_once(p);
#else
diff --git a/ndb/include/util/BaseString.hpp b/ndb/include/util/BaseString.hpp
index a1bb91ea9c5..066a24f294e 100644
--- a/ndb/include/util/BaseString.hpp
+++ b/ndb/include/util/BaseString.hpp
@@ -177,6 +177,12 @@ public:
* Trim string from <i>delim</i>
*/
static char* trim(char * src, const char * delim);
+
+ /**
+ * snprintf on some platforms need special treatment
+ */
+ static int snprintf(char *str, size_t size, const char *format, ...);
+ static int vsnprintf(char *str, size_t size, const char *format, va_list ap);
private:
char* m_chr;
unsigned m_len;
diff --git a/ndb/include/util/basestring_vsnprintf.h b/ndb/include/util/basestring_vsnprintf.h
new file mode 100644
index 00000000000..7c804f22841
--- /dev/null
+++ b/ndb/include/util/basestring_vsnprintf.h
@@ -0,0 +1,29 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef BASESTRING_VSNPRINTF_H
+#define BASESTRING_VSNPRINTF_H
+#include <stdarg.h>
+#if defined(__cplusplus)
+extern "C"
+{
+#endif
+int basestring_snprintf(char*, size_t, const char*, ...);
+int basestring_vsnprintf(char*,size_t, const char*,va_list);
+#if defined(__cplusplus)
+}
+#endif
+#endif
diff --git a/ndb/src/common/debugger/DebuggerNames.cpp b/ndb/src/common/debugger/DebuggerNames.cpp
index b2a79e2385b..8571b8ece86 100644
--- a/ndb/src/common/debugger/DebuggerNames.cpp
+++ b/ndb/src/common/debugger/DebuggerNames.cpp
@@ -15,6 +15,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include <ndb_global.h>
+#include <BaseString.hpp>
#include "DebuggerNames.hpp"
@@ -53,14 +54,13 @@ initSignalNames(const char * dst[], const GsnName src[], unsigned short len){
static
int
initSignalPrinters(SignalDataPrintFunction dst[],
- const NameFunctionPair src[],
- unsigned short len){
+ const NameFunctionPair src[]){
unsigned i;
for(i = 0; i<=MAX_GSN; i++)
dst[i] = 0;
- for(i = 0; i<len; i++){
- unsigned short gsn = src[i].gsn;
+ unsigned short gsn;
+ for(i = 0; (gsn = src[i].gsn) > 0; i++){
SignalDataPrintFunction fun = src[i].function;
if(dst[gsn] != 0 && fun != 0){
@@ -107,8 +107,7 @@ xxx_DUMMY_SIGNAL_NAMES_xxx = initSignalNames(localSignalNames,
NO_OF_SIGNAL_NAMES);
static const int
xxx_DUMMY_PRINT_FUNCTIONS_xxx = initSignalPrinters(localPrintFunctions,
- SignalDataPrintFunctions,
- NO_OF_PRINT_FUNCTIONS);
+ SignalDataPrintFunctions);
static const int
xxx_DUMMY_BLOCK_NAMES_xxx = initBlockNames(localBlockNames,
@@ -133,7 +132,7 @@ getBlockName(unsigned short blockNo, const char * ret){
return localBlockNames[blockNo-MIN_BLOCK_NO];
if (ret == 0) {
static char buf[20];
- snprintf(buf, sizeof(buf), "BLOCK#%d", (int)blockNo);
+ BaseString::snprintf(buf, sizeof(buf), "BLOCK#%d", (int)blockNo);
return buf;
}
return ret;
diff --git a/ndb/src/common/debugger/EventLogger.cpp b/ndb/src/common/debugger/EventLogger.cpp
index 03445622e6a..8a09be9a0a7 100644
--- a/ndb/src/common/debugger/EventLogger.cpp
+++ b/ndb/src/common/debugger/EventLogger.cpp
@@ -127,7 +127,7 @@ EventLogger::getText(char * m_text, size_t m_text_len,
// TODO: Change the switch implementation...
char theNodeId[32];
if (nodeId != 0){
- ::snprintf(theNodeId, 32, "Node %u: ", nodeId);
+ BaseString::snprintf(theNodeId, 32, "Node %u: ", nodeId);
} else {
theNodeId[0] = 0;
}
@@ -135,13 +135,13 @@ EventLogger::getText(char * m_text, size_t m_text_len,
EventReport::EventType eventType = (EventReport::EventType)type;
switch (eventType){
case EventReport::Connected:
- ::snprintf(m_text, m_text_len,
+ BaseString::snprintf(m_text, m_text_len,
"%sNode %u Connected",
theNodeId,
theData[1]);
break;
case EventReport::ConnectedApiVersion:
- ::snprintf(m_text, m_text_len,
+ BaseString::snprintf(m_text, m_text_len,
"%sNode %u: API version %d.%d.%d",
theNodeId,
theData[1],
@@ -150,7 +150,7 @@ EventLogger::getText(char * m_text, size_t m_text_len,
getBuild(theData[2]));
break;
case EventReport::Disconnected:
- ::snprintf(m_text, m_text_len,
+ BaseString::snprintf(m_text, m_text_len,
"%sNode %u Disconnected",
theNodeId,
theData[1]);
@@ -159,7 +159,7 @@ EventLogger::getText(char * m_text, size_t m_text_len,
//-----------------------------------------------------------------------
// REPORT communication to node closed.
//-----------------------------------------------------------------------
- ::snprintf(m_text, m_text_len,
+ BaseString::snprintf(m_text, m_text_len,
"%sCommunication to Node %u closed",
theNodeId,
theData[1]);
@@ -168,7 +168,7 @@ EventLogger::getText(char * m_text, size_t m_text_len,
//-----------------------------------------------------------------------
// REPORT communication to node opened.
//-----------------------------------------------------------------------
- ::snprintf(m_text, m_text_len,
+ BaseString::snprintf(m_text, m_text_len,
"%sCommunication to Node %u opened",
theNodeId,
theData[1]);
@@ -177,7 +177,7 @@ EventLogger::getText(char * m_text, size_t m_text_len,
//-----------------------------------------------------------------------
// Start of NDB has been initiated.
//-----------------------------------------------------------------------
- ::snprintf(m_text, m_text_len,
+ BaseString::snprintf(m_text, m_text_len,
"%sStart initiated (version %d.%d.%d)",
theNodeId ,
getMajor(theData[1]),
@@ -185,13 +185,13 @@ EventLogger::getText(char * m_text, size_t m_text_len,
getBuild(theData[1]));
break;
case EventReport::NDBStopStarted:
- ::snprintf(m_text, m_text_len,
+ BaseString::snprintf(m_text, m_text_len,
"%s%s shutdown initiated",
theNodeId,
(theData[1] == 1 ? "Cluster" : "Node"));
break;
case EventReport::NDBStopAborted:
- ::snprintf(m_text, m_text_len,
+ BaseString::snprintf(m_text, m_text_len,
"%sNode shutdown aborted",
theNodeId);
break;
@@ -199,7 +199,7 @@ EventLogger::getText(char * m_text, size_t m_text_len,
//-----------------------------------------------------------------------
// Start of NDB has been completed.
//-----------------------------------------------------------------------
- ::snprintf(m_text, m_text_len,
+ BaseString::snprintf(m_text, m_text_len,
"%sStarted (version %d.%d.%d)",
theNodeId ,
getMajor(theData[1]),
@@ -211,7 +211,7 @@ EventLogger::getText(char * m_text, size_t m_text_len,
//-----------------------------------------------------------------------
// STTORRY recevied after restart finished.
//-----------------------------------------------------------------------
- ::snprintf(m_text, m_text_len,
+ BaseString::snprintf(m_text, m_text_len,
"%sSTTORRY received after restart finished",
theNodeId);
break;
@@ -237,7 +237,7 @@ EventLogger::getText(char * m_text, size_t m_text_len,
type = "";
break;
default:{
- ::snprintf(m_text, m_text_len,
+ BaseString::snprintf(m_text, m_text_len,
"%sStart phase %u completed (unknown = %d)",
theNodeId,
theData[1],
@@ -245,7 +245,7 @@ EventLogger::getText(char * m_text, size_t m_text_len,
return m_text;
}
}
- ::snprintf(m_text, m_text_len,
+ BaseString::snprintf(m_text, m_text_len,
"%sStart phase %u completed %s",
theNodeId,
theData[1],
@@ -254,7 +254,7 @@ EventLogger::getText(char * m_text, size_t m_text_len,
break;
}
case EventReport::CM_REGCONF:
- ::snprintf(m_text, m_text_len,
+ BaseString::snprintf(m_text, m_text_len,
"%sCM_REGCONF president = %u, own Node = %u, our dynamic id = %u"
,
theNodeId,
@@ -286,7 +286,7 @@ EventLogger::getText(char * m_text, size_t m_text_len,
break;
}//switch
- ::snprintf(m_text, m_text_len,
+ BaseString::snprintf(m_text, m_text_len,
"%sCM_REGREF from Node %u to our Node %u. Cause = %s",
theNodeId,
theData[2],
@@ -298,7 +298,7 @@ EventLogger::getText(char * m_text, size_t m_text_len,
//-----------------------------------------------------------------------
// REPORT Node Restart copied a fragment.
//-----------------------------------------------------------------------
- ::snprintf(m_text,
+ BaseString::snprintf(m_text,
m_text_len,
"%sWe are Node %u with dynamic ID %u, our left neighbour "
"is Node %u, our right is Node %u",
@@ -315,13 +315,13 @@ EventLogger::getText(char * m_text, size_t m_text_len,
if (theData[1] == 0)
{
if (theData[3] != 0) {
- ::snprintf(m_text, m_text_len,
+ BaseString::snprintf(m_text, m_text_len,
"%sNode %u completed failure of Node %u",
theNodeId,
theData[3],
theData[2]);
} else {
- ::snprintf(m_text, m_text_len,
+ BaseString::snprintf(m_text, m_text_len,
"%sAll nodes completed failure of Node %u",
theNodeId,
theData[2]);
@@ -338,7 +338,7 @@ EventLogger::getText(char * m_text, size_t m_text_len,
line = "DBLQH";
}
- ::snprintf(m_text, m_text_len,
+ BaseString::snprintf(m_text, m_text_len,
"%sNode failure of %u %s completed",
theNodeId,
theData[2],
@@ -346,7 +346,7 @@ EventLogger::getText(char * m_text, size_t m_text_len,
}
break;
case EventReport::NODE_FAILREP:
- ::snprintf(m_text,
+ BaseString::snprintf(m_text,
m_text_len,
"%sNode %u has failed. The Node state at failure "
"was %u",
@@ -366,41 +366,41 @@ EventLogger::getText(char * m_text, size_t m_text_len,
const unsigned state = sd->code >> 16;
switch (code) {
case ArbitCode::ThreadStart:
- ::snprintf(m_text, m_text_len,
+ BaseString::snprintf(m_text, m_text_len,
"%sPresident restarts arbitration thread [state=%u]",
theNodeId, state);
break;
case ArbitCode::PrepPart2:
sd->ticket.getText(ticketText, sizeof(ticketText));
- ::snprintf(m_text, m_text_len,
+ BaseString::snprintf(m_text, m_text_len,
"%sPrepare arbitrator node %u [ticket=%s]",
theNodeId, sd->node, ticketText);
break;
case ArbitCode::PrepAtrun:
sd->ticket.getText(ticketText, sizeof(ticketText));
- ::snprintf(m_text, m_text_len,
+ BaseString::snprintf(m_text, m_text_len,
"%sReceive arbitrator node %u [ticket=%s]",
theNodeId, sd->node, ticketText);
break;
case ArbitCode::ApiStart:
sd->ticket.getText(ticketText, sizeof(ticketText));
- ::snprintf(m_text, m_text_len,
+ BaseString::snprintf(m_text, m_text_len,
"%sStarted arbitrator node %u [ticket=%s]",
theNodeId, sd->node, ticketText);
break;
case ArbitCode::ApiFail:
- ::snprintf(m_text, m_text_len,
+ BaseString::snprintf(m_text, m_text_len,
"%sLost arbitrator node %u - process failure [state=%u]",
theNodeId, sd->node, state);
break;
case ArbitCode::ApiExit:
- ::snprintf(m_text, m_text_len,
+ BaseString::snprintf(m_text, m_text_len,
"%sLost arbitrator node %u - process exit [state=%u]",
theNodeId, sd->node, state);
break;
default:
ArbitCode::getErrText(code, errText, sizeof(errText));
- ::snprintf(m_text, m_text_len,
+ BaseString::snprintf(m_text, m_text_len,
"%sLost arbitrator node %u - %s [state=%u]",
theNodeId, sd->node, errText, state);
break;
@@ -417,48 +417,48 @@ EventLogger::getText(char * m_text, size_t m_text_len,
const unsigned state = sd->code >> 16;
switch (code) {
case ArbitCode::LoseNodes:
- ::snprintf(m_text, m_text_len,
+ BaseString::snprintf(m_text, m_text_len,
"%sArbitration check lost - less than 1/2 nodes left",
theNodeId);
break;
case ArbitCode::WinGroups:
- ::snprintf(m_text, m_text_len,
+ BaseString::snprintf(m_text, m_text_len,
"%sArbitration check won - node group majority",
theNodeId);
break;
case ArbitCode::LoseGroups:
- ::snprintf(m_text, m_text_len,
+ BaseString::snprintf(m_text, m_text_len,
"%sArbitration check lost - missing node group",
theNodeId);
break;
case ArbitCode::Partitioning:
- ::snprintf(m_text, m_text_len,
+ BaseString::snprintf(m_text, m_text_len,
"%sNetwork partitioning - arbitration required",
theNodeId);
break;
case ArbitCode::WinChoose:
- ::snprintf(m_text, m_text_len,
+ BaseString::snprintf(m_text, m_text_len,
"%sArbitration won - positive reply from node %u",
theNodeId, sd->node);
break;
case ArbitCode::LoseChoose:
- ::snprintf(m_text, m_text_len,
+ BaseString::snprintf(m_text, m_text_len,
"%sArbitration lost - negative reply from node %u",
theNodeId, sd->node);
break;
case ArbitCode::LoseNorun:
- ::snprintf(m_text, m_text_len,
+ BaseString::snprintf(m_text, m_text_len,
"%sNetwork partitioning - no arbitrator available",
theNodeId);
break;
case ArbitCode::LoseNocfg:
- ::snprintf(m_text, m_text_len,
+ BaseString::snprintf(m_text, m_text_len,
"%sNetwork partitioning - no arbitrator configured",
theNodeId);
break;
default:
ArbitCode::getErrText(code, errText, sizeof(errText));
- ::snprintf(m_text, m_text_len,
+ BaseString::snprintf(m_text, m_text_len,
"%sArbitration failure - %s [state=%u]",
theNodeId, errText, state);
break;
@@ -470,7 +470,7 @@ EventLogger::getText(char * m_text, size_t m_text_len,
// This event reports that a global checkpoint has been started and this
// node is the master of this global checkpoint.
//-----------------------------------------------------------------------
- ::snprintf(m_text,
+ BaseString::snprintf(m_text,
m_text_len,
"%sGlobal checkpoint %u started",
theNodeId,
@@ -481,7 +481,7 @@ EventLogger::getText(char * m_text, size_t m_text_len,
// This event reports that a global checkpoint has been completed on this
// node and the node is the master of this global checkpoint.
//-----------------------------------------------------------------------
- ::snprintf(m_text, m_text_len,
+ BaseString::snprintf(m_text, m_text_len,
"%sGlobal checkpoint %u completed",
theNodeId,
theData[1]);
@@ -491,7 +491,7 @@ EventLogger::getText(char * m_text, size_t m_text_len,
// This event reports that a local checkpoint has been started and this
// node is the master of this local checkpoint.
//-----------------------------------------------------------------------
- ::snprintf(m_text,
+ BaseString::snprintf(m_text,
m_text_len,
"%sLocal checkpoint %u started. "
"Keep GCI = %u oldest restorable GCI = %u",
@@ -505,7 +505,7 @@ EventLogger::getText(char * m_text, size_t m_text_len,
// This event reports that a local checkpoint has been completed on this
// node and the node is the master of this local checkpoint.
//-----------------------------------------------------------------------
- ::snprintf(m_text,
+ BaseString::snprintf(m_text,
m_text_len,
"%sLocal checkpoint %u completed",
theNodeId,
@@ -515,14 +515,14 @@ EventLogger::getText(char * m_text, size_t m_text_len,
//-----------------------------------------------------------------------
// This event reports that a table has been created.
//-----------------------------------------------------------------------
- ::snprintf(m_text, m_text_len,
+ BaseString::snprintf(m_text, m_text_len,
"%sTable with ID = %u created",
theNodeId,
theData[1]);
break;
case EventReport::LCPStoppedInCalcKeepGci:
if (theData[1] == 0)
- ::snprintf(m_text, m_text_len,
+ BaseString::snprintf(m_text, m_text_len,
"%sLocal Checkpoint stopped in CALCULATED_KEEP_GCI",
theNodeId);
break;
@@ -530,7 +530,7 @@ EventLogger::getText(char * m_text, size_t m_text_len,
//-----------------------------------------------------------------------
// REPORT Node Restart completed copy of dictionary information.
//-----------------------------------------------------------------------
- ::snprintf(m_text,
+ BaseString::snprintf(m_text,
m_text_len,
"%sNode restart completed copy of dictionary information",
theNodeId);
@@ -539,7 +539,7 @@ EventLogger::getText(char * m_text, size_t m_text_len,
//-----------------------------------------------------------------------
// REPORT Node Restart completed copy of distribution information.
//-----------------------------------------------------------------------
- ::snprintf(m_text,
+ BaseString::snprintf(m_text,
m_text_len,
"%sNode restart completed copy of distribution information",
theNodeId);
@@ -548,7 +548,7 @@ EventLogger::getText(char * m_text, size_t m_text_len,
//-----------------------------------------------------------------------
// REPORT Node Restart is starting to copy the fragments.
//-----------------------------------------------------------------------
- ::snprintf(m_text,
+ BaseString::snprintf(m_text,
m_text_len,
"%sNode restart starting to copy the fragments "
"to Node %u",
@@ -559,7 +559,7 @@ EventLogger::getText(char * m_text, size_t m_text_len,
//-----------------------------------------------------------------------
// REPORT Node Restart copied a fragment.
//-----------------------------------------------------------------------
- ::snprintf(m_text,
+ BaseString::snprintf(m_text,
m_text_len,
"%sTable ID = %u, fragment ID = %u have been copied "
"to Node %u",
@@ -569,7 +569,7 @@ EventLogger::getText(char * m_text, size_t m_text_len,
theData[1]);
break;
case EventReport::NR_CopyFragsCompleted:
- ::snprintf(m_text,
+ BaseString::snprintf(m_text,
m_text_len,
"%sNode restart completed copying the fragments "
"to Node %u",
@@ -577,7 +577,7 @@ EventLogger::getText(char * m_text, size_t m_text_len,
theData[1]);
break;
case EventReport::LCPFragmentCompleted:
- ::snprintf(m_text,
+ BaseString::snprintf(m_text,
m_text_len,
"%sTable ID = %u, fragment ID = %u has completed LCP "
"on Node %u",
@@ -590,7 +590,7 @@ EventLogger::getText(char * m_text, size_t m_text_len,
// -------------------------------------------------------------------
// Report information about transaction activity once per 10 seconds.
// -------------------------------------------------------------------
- ::snprintf(m_text,
+ BaseString::snprintf(m_text,
m_text_len,
"%sTrans. Count = %u, Commit Count = %u, "
"Read Count = %u, Simple Read Count = %u,\n"
@@ -610,7 +610,7 @@ EventLogger::getText(char * m_text, size_t m_text_len,
theData[10]);
break;
case EventReport::OperationReportCounters:
- ::snprintf(m_text, m_text_len,
+ BaseString::snprintf(m_text, m_text_len,
"%sOperations=%u",
theNodeId,
theData[1]);
@@ -619,7 +619,7 @@ EventLogger::getText(char * m_text, size_t m_text_len,
//-----------------------------------------------------------------------
// REPORT Undo Logging blocked due to buffer near to overflow.
//-----------------------------------------------------------------------
- ::snprintf(m_text,
+ BaseString::snprintf(m_text,
m_text_len,
"%sACC Blocked %u and TUP Blocked %u times last second",
theNodeId,
@@ -628,7 +628,7 @@ EventLogger::getText(char * m_text, size_t m_text_len,
break;
case EventReport::TransporterError:
case EventReport::TransporterWarning:
- ::snprintf(m_text,
+ BaseString::snprintf(m_text,
m_text_len,
"%sTransporter to node %d reported error 0x%x",
theNodeId,
@@ -639,7 +639,7 @@ EventLogger::getText(char * m_text, size_t m_text_len,
//-----------------------------------------------------------------------
// REPORT Undo Logging blocked due to buffer near to overflow.
//-----------------------------------------------------------------------
- ::snprintf(m_text,
+ BaseString::snprintf(m_text,
m_text_len,
"%sNode %d missed heartbeat %d",
theNodeId,
@@ -650,21 +650,21 @@ EventLogger::getText(char * m_text, size_t m_text_len,
//-----------------------------------------------------------------------
// REPORT Undo Logging blocked due to buffer near to overflow.
//-----------------------------------------------------------------------
- ::snprintf(m_text,
+ BaseString::snprintf(m_text,
m_text_len,
"%sNode %d declared dead due to missed heartbeat",
theNodeId,
theData[1]);
break;
case EventReport::JobStatistic:
- ::snprintf(m_text,
+ BaseString::snprintf(m_text,
m_text_len,
"%sMean loop Counter in doJob last 8192 times = %u",
theNodeId,
theData[1]);
break;
case EventReport::SendBytesStatistic:
- ::snprintf(m_text,
+ BaseString::snprintf(m_text,
m_text_len,
"%sMean send size to Node = %d last 4096 sends = %u bytes",
theNodeId,
@@ -672,7 +672,7 @@ EventLogger::getText(char * m_text, size_t m_text_len,
theData[2]);
break;
case EventReport::ReceiveBytesStatistic:
- ::snprintf(m_text,
+ BaseString::snprintf(m_text,
m_text_len,
"%sMean receive size to Node = %d last 4096 sends = %u bytes",
theNodeId,
@@ -680,14 +680,14 @@ EventLogger::getText(char * m_text, size_t m_text_len,
theData[2]);
break;
case EventReport::SentHeartbeat:
- ::snprintf(m_text,
+ BaseString::snprintf(m_text,
m_text_len,
"%sNode Sent Heartbeat to node = %d",
theNodeId,
theData[1]);
break;
case EventReport::CreateLogBytes:
- ::snprintf(m_text,
+ BaseString::snprintf(m_text,
m_text_len,
"%sLog part %u, log file %u, MB %u",
theNodeId,
@@ -696,7 +696,7 @@ EventLogger::getText(char * m_text, size_t m_text_len,
theData[3]);
break;
case EventReport::StartLog:
- ::snprintf(m_text,
+ BaseString::snprintf(m_text,
m_text_len,
"%sLog part %u, start MB %u, stop MB %u, last GCI, log exec %u",
theNodeId,
@@ -706,7 +706,7 @@ EventLogger::getText(char * m_text, size_t m_text_len,
theData[4]);
break;
case EventReport::StartREDOLog:
- ::snprintf(m_text,
+ BaseString::snprintf(m_text,
m_text_len,
"%sNode: %d StartLog: [GCI Keep: %d LastCompleted: %d NewestRestorable: %d]",
theNodeId,
@@ -723,7 +723,7 @@ EventLogger::getText(char * m_text, size_t m_text_len,
line = "DBACC";
}
- ::snprintf(m_text,
+ BaseString::snprintf(m_text,
m_text_len,
"%s UNDO %s %d [%d %d %d %d %d %d %d %d %d]",
theNodeId,
@@ -741,36 +741,36 @@ EventLogger::getText(char * m_text, size_t m_text_len,
}
break;
case EventReport::InfoEvent:
- ::snprintf(m_text,
+ BaseString::snprintf(m_text,
m_text_len,
"%s%s",
theNodeId,
(char *)&theData[1]);
break;
case EventReport::WarningEvent:
- ::snprintf(m_text,
+ BaseString::snprintf(m_text,
m_text_len,
"%s%s",
theNodeId,
(char *)&theData[1]);
break;
case EventReport::GCP_TakeoverStarted:
- ::snprintf(m_text,
+ BaseString::snprintf(m_text,
m_text_len,
"%sGCP Take over started", theNodeId);
break;
case EventReport::GCP_TakeoverCompleted:
- ::snprintf(m_text,
+ BaseString::snprintf(m_text,
m_text_len,
"%sGCP Take over completed", theNodeId);
break;
case EventReport::LCP_TakeoverStarted:
- ::snprintf(m_text,
+ BaseString::snprintf(m_text,
m_text_len,
"%sLCP Take over started", theNodeId);
break;
case EventReport::LCP_TakeoverCompleted:
- ::snprintf(m_text,
+ BaseString::snprintf(m_text,
m_text_len,
"%sLCP Take over completed (state = %d)",
theNodeId, theData[1]);
@@ -783,7 +783,7 @@ EventLogger::getText(char * m_text, size_t m_text_len,
const int block = theData[5];
const int percent = (used*100)/total;
- ::snprintf(m_text, m_text_len,
+ BaseString::snprintf(m_text, m_text_len,
"%s%s usage %s %d%s(%d %dK pages of total %d)",
theNodeId,
(block==DBACC ? "Index" : (block == DBTUP ?"Data":"<unknown>")),
@@ -802,7 +802,7 @@ EventLogger::getText(char * m_text, size_t m_text_len,
const int subId = theData[2];
const int subKey = theData[3];
const int err = theData[4];
- ::snprintf(m_text, m_text_len,
+ BaseString::snprintf(m_text, m_text_len,
"Grep::SSCoord: Created subscription id"
" (subId=%d,SubKey=%d)"
" Return code: %d.",
@@ -816,7 +816,7 @@ EventLogger::getText(char * m_text, size_t m_text_len,
const int subId = theData[2];
const int subKey = theData[3];
const int err = theData[4];
- ::snprintf(m_text, m_text_len,
+ BaseString::snprintf(m_text, m_text_len,
"Grep::PSCoord: Created subscription id"
" (subId=%d,SubKey=%d)"
" Return code: %d.",
@@ -831,7 +831,7 @@ EventLogger::getText(char * m_text, size_t m_text_len,
const int subKey = theData[3];
const int err = theData[4];
const int nodegrp = theData[5];
- ::snprintf(m_text, m_text_len,
+ BaseString::snprintf(m_text, m_text_len,
"Grep::SSCoord: Created subscription using"
" (subId=%d,SubKey=%d)"
" in primary system. Primary system has %d nodegroup(s)."
@@ -847,7 +847,7 @@ EventLogger::getText(char * m_text, size_t m_text_len,
const int subId = theData[2];
const int subKey = theData[3];
const int err = theData[4];
- ::snprintf(m_text, m_text_len,
+ BaseString::snprintf(m_text, m_text_len,
"Grep::PSCoord: All participants have created "
"subscriptions"
" using (subId=%d,SubKey=%d)."
@@ -862,7 +862,7 @@ EventLogger::getText(char * m_text, size_t m_text_len,
const int subId = theData[2];
const int subKey = theData[3];
const int err = theData[4];
- ::snprintf(m_text, m_text_len,
+ BaseString::snprintf(m_text, m_text_len,
"Grep::SSCoord: Logging started on meta data changes."
" using (subId=%d,SubKey=%d)"
" Return code: %d",
@@ -876,7 +876,7 @@ EventLogger::getText(char * m_text, size_t m_text_len,
const int subId = theData[2];
const int subKey = theData[3];
const int err = theData[4];
- ::snprintf(m_text, m_text_len,
+ BaseString::snprintf(m_text, m_text_len,
"Grep::PSCoord: All participants have started "
"logging meta data"
" changes on the subscription subId=%d,SubKey=%d) "
@@ -891,7 +891,7 @@ EventLogger::getText(char * m_text, size_t m_text_len,
const int subId = theData[2];
const int subKey = theData[3];
const int err = theData[4];
- ::snprintf(m_text, m_text_len,
+ BaseString::snprintf(m_text, m_text_len,
"Grep::SSCoord: Logging started on table data changes "
" using (subId=%d,SubKey=%d)"
" Return code: %d",
@@ -905,7 +905,7 @@ EventLogger::getText(char * m_text, size_t m_text_len,
const int subId = theData[2];
const int subKey = theData[3];
const int err = theData[4];
- ::snprintf(m_text, m_text_len,
+ BaseString::snprintf(m_text, m_text_len,
"Grep::PSCoord: All participants have started logging "
"table data changes on the subscription "
"subId=%d,SubKey=%d)."
@@ -920,7 +920,7 @@ EventLogger::getText(char * m_text, size_t m_text_len,
const int subId = theData[2];
const int subKey = theData[3];
const int err = theData[4];
- ::snprintf(m_text, m_text_len,
+ BaseString::snprintf(m_text, m_text_len,
"Grep::PSCoord: All participants have started "
" synchronization on meta data (META SCAN) using "
"(subId=%d,SubKey=%d)."
@@ -935,7 +935,7 @@ EventLogger::getText(char * m_text, size_t m_text_len,
const int subId = theData[2];
const int subKey = theData[3];
const int err = theData[4];
- ::snprintf(m_text, m_text_len,
+ BaseString::snprintf(m_text, m_text_len,
"Grep::SSCoord: Synchronization started (META SCAN) on "
" meta data using (subId=%d,SubKey=%d)"
" Return code: %d",
@@ -949,7 +949,7 @@ EventLogger::getText(char * m_text, size_t m_text_len,
const int subId = theData[2];
const int subKey = theData[3];
const int err = theData[4];
- ::snprintf(m_text, m_text_len,
+ BaseString::snprintf(m_text, m_text_len,
"Grep::PSCoord: All participants have started "
"synchronization "
" on table data (DATA SCAN) using (subId=%d,SubKey=%d)."
@@ -965,7 +965,7 @@ EventLogger::getText(char * m_text, size_t m_text_len,
const int subKey = theData[3];
const int err = theData[4];
const int gci = theData[5];
- ::snprintf(m_text, m_text_len,
+ BaseString::snprintf(m_text, m_text_len,
"Grep::SSCoord: Synchronization started (DATA SCAN) on "
"table data using (subId=%d,SubKey=%d). GCI = %d"
" Return code: %d",
@@ -980,7 +980,7 @@ EventLogger::getText(char * m_text, size_t m_text_len,
const int subId = theData[2];
const int subKey = theData[3];
const int err = theData[4];
- ::snprintf(m_text, m_text_len,
+ BaseString::snprintf(m_text, m_text_len,
"Grep::PSCoord: All participants have removed "
"subscription (subId=%d,SubKey=%d). I have cleaned "
"up resources I've used."
@@ -995,7 +995,7 @@ EventLogger::getText(char * m_text, size_t m_text_len,
const int subId = theData[2];
const int subKey = theData[3];
const int err = theData[4];
- ::snprintf(m_text, m_text_len,
+ BaseString::snprintf(m_text, m_text_len,
"Grep::SSCoord: Removed subscription "
"(subId=%d,SubKey=%d)"
" Return code: %d",
@@ -1005,7 +1005,7 @@ EventLogger::getText(char * m_text, size_t m_text_len,
break;
}
default:
- ::snprintf(m_text,
+ BaseString::snprintf(m_text,
m_text_len,
"%sUnknown GrepSubscriptonInfo event: %d",
theNodeId,
@@ -1024,7 +1024,7 @@ EventLogger::getText(char * m_text, size_t m_text_len,
const int subId = theData[2];
const int subKey = theData[3];
const int err = theData[4];
- ::snprintf(m_text, m_text_len,
+ BaseString::snprintf(m_text, m_text_len,
"Grep::SSCoord:Error code: %d Error message: %s"
" (subId=%d,SubKey=%d)",
err,
@@ -1038,7 +1038,7 @@ EventLogger::getText(char * m_text, size_t m_text_len,
const int subId = theData[2];
const int subKey = theData[3];
const int err = theData[4];
- ::snprintf(m_text, m_text_len,
+ BaseString::snprintf(m_text, m_text_len,
"Grep::SSCoord: FAILED to Created subscription using"
" (subId=%d,SubKey=%d)in primary system."
" Error code: %d Error Message: %s",
@@ -1053,7 +1053,7 @@ EventLogger::getText(char * m_text, size_t m_text_len,
const int subId = theData[2];
const int subKey = theData[3];
const int err = theData[4];
- ::snprintf(m_text, m_text_len,
+ BaseString::snprintf(m_text, m_text_len,
"Grep::SSCoord: Logging failed to start on meta "
"data changes."
" using (subId=%d,SubKey=%d)"
@@ -1069,7 +1069,7 @@ EventLogger::getText(char * m_text, size_t m_text_len,
const int subId = theData[2];
const int subKey = theData[3];
const int err = theData[4];
- ::snprintf(m_text, m_text_len,
+ BaseString::snprintf(m_text, m_text_len,
"Grep::SSCoord: Logging FAILED to start on table data "
" changes using (subId=%d,SubKey=%d)"
" Error code: %d Error Message: %s",
@@ -1084,7 +1084,7 @@ EventLogger::getText(char * m_text, size_t m_text_len,
const int subId = theData[2];
const int subKey = theData[3];
const int err = theData[4];
- ::snprintf(m_text, m_text_len,
+ BaseString::snprintf(m_text, m_text_len,
"Grep::SSCoord: Synchronization FAILED (META SCAN) on "
" meta data using (subId=%d,SubKey=%d)"
" Error code: %d Error Message: %s",
@@ -1100,7 +1100,7 @@ EventLogger::getText(char * m_text, size_t m_text_len,
const int subKey = theData[3];
const int err = theData[4];
const int gci = theData[5];
- ::snprintf(m_text, m_text_len,
+ BaseString::snprintf(m_text, m_text_len,
"Grep::SSCoord: Synchronization FAILED (DATA SCAN) on "
"table data using (subId=%d,SubKey=%d). GCI = %d"
" Error code: %d Error Message: %s",
@@ -1116,7 +1116,7 @@ EventLogger::getText(char * m_text, size_t m_text_len,
const int subId = theData[2];
const int subKey = theData[3];
const int err = theData[4];
- ::snprintf(m_text, m_text_len,
+ BaseString::snprintf(m_text, m_text_len,
"Grep::SSCoord: Failed to remove subscription "
"(subId=%d,SubKey=%d). "
" Error code: %d Error Message: %s",
@@ -1133,7 +1133,7 @@ EventLogger::getText(char * m_text, size_t m_text_len,
const int subId = theData[2];
const int subKey = theData[3];
const int err = theData[4];
- ::snprintf(m_text, m_text_len,
+ BaseString::snprintf(m_text, m_text_len,
"Grep::PSCoord: Error code: %d Error Message: %s"
" (subId=%d,SubKey=%d)",
err,
@@ -1147,7 +1147,7 @@ EventLogger::getText(char * m_text, size_t m_text_len,
const int subId = theData[2];
const int subKey = theData[3];
const int err = theData[4];
- ::snprintf(m_text, m_text_len,
+ BaseString::snprintf(m_text, m_text_len,
"Grep::PSCoord: FAILED to Created subscription using"
" (subId=%d,SubKey=%d)in primary system."
" Error code: %d Error Message: %s",
@@ -1162,7 +1162,7 @@ EventLogger::getText(char * m_text, size_t m_text_len,
const int subId = theData[2];
const int subKey = theData[3];
const int err = theData[4];
- ::snprintf(m_text, m_text_len,
+ BaseString::snprintf(m_text, m_text_len,
"Grep::PSCoord: Logging failed to start on meta "
"data changes."
" using (subId=%d,SubKey=%d)"
@@ -1178,7 +1178,7 @@ EventLogger::getText(char * m_text, size_t m_text_len,
const int subId = theData[2];
const int subKey = theData[3];
const int err = theData[4];
- ::snprintf(m_text, m_text_len,
+ BaseString::snprintf(m_text, m_text_len,
"Grep::PSCoord: Logging FAILED to start on table data "
" changes using (subId=%d,SubKey=%d)"
" Error code: %d Error Message: %s",
@@ -1193,7 +1193,7 @@ EventLogger::getText(char * m_text, size_t m_text_len,
const int subId = theData[2];
const int subKey = theData[3];
const int err = theData[4];
- ::snprintf(m_text, m_text_len,
+ BaseString::snprintf(m_text, m_text_len,
"Grep::PSCoord: Synchronization FAILED (META SCAN) on "
" meta data using (subId=%d,SubKey=%d)"
" Error code: %d Error Message: %s",
@@ -1209,7 +1209,7 @@ EventLogger::getText(char * m_text, size_t m_text_len,
const int subKey = theData[3];
const int err = theData[4];
const int gci = theData[5];
- ::snprintf(m_text, m_text_len,
+ BaseString::snprintf(m_text, m_text_len,
"Grep::PSCoord: Synchronization FAILED (DATA SCAN) on "
"table data using (subId=%d,SubKey=%d). GCI = %d. "
" Error code: %d Error Message: %s",
@@ -1225,7 +1225,7 @@ EventLogger::getText(char * m_text, size_t m_text_len,
const int subId = theData[2];
const int subKey = theData[3];
const int err = theData[4];
- ::snprintf(m_text, m_text_len,
+ BaseString::snprintf(m_text, m_text_len,
"Grep::PSCoord: Failed to remove subscription "
"(subId=%d,SubKey=%d)."
" Error code: %d Error Message: %s",
@@ -1239,7 +1239,7 @@ EventLogger::getText(char * m_text, size_t m_text_len,
{
const int err = theData[4];
const int nodeId = theData[5];
- ::snprintf(m_text, m_text_len,
+ BaseString::snprintf(m_text, m_text_len,
"Rep: Node %d."
" Error code: %d Error Message: %s",
nodeId,
@@ -1250,7 +1250,7 @@ EventLogger::getText(char * m_text, size_t m_text_len,
default:
- ::snprintf(m_text,
+ BaseString::snprintf(m_text,
m_text_len,
"%sUnknown GrepSubscriptionAlert event: %d",
theNodeId,
@@ -1261,19 +1261,19 @@ EventLogger::getText(char * m_text, size_t m_text_len,
}
case EventReport::BackupStarted:
- ::snprintf(m_text,
+ BaseString::snprintf(m_text,
m_text_len,
"%sBackup %d started from node %d",
theNodeId, theData[2], refToNode(theData[1]));
break;
case EventReport::BackupFailedToStart:
- ::snprintf(m_text,
+ BaseString::snprintf(m_text,
m_text_len,
"%sBackup request from %d failed to start. Error: %d",
theNodeId, refToNode(theData[1]), theData[2]);
break;
case EventReport::BackupCompleted:
- ::snprintf(m_text,
+ BaseString::snprintf(m_text,
m_text_len,
"%sBackup %d started from node %d completed\n"
" StartGCP: %d StopGCP: %d\n"
@@ -1284,7 +1284,7 @@ EventLogger::getText(char * m_text, size_t m_text_len,
theData[5], theData[7]);
break;
case EventReport::BackupAborted:
- ::snprintf(m_text,
+ BaseString::snprintf(m_text,
m_text_len,
"%sBackup %d started from %d has been aborted. Error: %d",
theNodeId,
@@ -1293,7 +1293,7 @@ EventLogger::getText(char * m_text, size_t m_text_len,
theData[3]);
break;
default:
- ::snprintf(m_text,
+ BaseString::snprintf(m_text,
m_text_len,
"%sUnknown event: %d",
theNodeId,
@@ -1306,7 +1306,7 @@ EventLogger::getText(char * m_text, size_t m_text_len,
EventLogger::EventLogger() : m_filterLevel(15)
{
setCategory("EventLogger");
- enable(Logger::Logger::LL_INFO, Logger::Logger::LL_ALERT);
+ enable(Logger::LL_INFO, Logger::LL_ALERT);
}
EventLogger::~EventLogger()
@@ -1343,7 +1343,7 @@ EventLogger::log(int eventType, const Uint32* theData, NodeId nodeId,
{
Uint32 threshold = 0;
Logger::LoggerLevel severity = Logger::LL_WARNING;
- LogLevel::EventCategory cat;
+ LogLevel::EventCategory cat= LogLevel::llInvalid;
for(unsigned i = 0; i<EventLoggerBase::matrixSize; i++){
if(EventLoggerBase::matrix[i].eventType == eventType){
@@ -1353,6 +1353,9 @@ EventLogger::log(int eventType, const Uint32* theData, NodeId nodeId,
break;
}
}
+
+ if (cat == LogLevel::llInvalid)
+ return;
Uint32 set = ll?ll->getLogLevel(cat) : m_logLevel.getLogLevel(cat);
if (threshold <= set){
diff --git a/ndb/src/common/debugger/signaldata/ContinueB.cpp b/ndb/src/common/debugger/signaldata/ContinueB.cpp
index 1be6da86cb1..c295041bc01 100644
--- a/ndb/src/common/debugger/signaldata/ContinueB.cpp
+++ b/ndb/src/common/debugger/signaldata/ContinueB.cpp
@@ -24,9 +24,9 @@ bool
printCONTINUEB(FILE * output, const Uint32 * theData, Uint32 len,
Uint16 receiverBlockNo){
if(receiverBlockNo == DBDIH){
- return printCONTINUEB_DBDIH(output, theData, len);
+ return printCONTINUEB_DBDIH(output, theData, len, 0);
} else if(receiverBlockNo == NDBFS) {
- return printCONTINUEB_NDBFS(output, theData, len);
+ return printCONTINUEB_NDBFS(output, theData, len, 0);
}
return false;
diff --git a/ndb/src/common/debugger/signaldata/CopyGCI.cpp b/ndb/src/common/debugger/signaldata/CopyGCI.cpp
index 96186e82525..173b3f6708f 100644
--- a/ndb/src/common/debugger/signaldata/CopyGCI.cpp
+++ b/ndb/src/common/debugger/signaldata/CopyGCI.cpp
@@ -21,22 +21,22 @@ void
print(char * buf, size_t buf_len, CopyGCIReq::CopyReason r){
switch(r){
case CopyGCIReq::IDLE:
- snprintf(buf, buf_len, "IDLE");
+ BaseString::snprintf(buf, buf_len, "IDLE");
break;
case CopyGCIReq::LOCAL_CHECKPOINT:
- snprintf(buf, buf_len, "LOCAL_CHECKPOINT");
+ BaseString::snprintf(buf, buf_len, "LOCAL_CHECKPOINT");
break;
case CopyGCIReq::RESTART:
- snprintf(buf, buf_len, "RESTART");
+ BaseString::snprintf(buf, buf_len, "RESTART");
break;
case CopyGCIReq::GLOBAL_CHECKPOINT:
- snprintf(buf, buf_len, "GLOBAL_CHECKPOINT");
+ BaseString::snprintf(buf, buf_len, "GLOBAL_CHECKPOINT");
break;
case CopyGCIReq::INITIAL_START_COMPLETED:
- snprintf(buf, buf_len, "INITIAL_START_COMPLETED");
+ BaseString::snprintf(buf, buf_len, "INITIAL_START_COMPLETED");
break;
default:
- snprintf(buf, buf_len, "<Unknown>");
+ BaseString::snprintf(buf, buf_len, "<Unknown>");
}
}
diff --git a/ndb/src/common/debugger/signaldata/CreateTrig.cpp b/ndb/src/common/debugger/signaldata/CreateTrig.cpp
index ddd45080cba..db5344cfbe7 100644
--- a/ndb/src/common/debugger/signaldata/CreateTrig.cpp
+++ b/ndb/src/common/debugger/signaldata/CreateTrig.cpp
@@ -28,51 +28,51 @@ bool printCREATE_TRIG_REQ(FILE * output, const Uint32 * theData, Uint32 len, Uin
//sig->getTriggerName((char *) &triggerName);
switch (sig->getTriggerType()) {
case(TriggerType::SECONDARY_INDEX):
- snprintf(triggerType, sizeof(triggerType), "SECONDARY_INDEX");
+ BaseString::snprintf(triggerType, sizeof(triggerType), "SECONDARY_INDEX");
break;
case(TriggerType::SUBSCRIPTION):
- snprintf(triggerType, sizeof(triggerType), "SUBSCRIPTION");
+ BaseString::snprintf(triggerType, sizeof(triggerType), "SUBSCRIPTION");
break;
case(TriggerType::ORDERED_INDEX):
- snprintf(triggerType, sizeof(triggerType), "ORDERED_INDEX");
+ BaseString::snprintf(triggerType, sizeof(triggerType), "ORDERED_INDEX");
break;
default:
- snprintf(triggerType, sizeof(triggerType), "UNKNOWN [%d]", (int)sig->getTriggerType());
+ BaseString::snprintf(triggerType, sizeof(triggerType), "UNKNOWN [%d]", (int)sig->getTriggerType());
break;
}
switch (sig->getTriggerActionTime()) {
case (TriggerActionTime::TA_BEFORE):
- snprintf(triggerActionTime, sizeof(triggerActionTime), "BEFORE");
+ BaseString::snprintf(triggerActionTime, sizeof(triggerActionTime), "BEFORE");
break;
case(TriggerActionTime::TA_AFTER):
- snprintf(triggerActionTime, sizeof(triggerActionTime), "AFTER");
+ BaseString::snprintf(triggerActionTime, sizeof(triggerActionTime), "AFTER");
break;
case (TriggerActionTime::TA_DEFERRED):
- snprintf(triggerActionTime, sizeof(triggerActionTime), "DEFERRED");
+ BaseString::snprintf(triggerActionTime, sizeof(triggerActionTime), "DEFERRED");
break;
case (TriggerActionTime::TA_DETACHED):
- snprintf(triggerActionTime, sizeof(triggerActionTime), "DETACHED");
+ BaseString::snprintf(triggerActionTime, sizeof(triggerActionTime), "DETACHED");
break;
default:
- snprintf(triggerActionTime, sizeof(triggerActionTime),
+ BaseString::snprintf(triggerActionTime, sizeof(triggerActionTime),
"UNKNOWN [%d]", (int)sig->getTriggerActionTime());
break;
}
switch (sig->getTriggerEvent()) {
case (TriggerEvent::TE_INSERT):
- snprintf(triggerEvent, sizeof(triggerEvent), "INSERT");
+ BaseString::snprintf(triggerEvent, sizeof(triggerEvent), "INSERT");
break;
case(TriggerEvent::TE_DELETE):
- snprintf(triggerEvent, sizeof(triggerEvent), "DELETE");
+ BaseString::snprintf(triggerEvent, sizeof(triggerEvent), "DELETE");
break;
case(TriggerEvent::TE_UPDATE):
- snprintf(triggerEvent, sizeof(triggerEvent), "UPDATE");
+ BaseString::snprintf(triggerEvent, sizeof(triggerEvent), "UPDATE");
break;
case(TriggerEvent::TE_CUSTOM):
- snprintf(triggerEvent, sizeof(triggerEvent), "CUSTOM");
+ BaseString::snprintf(triggerEvent, sizeof(triggerEvent), "CUSTOM");
break;
default:
- snprintf(triggerEvent, sizeof(triggerEvent), "UNKNOWN [%d]", (int)sig->getTriggerEvent());
+ BaseString::snprintf(triggerEvent, sizeof(triggerEvent), "UNKNOWN [%d]", (int)sig->getTriggerEvent());
break;
}
diff --git a/ndb/src/common/debugger/signaldata/DihContinueB.cpp b/ndb/src/common/debugger/signaldata/DihContinueB.cpp
index 94453e76d72..9fece17315c 100644
--- a/ndb/src/common/debugger/signaldata/DihContinueB.cpp
+++ b/ndb/src/common/debugger/signaldata/DihContinueB.cpp
@@ -18,7 +18,10 @@
#include <signaldata/DihContinueB.hpp>
bool
-printCONTINUEB_DBDIH(FILE * output, const Uint32 * theData, Uint32 len){
+printCONTINUEB_DBDIH(FILE * output, const Uint32 * theData,
+ Uint32 len, Uint16 not_used){
+
+ (void)not_used;
switch (theData[0]) {
case DihContinueB::ZPACK_TABLE_INTO_PAGES:
diff --git a/ndb/src/common/debugger/signaldata/Makefile.am b/ndb/src/common/debugger/signaldata/Makefile.am
index 0a5806e1e00..c855c5f8a18 100644
--- a/ndb/src/common/debugger/signaldata/Makefile.am
+++ b/ndb/src/common/debugger/signaldata/Makefile.am
@@ -23,7 +23,8 @@ libsignaldataprint_la_SOURCES = \
FailRep.cpp DisconnectRep.cpp SignalDroppedRep.cpp \
SumaImpl.cpp NdbSttor.cpp CreateFragmentation.cpp \
UtilLock.cpp TuxMaint.cpp AccLock.cpp \
- LqhTrans.cpp ReadNodesConf.cpp CntrStart.cpp
+ LqhTrans.cpp ReadNodesConf.cpp CntrStart.cpp \
+ ScanFrag.cpp
include $(top_srcdir)/ndb/config/common.mk.am
include $(top_srcdir)/ndb/config/type_ndbapi.mk.am
diff --git a/ndb/src/common/debugger/signaldata/MasterLCP.cpp b/ndb/src/common/debugger/signaldata/MasterLCP.cpp
index aa30404524f..078b92f6f2e 100644
--- a/ndb/src/common/debugger/signaldata/MasterLCP.cpp
+++ b/ndb/src/common/debugger/signaldata/MasterLCP.cpp
@@ -23,16 +23,16 @@ void
print(char *buf, size_t buf_len, MasterLCPConf::State s){
switch(s){
case MasterLCPConf::LCP_STATUS_IDLE:
- snprintf(buf, buf_len, "LCP_STATUS_IDLE");
+ BaseString::snprintf(buf, buf_len, "LCP_STATUS_IDLE");
break;
case MasterLCPConf::LCP_STATUS_ACTIVE:
- snprintf(buf, buf_len, "LCP_STATUS_ACTIVE");
+ BaseString::snprintf(buf, buf_len, "LCP_STATUS_ACTIVE");
break;
case MasterLCPConf::LCP_TAB_COMPLETED:
- snprintf(buf, buf_len, "LCP_TAB_COMPLETED");
+ BaseString::snprintf(buf, buf_len, "LCP_TAB_COMPLETED");
break;
case MasterLCPConf::LCP_TAB_SAVED:
- snprintf(buf, buf_len, "LCP_TAB_SAVED");
+ BaseString::snprintf(buf, buf_len, "LCP_TAB_SAVED");
break;
}
}
diff --git a/ndb/src/common/debugger/signaldata/NdbfsContinueB.cpp b/ndb/src/common/debugger/signaldata/NdbfsContinueB.cpp
index b3c7a61136e..9f55efae017 100644
--- a/ndb/src/common/debugger/signaldata/NdbfsContinueB.cpp
+++ b/ndb/src/common/debugger/signaldata/NdbfsContinueB.cpp
@@ -18,7 +18,10 @@
#include <signaldata/NdbfsContinueB.hpp>
bool
-printCONTINUEB_NDBFS(FILE * output, const Uint32 * theData, Uint32 len){
+printCONTINUEB_NDBFS(FILE * output, const Uint32 * theData,
+ Uint32 len, Uint16 not_used){
+
+ (void)not_used;
switch (theData[0]) {
case NdbfsContinueB::ZSCAN_MEMORYCHANNEL_10MS_DELAY:
diff --git a/ndb/src/common/debugger/signaldata/ScanFrag.cpp b/ndb/src/common/debugger/signaldata/ScanFrag.cpp
new file mode 100644
index 00000000000..4d19a325637
--- /dev/null
+++ b/ndb/src/common/debugger/signaldata/ScanFrag.cpp
@@ -0,0 +1,42 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+
+
+#include <BlockNumbers.h>
+#include <signaldata/ScanTab.hpp>
+#include <signaldata/ScanFrag.hpp>
+
+bool
+printSCAN_FRAGREQ(FILE * output, const Uint32 * theData,
+ Uint32 len, Uint16 receiverBlockNo) {
+ const ScanFragReq * const sig = (ScanFragReq *)theData;
+ fprintf(output, " senderData: %x\n", sig->senderData);
+ fprintf(output, " resultRef: %x\n", sig->resultRef);
+ fprintf(output, " savePointId: %x\n", sig->savePointId);
+ fprintf(output, " requestInfo: %x\n", sig->requestInfo);
+ fprintf(output, " tableId: %x\n", sig->tableId);
+ fprintf(output, " fragmentNo: %x\n", sig->fragmentNoKeyLen & 0xFFFF);
+ fprintf(output, " keyLen: %x\n", sig->fragmentNoKeyLen >> 16);
+ fprintf(output, " schemaVersion: %x\n", sig->schemaVersion);
+ fprintf(output, " transId1: %x\n", sig->transId1);
+ fprintf(output, " transId2: %x\n", sig->transId2);
+ fprintf(output, " clientOpPtr: %x\n", sig->clientOpPtr);
+ fprintf(output, " batch_size_rows: %x\n", sig->batch_size_rows);
+ fprintf(output, " batch_size_bytes: %x\n", sig->batch_size_bytes);
+ return true;
+}
+
diff --git a/ndb/src/common/debugger/signaldata/ScanTab.cpp b/ndb/src/common/debugger/signaldata/ScanTab.cpp
index 3f2109d9477..72a4d9f94b9 100644
--- a/ndb/src/common/debugger/signaldata/ScanTab.cpp
+++ b/ndb/src/common/debugger/signaldata/ScanTab.cpp
@@ -30,15 +30,18 @@ printSCANTABREQ(FILE * output, const Uint32 * theData, Uint32 len, Uint16 receiv
fprintf(output, " apiConnectPtr: H\'%.8x",
sig->apiConnectPtr);
fprintf(output, " requestInfo: H\'%.8x:\n", requestInfo);
- fprintf(output, " Parallellism: %u, Batch: %u LockMode: %u, Holdlock: %u, RangeScan: %u\n",
+ fprintf(output, " Parallellism: %u, Batch: %u LockMode: %u, Keyinfo: %u Holdlock: %u, RangeScan: %u\n",
sig->getParallelism(requestInfo),
sig->getScanBatch(requestInfo),
sig->getLockMode(requestInfo),
sig->getHoldLockFlag(requestInfo),
- sig->getRangeScanFlag(requestInfo));
+ sig->getRangeScanFlag(requestInfo),
+ sig->getKeyinfoFlag(requestInfo));
- fprintf(output, " attrLen: %d, tableId: %d, tableSchemaVer: %d\n",
- sig->attrLen, sig->tableId, sig->tableSchemaVersion);
+ Uint32 keyLen = (sig->attrLenKeyLen >> 16);
+ Uint32 attrLen = (sig->attrLenKeyLen & 0xFFFF);
+ fprintf(output, " attrLen: %d, keyLen: %d tableId: %d, tableSchemaVer: %d\n",
+ attrLen, keyLen, sig->tableId, sig->tableSchemaVersion);
fprintf(output, " transId(1, 2): (H\'%.8x, H\'%.8x) storedProcId: H\'%.8x\n",
sig->transId1, sig->transId2, sig->storedProcId);
diff --git a/ndb/src/common/debugger/signaldata/SignalDataPrint.cpp b/ndb/src/common/debugger/signaldata/SignalDataPrint.cpp
index 65351663789..3314f0bd097 100644
--- a/ndb/src/common/debugger/signaldata/SignalDataPrint.cpp
+++ b/ndb/src/common/debugger/signaldata/SignalDataPrint.cpp
@@ -53,6 +53,7 @@
#include <signaldata/UtilPrepare.hpp>
#include <signaldata/UtilExecute.hpp>
#include <signaldata/ScanTab.hpp>
+#include <signaldata/ScanFrag.hpp>
#include <signaldata/LqhFrag.hpp>
#include <signaldata/LqhTransConf.hpp>
#include <signaldata/DropTab.hpp>
@@ -75,12 +76,11 @@
#include <signaldata/TuxMaint.hpp>
#include <signaldata/AccLock.hpp>
-bool printCONTINUEB(FILE *, const Uint32 *, Uint32, Uint16);
-
/**
* This is the register
*/
-const NameFunctionPair
+
+const NameFunctionPair
SignalDataPrintFunctions[] = {
{ GSN_TCKEYREQ, printTCKEYREQ },
{ GSN_TCKEYCONF, printTCKEYCONF },
@@ -250,10 +250,10 @@ SignalDataPrintFunctions[] = {
,{ GSN_TUX_MAINT_REQ, printTUX_MAINT_REQ }
,{ GSN_ACC_LOCKREQ, printACC_LOCKREQ }
,{ GSN_LQH_TRANSCONF, printLQH_TRANSCONF }
+ ,{ GSN_SCAN_FRAGREQ, printSCAN_FRAGREQ }
+ ,{ 0, 0 }
};
-const unsigned short NO_OF_PRINT_FUNCTIONS = sizeof(SignalDataPrintFunctions)/sizeof(NameFunctionPair);
-
template class Bitmask<1>;
template class Bitmask<2>;
template class Bitmask<4>;
diff --git a/ndb/src/common/debugger/signaldata/SignalNames.cpp b/ndb/src/common/debugger/signaldata/SignalNames.cpp
index 9d4d5bdf6f5..9228e305677 100644
--- a/ndb/src/common/debugger/signaldata/SignalNames.cpp
+++ b/ndb/src/common/debugger/signaldata/SignalNames.cpp
@@ -446,6 +446,8 @@ const GsnName SignalNames [] = {
,{ GSN_STOP_REQ, "STOP_REQ" }
,{ GSN_STOP_REF, "STOP_REF" }
+ ,{ GSN_API_VERSION_REQ, "API_VERSION_REQ" }
+ ,{ GSN_API_VERSION_CONF, "API_VERSION_CONF" }
,{ GSN_ABORT_ALL_REQ, "ABORT_ALL_REQ" }
,{ GSN_ABORT_ALL_REF, "ABORT_ALL_REF" }
diff --git a/ndb/src/common/debugger/signaldata/TcKeyConf.cpp b/ndb/src/common/debugger/signaldata/TcKeyConf.cpp
index 727e097a464..652c2b8a557 100644
--- a/ndb/src/common/debugger/signaldata/TcKeyConf.cpp
+++ b/ndb/src/common/debugger/signaldata/TcKeyConf.cpp
@@ -22,38 +22,48 @@ printTCKEYCONF(FILE * output, const Uint32 * theData, Uint32 len, Uint16 receive
if (receiverBlockNo == API_PACKED) {
- fprintf(output, "Signal data: ");
- Uint32 i = 0;
- while (i < len)
- fprintf(output, "H\'%.8x ", theData[i++]);
- fprintf(output,"\n");
+ return false;
+ Uint32 Theader = * theData++;
+ Uint32 TpacketLen = (Theader & 0x1F) + 3;
+ Uint32 TrecBlockNo = Theader >> 16;
+
+ do {
+ fprintf(output, "Block: %d %d %d\n", TrecBlockNo, len, TpacketLen);
+ printTCKEYCONF(output, theData, TpacketLen, TrecBlockNo);
+ assert(len >= (1 + TpacketLen));
+ len -= (1 + TpacketLen);
+ theData += TpacketLen;
+ } while(len);
+ return true;
}
else {
const TcKeyConf * const sig = (TcKeyConf *) theData;
- fprintf(output, "Signal data: ");
Uint32 i = 0;
Uint32 confInfo = sig->confInfo;
Uint32 noOfOp = TcKeyConf::getNoOfOperations(confInfo);
if (noOfOp > 10) noOfOp = 10;
- while (i < len)
- fprintf(output, "H\'%.8x ", theData[i++]);
- fprintf(output,"\n");
- fprintf(output, "apiConnectPtr: H'%.8x, gci: %u, transId:(H'%.8x, H'%.8x)\n",
+ fprintf(output, " apiConnectPtr: H'%.8x, gci: %u, transId:(H'%.8x, H'%.8x)\n",
sig->apiConnectPtr, sig->gci, sig->transId1, sig->transId2);
- fprintf(output, "noOfOperations: %u, commitFlag: %s, markerFlag: %s\n",
+ fprintf(output, " noOfOperations: %u, commitFlag: %s, markerFlag: %s\n",
noOfOp,
(TcKeyConf::getCommitFlag(confInfo) == 0)?"false":"true",
(TcKeyConf::getMarkerFlag(confInfo) == 0)?"false":"true");
fprintf(output, "Operations:\n");
for(i = 0; i < noOfOp; i++) {
- fprintf(output,
- "apiOperationPtr: H'%.8x, attrInfoLen: %u\n",
- sig->operations[i].apiOperationPtr,
- sig->operations[i].attrInfoLen);
+ if(sig->operations[i].attrInfoLen > TcKeyConf::SimpleReadBit)
+ fprintf(output,
+ " apiOperationPtr: H'%.8x, simplereadnode: %u\n",
+ sig->operations[i].apiOperationPtr,
+ sig->operations[i].attrInfoLen & (~TcKeyConf::SimpleReadBit));
+ else
+ fprintf(output,
+ " apiOperationPtr: H'%.8x, attrInfoLen: %u\n",
+ sig->operations[i].apiOperationPtr,
+ sig->operations[i].attrInfoLen);
}
}
-
+
return true;
}
diff --git a/ndb/src/common/logger/FileLogHandler.cpp b/ndb/src/common/logger/FileLogHandler.cpp
index 632db71db15..29172ff93ad 100644
--- a/ndb/src/common/logger/FileLogHandler.cpp
+++ b/ndb/src/common/logger/FileLogHandler.cpp
@@ -153,11 +153,11 @@ FileLogHandler::createNewFile()
if (fileNo >= m_maxNoFiles)
{
fileNo = 1;
- ::snprintf(newName, sizeof(newName),
+ BaseString::snprintf(newName, sizeof(newName),
"%s.%d", m_pLogFile->getName(), fileNo);
break;
}
- ::snprintf(newName, sizeof(newName),
+ BaseString::snprintf(newName, sizeof(newName),
"%s.%d", m_pLogFile->getName(), fileNo++);
} while (File_class::exists(newName));
diff --git a/ndb/src/common/logger/LogHandler.cpp b/ndb/src/common/logger/LogHandler.cpp
index 83d479c82fd..4fab957fc50 100644
--- a/ndb/src/common/logger/LogHandler.cpp
+++ b/ndb/src/common/logger/LogHandler.cpp
@@ -45,7 +45,7 @@ LogHandler::getDefaultHeader(char* pStr, const char* pCategory,
Logger::LoggerLevel level) const
{
char time[MAX_DATE_TIME_HEADER_LENGTH];
- ::snprintf(pStr, MAX_HEADER_LENGTH, "%s [%s] %s -- ",
+ BaseString::snprintf(pStr, MAX_HEADER_LENGTH, "%s [%s] %s -- ",
getTimeAsString((char*)time),
pCategory,
Logger::LoggerLevelNames[level]);
@@ -84,7 +84,7 @@ LogHandler::getTimeAsString(char* pStr) const
tm_now = ::localtime(&now); //uses the "current" timezone
#endif
- ::snprintf(pStr, MAX_DATE_TIME_HEADER_LENGTH,
+ BaseString::snprintf(pStr, MAX_DATE_TIME_HEADER_LENGTH,
m_pDateTimeFormat,
tm_now->tm_year + 1900,
tm_now->tm_mon + 1, //month is [0,11]. +1 -> [1,12]
diff --git a/ndb/src/common/logger/Logger.cpp b/ndb/src/common/logger/Logger.cpp
index c2fdecb642b..fed5c211149 100644
--- a/ndb/src/common/logger/Logger.cpp
+++ b/ndb/src/common/logger/Logger.cpp
@@ -340,7 +340,7 @@ Logger::log(LoggerLevel logLevel, const char* pMsg, va_list ap) const
while ( (pHandler = m_pHandlerList->next()) != NULL)
{
char buf[1024];
- vsnprintf(buf, sizeof(buf), pMsg, ap);
+ BaseString::vsnprintf(buf, sizeof(buf), pMsg, ap);
pHandler->append(m_pCategory, logLevel, buf);
}
}
diff --git a/ndb/src/common/logger/listtest/LogHandlerListUnitTest.cpp b/ndb/src/common/logger/listtest/LogHandlerListUnitTest.cpp
index 44ee11717b4..7de9ee46479 100644
--- a/ndb/src/common/logger/listtest/LogHandlerListUnitTest.cpp
+++ b/ndb/src/common/logger/listtest/LogHandlerListUnitTest.cpp
@@ -48,7 +48,7 @@ int main(int argc, char* argv[])
{
ndbout << "-- " << " Test " << i + 1
<< " [" << testCases[i].name << "] --" << endl;
- snprintf(str, 256, "%s %s %s %d", "Logging ",
+ BaseString::snprintf(str, 256, "%s %s %s %d", "Logging ",
testCases[i].name, " message ", i);
if (testCases[i].test(str))
{
@@ -128,7 +128,7 @@ LogHandlerListUnitTest::testTraverseNext(const char* msg)
{
char* str = new char[3];
pHandlers[i] = new ConsoleLogHandler();
- ::snprintf(str, 3, "%d", i);
+ BaseString::snprintf(str, 3, "%d", i);
pHandlers[i]->setDateTimeFormat(str);
list.add(pHandlers[i]);
}
diff --git a/ndb/src/common/logger/loggertest/LoggerUnitTest.cpp b/ndb/src/common/logger/loggertest/LoggerUnitTest.cpp
index 017dcb79c1f..990d2e0eada 100644
--- a/ndb/src/common/logger/loggertest/LoggerUnitTest.cpp
+++ b/ndb/src/common/logger/loggertest/LoggerUnitTest.cpp
@@ -86,7 +86,7 @@ NDB_COMMAND(loggertest, "loggertest", "loggertest -console | -file",
{
ndbout << "-- " << " Test " << i + 1
<< " [" << testCases[i].name << "] --" << endl;
- ::snprintf(str, 256, "%s %s %s %d", "Logging ",
+ BaseString::snprintf(str, 256, "%s %s %s %d", "Logging ",
testCases[i].name, " message ", i);
if (testCases[i].test(str))
{
diff --git a/ndb/src/common/mgmcommon/ConfigRetriever.cpp b/ndb/src/common/mgmcommon/ConfigRetriever.cpp
index b4f2d0b9897..d8417ac146a 100644
--- a/ndb/src/common/mgmcommon/ConfigRetriever.cpp
+++ b/ndb/src/common/mgmcommon/ConfigRetriever.cpp
@@ -186,7 +186,7 @@ ConfigRetriever::getConfig(const char * filename){
const int res = stat(filename, &sbuf);
if(res != 0){
char buf[255];
- snprintf(buf, sizeof(buf), "Could not find file: \"%s\"", filename);
+ BaseString::snprintf(buf, sizeof(buf), "Could not find file: \"%s\"", filename);
setError(CR_ERROR, buf);
return 0;
}
@@ -211,7 +211,7 @@ ConfigRetriever::getConfig(const char * filename){
ConfigValuesFactory cvf;
if(!cvf.unpack(buf2, bytes)){
char buf[255];
- snprintf(buf, sizeof(buf), "Error while unpacking");
+ BaseString::snprintf(buf, sizeof(buf), "Error while unpacking");
setError(CR_ERROR, buf);
delete []buf2;
return 0;
@@ -241,7 +241,7 @@ ConfigRetriever::verifyConfig(const struct ndb_mgm_configuration * conf, Uint32
it = ndb_mgm_create_configuration_iterator((struct ndb_mgm_configuration *)conf, CFG_SECTION_NODE);
if(it == 0){
- snprintf(buf, 255, "Unable to create config iterator");
+ BaseString::snprintf(buf, 255, "Unable to create config iterator");
setError(CR_ERROR, buf);
return false;
@@ -249,14 +249,14 @@ ConfigRetriever::verifyConfig(const struct ndb_mgm_configuration * conf, Uint32
NdbAutoPtr<ndb_mgm_configuration_iterator> ptr(it);
if(ndb_mgm_find(it, CFG_NODE_ID, nodeid) != 0){
- snprintf(buf, 255, "Unable to find node with id: %d", nodeid);
+ BaseString::snprintf(buf, 255, "Unable to find node with id: %d", nodeid);
setError(CR_ERROR, buf);
return false;
}
const char * hostname;
if(ndb_mgm_get_string_parameter(it, CFG_NODE_HOST, &hostname)){
- snprintf(buf, 255, "Unable to get hostname(%d) from config",CFG_NODE_HOST);
+ BaseString::snprintf(buf, 255, "Unable to get hostname(%d) from config",CFG_NODE_HOST);
setError(CR_ERROR, buf);
return false;
}
@@ -268,7 +268,7 @@ ConfigRetriever::verifyConfig(const struct ndb_mgm_configuration * conf, Uint32
if (hostname && hostname[0] != 0 &&
!SocketServer::tryBind(0,hostname)) {
- snprintf(buf, 255, "Config hostname(%s) don't match a local interface,"
+ BaseString::snprintf(buf, 255, "Config hostname(%s) don't match a local interface,"
" tried to bind, error = %d - %s",
hostname, errno, strerror(errno));
setError(CR_ERROR, buf);
@@ -277,14 +277,14 @@ ConfigRetriever::verifyConfig(const struct ndb_mgm_configuration * conf, Uint32
unsigned int _type;
if(ndb_mgm_get_int_parameter(it, CFG_TYPE_OF_SECTION, &_type)){
- snprintf(buf, 255, "Unable to get type of node(%d) from config",
+ BaseString::snprintf(buf, 255, "Unable to get type of node(%d) from config",
CFG_TYPE_OF_SECTION);
setError(CR_ERROR, buf);
return false;
}
if(_type != m_node_type){
- snprintf(buf, 255, "Supplied node type(%d) and config node type(%d) "
+ BaseString::snprintf(buf, 255, "Supplied node type(%d) and config node type(%d) "
" don't match", m_node_type, _type);
setError(CR_ERROR, buf);
return false;
diff --git a/ndb/src/common/mgmcommon/LocalConfig.cpp b/ndb/src/common/mgmcommon/LocalConfig.cpp
index cc66f357236..3cd4341c6b7 100644
--- a/ndb/src/common/mgmcommon/LocalConfig.cpp
+++ b/ndb/src/common/mgmcommon/LocalConfig.cpp
@@ -40,7 +40,7 @@ LocalConfig::init(const char *connectString,
//1. Check connectString
if(connectString != 0 && connectString[0] != 0){
- if(readConnectString(connectString)){
+ if(readConnectString(connectString, "connect string")){
return true;
}
return false;
@@ -59,7 +59,7 @@ LocalConfig::init(const char *connectString,
char buf[255];
if(NdbEnv_GetEnv("NDB_CONNECTSTRING", buf, sizeof(buf)) &&
strlen(buf) != 0){
- if(readConnectString(buf)){
+ if(readConnectString(buf, "NDB_CONNECTSTRING")){
return true;
}
return false;
@@ -90,8 +90,8 @@ LocalConfig::init(const char *connectString,
//7. Check
{
char buf[256];
- snprintf(buf, sizeof(buf), "host=localhost:%s", NDB_BASE_PORT);
- if(readConnectString(buf))
+ BaseString::snprintf(buf, sizeof(buf), "host=localhost:%s", NDB_BASE_PORT);
+ if(readConnectString(buf, "default connect string"))
return true;
}
@@ -109,8 +109,10 @@ void LocalConfig::setError(int lineNumber, const char * _msg) {
}
void LocalConfig::printError() const {
- ndbout << "Local configuration error"<< endl
- << "Line: "<< error_line << ", " << error_msg << endl << endl;
+ ndbout << "Configuration error" << endl;
+ if (error_line)
+ ndbout << "Line: "<< error_line << ", ";
+ ndbout << error_msg << endl << endl;
}
void LocalConfig::printUsage() const {
@@ -140,7 +142,7 @@ const char *nodeIdTokens[] = {
const char *hostNameTokens[] = {
"host://%[^:]:%i",
"host=%[^:]:%i",
- "%[^:]:%i",
+ "%[^:^=^ ]:%i",
"%s %i",
0
};
@@ -192,7 +194,7 @@ LocalConfig::parseFileName(const char * buf){
}
bool
-LocalConfig::parseString(const char * connectString, char *line){
+LocalConfig::parseString(const char * connectString, BaseString &err){
char * for_strtok;
char * copy = strdup(connectString);
NdbAutoPtr<char> tmp_aptr(copy);
@@ -212,15 +214,12 @@ LocalConfig::parseString(const char * connectString, char *line){
if (found_other = parseFileName(tok))
continue;
- if (line)
- snprintf(line, 150, "Unexpected entry: \"%s\"", tok);
+ err.assfmt("Unexpected entry: \"%s\"", tok);
return false;
}
if (!found_other) {
- if (line)
- snprintf(line, 150, "Missing host/file name extry in \"%s\"",
- connectString);
+ err.appfmt("Missing host/file name extry in \"%s\"", connectString);
return false;
}
@@ -235,7 +234,8 @@ bool LocalConfig::readFile(const char * filename, bool &fopenError)
FILE * file = fopen(filename, "r");
if(file == 0){
- snprintf(line, 150, "Unable to open local config file: %s", filename);
+ BaseString::snprintf(line, sizeof(line),
+ "Unable to open local config file: %s", filename);
setError(0, line);
fopenError = true;
return false;
@@ -243,7 +243,7 @@ bool LocalConfig::readFile(const char * filename, bool &fopenError)
BaseString theString;
- while(fgets(line, 1024, file)){
+ while(fgets(line, sizeof(line), file)){
BaseString tmp(line);
tmp.trim(" \t\n\r");
if(tmp.length() > 0 && tmp.c_str()[0] != '#'){
@@ -251,7 +251,7 @@ bool LocalConfig::readFile(const char * filename, bool &fopenError)
break;
}
}
- while (fgets(line, 1024, file)) {
+ while (fgets(line, sizeof(line), file)) {
BaseString tmp(line);
tmp.trim(" \t\n\r");
if(tmp.length() > 0 && tmp.c_str()[0] != '#'){
@@ -260,11 +260,12 @@ bool LocalConfig::readFile(const char * filename, bool &fopenError)
}
}
- bool return_value = parseString(theString.c_str(), line);
+ BaseString err;
+ bool return_value = parseString(theString.c_str(), err);
if (!return_value) {
BaseString tmp;
- tmp.assfmt("Reading %s: %s", filename, line);
+ tmp.assfmt("Reading %s: %s", filename, err.c_str());
setError(0, tmp.c_str());
}
@@ -273,12 +274,14 @@ bool LocalConfig::readFile(const char * filename, bool &fopenError)
}
bool
-LocalConfig::readConnectString(const char * connectString){
- char line[150], line2[150];
- bool return_value = parseString(connectString, line);
+LocalConfig::readConnectString(const char * connectString,
+ const char * info){
+ BaseString err;
+ bool return_value = parseString(connectString, err);
if (!return_value) {
- snprintf(line2, 150, "Reading NDB_CONNECTSTRING \"%s\": %s", connectString, line);
- setError(0,line2);
+ BaseString err2;
+ err2.assfmt("Reading %d \"%s\": %s", info, connectString, err.c_str());
+ setError(0,err2.c_str());
}
return return_value;
}
diff --git a/ndb/src/common/portlib/NdbDaemon.c b/ndb/src/common/portlib/NdbDaemon.c
index d8d33595156..c73b5927ff4 100644
--- a/ndb/src/common/portlib/NdbDaemon.c
+++ b/ndb/src/common/portlib/NdbDaemon.c
@@ -28,6 +28,8 @@ NdbDaemon_Make(const char* lockfile, const char* logfile, unsigned flags)
int lockfd = -1, logfd = -1, n;
char buf[64];
+ (void)flags; /* remove warning for unused parameter */
+
/* Check that we have write access to lock file */
assert(lockfile != NULL);
lockfd = open(lockfile, O_CREAT|O_RDWR, 0644);
diff --git a/ndb/src/common/portlib/NdbMem.c b/ndb/src/common/portlib/NdbMem.c
index c077d6650ce..f964f4d9937 100644
--- a/ndb/src/common/portlib/NdbMem.c
+++ b/ndb/src/common/portlib/NdbMem.c
@@ -42,6 +42,7 @@ void* NdbMem_Allocate(size_t size)
void* NdbMem_AllocateAlign(size_t size, size_t alignment)
{
+ (void)alignment; /* remove warning for unused parameter */
/*
return (void*)memalign(alignment, size);
TEMP fix
diff --git a/ndb/src/common/portlib/NdbSleep.c b/ndb/src/common/portlib/NdbSleep.c
index 8702a25d1b1..19ab526fda8 100644
--- a/ndb/src/common/portlib/NdbSleep.c
+++ b/ndb/src/common/portlib/NdbSleep.c
@@ -16,7 +16,7 @@
#include <ndb_global.h>
-#include "NdbSleep.h"
+#include <NdbSleep.h>
int
NdbSleep_MilliSleep(int milliseconds){
diff --git a/ndb/src/common/portlib/NdbThread.c b/ndb/src/common/portlib/NdbThread.c
index 60687a9053e..69e39994a9c 100644
--- a/ndb/src/common/portlib/NdbThread.c
+++ b/ndb/src/common/portlib/NdbThread.c
@@ -42,6 +42,8 @@ struct NdbThread* NdbThread_Create(NDB_THREAD_FUNC *p_thread_func,
int result;
pthread_attr_t thread_attr;
+ (void)thread_prio; /* remove warning for unused parameter */
+
if (p_thread_func == NULL)
return 0;
@@ -49,8 +51,7 @@ struct NdbThread* NdbThread_Create(NDB_THREAD_FUNC *p_thread_func,
if (tmpThread == NULL)
return NULL;
- snprintf(tmpThread->thread_name, sizeof(tmpThread->thread_name),
- "%s", p_thread_name);
+ strnmov(tmpThread->thread_name,p_thread_name,sizeof(tmpThread->thread_name));
pthread_attr_init(&thread_attr);
pthread_attr_setstacksize(&thread_attr, thread_stack_size);
@@ -109,6 +110,7 @@ int NdbThread_SetConcurrencyLevel(int level)
#ifdef USE_PTHREAD_EXTRAS
return pthread_setconcurrency(level);
#else
+ (void)level; /* remove warning for unused parameter */
return 0;
#endif
}
diff --git a/ndb/src/common/portlib/memtest.c b/ndb/src/common/portlib/memtest.c
index 059a4ec025e..673f23fa803 100644
--- a/ndb/src/common/portlib/memtest.c
+++ b/ndb/src/common/portlib/memtest.c
@@ -90,7 +90,7 @@ void malloctest(int loopcount, int memsize, int touch) {
long long start=0;
int total=0;
int i=0, j=0;
- int size=memsize*1024*1024; //bytes;
+ int size=memsize*1024*1024; /*bytes*/;
float mean;
char * ptr =0;
@@ -126,7 +126,7 @@ void mmaptest(int loopcount, int memsize, int touch) {
int total=0;
int i=0, j=0;
char * ptr;
- int size=memsize*1024*1024; //bytes;
+ int size=memsize*1024*1024; /*bytes*/;
float mean;
printf("Staring mmaptest ");
@@ -165,7 +165,7 @@ void unmaptest(loopcount, memsize)
int total=0;
int i=0, j=0;
char * ptr;
- int size=memsize*1024*1024; //bytes;
+ int size=memsize*1024*1024; /*bytes*/;
float mean;
printf("Staring munmap test (loopcount = 1 no matter what you prev. set)\n");
@@ -215,7 +215,7 @@ void freetest(int loopcount, int memsize) {
long long start=0;
int total=0;
int i=0, j=0;
- int size=memsize*1024*1024; //bytes;
+ int size=memsize*1024*1024; /*bytes*/;
float mean;
char * ptr =0;
diff --git a/ndb/src/common/transporter/OSE_Receiver.cpp b/ndb/src/common/transporter/OSE_Receiver.cpp
index b7d47b2f88c..63a33fc8f24 100644
--- a/ndb/src/common/transporter/OSE_Receiver.cpp
+++ b/ndb/src/common/transporter/OSE_Receiver.cpp
@@ -41,7 +41,7 @@ OSE_Receiver::OSE_Receiver(TransporterRegistry * tr,
phantomCreated = false;
localNodeId = _localNodeId;
- snprintf(localHostName, sizeof(localHostName),
+ BaseString::snprintf(localHostName, sizeof(localHostName),
"ndb_node%d", localNodeId);
DEBUG("localNodeId = " << localNodeId << " -> localHostName = "
diff --git a/ndb/src/common/transporter/OSE_Transporter.cpp b/ndb/src/common/transporter/OSE_Transporter.cpp
index c9b0f777319..a52862a80e5 100644
--- a/ndb/src/common/transporter/OSE_Transporter.cpp
+++ b/ndb/src/common/transporter/OSE_Transporter.cpp
@@ -51,10 +51,10 @@ OSE_Transporter::OSE_Transporter(int _prioASignalSize,
prioBSignalSize = _prioBSignalSize;
if (strcmp(lHostName, rHostName) == 0){
- snprintf(remoteNodeName, sizeof(remoteNodeName),
+ BaseString::snprintf(remoteNodeName, sizeof(remoteNodeName),
"ndb_node%d", remoteNodeId);
} else {
- snprintf(remoteNodeName, sizeof(remoteNodeName),
+ BaseString::snprintf(remoteNodeName, sizeof(remoteNodeName),
"%s/ndb_node%d", rHostName, remoteNodeId);
}
diff --git a/ndb/src/common/transporter/TCP_Transporter.cpp b/ndb/src/common/transporter/TCP_Transporter.cpp
index 7cfdc224b34..524ecd653e0 100644
--- a/ndb/src/common/transporter/TCP_Transporter.cpp
+++ b/ndb/src/common/transporter/TCP_Transporter.cpp
@@ -362,7 +362,7 @@ TCP_Transporter::doReceive() {
// Select-function must return the socket for read
// before this method is called
// It reads the external TCP/IP interface once
- int size = receiveBuffer.sizeOfBuffer - receiveBuffer.sizeOfData;
+ Uint32 size = receiveBuffer.sizeOfBuffer - receiveBuffer.sizeOfData;
if(size > 0){
const int nBytesRead = recv(theSocket,
receiveBuffer.insertPtr,
diff --git a/ndb/src/common/transporter/Transporter.cpp b/ndb/src/common/transporter/Transporter.cpp
index 7a469252c00..e68bc86718e 100644
--- a/ndb/src/common/transporter/Transporter.cpp
+++ b/ndb/src/common/transporter/Transporter.cpp
@@ -32,7 +32,7 @@ Transporter::Transporter(TransporterRegistry &t_reg,
NodeId rNodeId,
int _byteorder,
bool _compression, bool _checksum, bool _signalId)
- : m_r_port(r_port), localNodeId(lNodeId), remoteNodeId(rNodeId),
+ : m_r_port(r_port), remoteNodeId(rNodeId), localNodeId(lNodeId),
isServer(lNodeId < rNodeId),
m_packer(_signalId, _checksum),
m_transporter_registry(t_reg)
diff --git a/ndb/src/common/transporter/perftest/perfTransporterTest.cpp b/ndb/src/common/transporter/perftest/perfTransporterTest.cpp
index d33221c2835..71df9f12a4c 100644
--- a/ndb/src/common/transporter/perftest/perfTransporterTest.cpp
+++ b/ndb/src/common/transporter/perftest/perfTransporterTest.cpp
@@ -276,7 +276,7 @@ printReport(TestPhase & p){
char buf[255];
if(p.signalSize != 0){
- snprintf(buf, 255,
+ BaseString::snprintf(buf, 255,
"%d\t%d\t%s\t%s\t%s\t%s\t%d\t%d",
p.noOfSignals,
4*p.signalSize,
@@ -287,7 +287,7 @@ printReport(TestPhase & p){
(int)(p.sendLenBytes / (p.sendCount == 0 ? 1 : p.sendCount)),
(int)(p.recvLenBytes / (p.recvCount == 0 ? 1 : p.recvCount)));
} else {
- snprintf(buf, 255,
+ BaseString::snprintf(buf, 255,
"%d\trand\t%s\t%s\t%s\t%s\t%d\t%d",
p.noOfSignals,
st,
diff --git a/ndb/src/common/transporter/priotest/prioTransporterTest.cpp b/ndb/src/common/transporter/priotest/prioTransporterTest.cpp
index 0fce6aaad39..6c5623a49a6 100644
--- a/ndb/src/common/transporter/priotest/prioTransporterTest.cpp
+++ b/ndb/src/common/transporter/priotest/prioTransporterTest.cpp
@@ -375,7 +375,7 @@ printReport(TestPhase & p){
char buf[255];
if(p.signalSize != 0){
- snprintf(buf, 255,
+ BaseString::snprintf(buf, 255,
"%d\t%d\t%d\t%s\t%s\t%s\t%d\t%d\t%d\t%d",
p.noOfSignals,
p.signalSize,
@@ -388,7 +388,7 @@ printReport(TestPhase & p){
(int)(p.totTimePrioA / p.loopCount),
(int)(p.bytesSentBeforePrioA));
} else {
- snprintf(buf, 255,
+ BaseString::snprintf(buf, 255,
"%d\trand\t4*rand\t%s\t%s\t%s\t%d\t%d\t%d\t%d",
p.noOfSignals,
st,
diff --git a/ndb/src/common/util/BaseString.cpp b/ndb/src/common/util/BaseString.cpp
index 8b7df485f77..dbff44c377d 100644
--- a/ndb/src/common/util/BaseString.cpp
+++ b/ndb/src/common/util/BaseString.cpp
@@ -17,6 +17,7 @@
/* -*- c-basic-offset: 4; -*- */
#include <ndb_global.h>
#include <BaseString.hpp>
+#include <basestring_vsnprintf.h>
BaseString::BaseString()
{
@@ -127,14 +128,14 @@ BaseString::assfmt(const char *fmt, ...)
* when called as vsnprintf(NULL, 0, ...).
*/
va_start(ap, fmt);
- l = vsnprintf(buf, sizeof(buf), fmt, ap) + 1;
+ l = basestring_vsnprintf(buf, sizeof(buf), fmt, ap) + 1;
va_end(ap);
if(l > (int)m_len) {
delete[] m_chr;
m_chr = new char[l];
}
va_start(ap, fmt);
- vsnprintf(m_chr, l, fmt, ap);
+ basestring_vsnprintf(m_chr, l, fmt, ap);
va_end(ap);
m_len = strlen(m_chr);
return *this;
@@ -152,11 +153,11 @@ BaseString::appfmt(const char *fmt, ...)
* when called as vsnprintf(NULL, 0, ...).
*/
va_start(ap, fmt);
- l = vsnprintf(buf, sizeof(buf), fmt, ap) + 1;
+ l = basestring_vsnprintf(buf, sizeof(buf), fmt, ap) + 1;
va_end(ap);
char *tmp = new char[l];
va_start(ap, fmt);
- vsnprintf(tmp, l, fmt, ap);
+ basestring_vsnprintf(tmp, l, fmt, ap);
va_end(ap);
append(tmp);
delete[] tmp;
@@ -335,6 +336,22 @@ BaseString::trim(char * str, const char * delim){
return str;
}
+int
+BaseString::vsnprintf(char *str, size_t size, const char *format, va_list ap)
+{
+ return(basestring_vsnprintf(str, size, format, ap));
+}
+
+int
+BaseString::snprintf(char *str, size_t size, const char *format, ...)
+{
+ va_list ap;
+ va_start(ap, format);
+ int ret= basestring_vsnprintf(str, size, format, ap);
+ va_end(ap);
+ return(ret);
+}
+
#ifdef TEST_BASE_STRING
diff --git a/ndb/src/common/util/ConfigValues.cpp b/ndb/src/common/util/ConfigValues.cpp
index 8a14882550c..5c4b17c73ca 100644
--- a/ndb/src/common/util/ConfigValues.cpp
+++ b/ndb/src/common/util/ConfigValues.cpp
@@ -1,9 +1,6 @@
+
+#include <ndb_global.h>
#include <ConfigValues.hpp>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <new>
#include <NdbOut.hpp>
#include <NdbTCP.h>
diff --git a/ndb/src/common/util/File.cpp b/ndb/src/common/util/File.cpp
index 22d262a0d27..f3faa8c4f7f 100644
--- a/ndb/src/common/util/File.cpp
+++ b/ndb/src/common/util/File.cpp
@@ -83,7 +83,7 @@ File_class::File_class(const char* aFileName, const char* mode) :
m_file(NULL),
m_fileMode(mode)
{
- ::snprintf(m_fileName, MAX_FILE_NAME_SIZE, aFileName);
+ BaseString::snprintf(m_fileName, MAX_FILE_NAME_SIZE, aFileName);
}
bool
@@ -99,7 +99,7 @@ File_class::open(const char* aFileName, const char* mode)
/**
* Only copy if it's not the same string
*/
- ::snprintf(m_fileName, MAX_FILE_NAME_SIZE, aFileName);
+ BaseString::snprintf(m_fileName, MAX_FILE_NAME_SIZE, aFileName);
}
m_fileMode = mode;
bool rc = true;
diff --git a/ndb/src/common/util/Makefile.am b/ndb/src/common/util/Makefile.am
index efb249dd330..0235adae7c9 100644
--- a/ndb/src/common/util/Makefile.am
+++ b/ndb/src/common/util/Makefile.am
@@ -9,7 +9,7 @@ libgeneral_la_SOURCES = \
NdbSqlUtil.cpp new.cpp \
uucode.c random.c getarg.c version.c \
strdup.c strlcat.c strlcpy.c \
- ConfigValues.cpp ndb_init.c
+ ConfigValues.cpp ndb_init.c basestring_vsnprintf.c
include $(top_srcdir)/ndb/config/common.mk.am
include $(top_srcdir)/ndb/config/type_util.mk.am
diff --git a/ndb/src/common/util/NdbErrHnd.cpp b/ndb/src/common/util/NdbErrHnd.cpp
index f1c28a7bbdd..38a67f29853 100644
--- a/ndb/src/common/util/NdbErrHnd.cpp
+++ b/ndb/src/common/util/NdbErrHnd.cpp
@@ -346,53 +346,53 @@ extern "C" OSBOOLEAN ndb_err_hnd(bool user_called,
file_name = "ose_err.h";
}
- snprintf (error_message.header1,
+ BaseString::snprintf(error_message.header1,
BUFSIZE,
"This is the OSE Example System Error handler\r\n");
- snprintf (error_message.err_hnd_file,
+ BaseString::snprintf(error_message.err_hnd_file,
BUFSIZE,
"located in: " __FILE__ "\r\n");
- snprintf (error_message.header2,
+ BaseString::snprintf(error_message.header2,
BUFSIZE,
"An Error has been reported:\r\n");
if (user_called == (OSBOOLEAN) 0 ) {
- snprintf(error_message.user_called_line,
+ BaseString::snprintf(error_message.user_called_line,
BUFSIZE,
"user_called: 0x%x (Error detected by the kernel)\r\n",
user_called);
}
else {
- snprintf(error_message.user_called_line,
+ BaseString::snprintf(error_message.user_called_line,
BUFSIZE,
"user_called: 0x%x (Error detected by an application)\r\n",
user_called);
}
- snprintf (error_message.error_code_line,
+ BaseString::snprintf(error_message.error_code_line,
BUFSIZE,
"error code: 0x%08x\r\n",
error_code);
- snprintf (error_message.subcode_line,
+ BaseString::snprintf(error_message.subcode_line,
BUFSIZE,
" subcode: %s (0x%08x)\r\n",
subcode_mnemonic,
( subcode << 16));
- snprintf (error_message.product_line,
+ BaseString::snprintf(error_message.product_line,
BUFSIZE,
" product: %s\r\n",
product_name);
- snprintf (error_message.header_file_line,
+ BaseString::snprintf(error_message.header_file_line,
BUFSIZE,
" header file: %s\r\n",
file_name);
- snprintf (error_message.extra_line,
+ BaseString::snprintf(error_message.extra_line,
BUFSIZE,
"extra: 0x%08x\r\n",
extra);
@@ -401,22 +401,22 @@ extern "C" OSBOOLEAN ndb_err_hnd(bool user_called,
struct OS_pcb *pcb = get_pcb(current_process());
const char *process_name = &pcb->strings[pcb->name];
- snprintf(error_message.current_process_id_line,
+ BaseString::snprintf(error_message.current_process_id_line,
BUFSIZE,
"Current Process: 0x%08x\r\n",
current_process());
- snprintf(error_message.current_process_name_line,
+ BaseString::snprintf(error_message.current_process_name_line,
BUFSIZE,
"Process Name: %s\r\n",
process_name);
- snprintf(error_message.file_line,
+ BaseString::snprintf(error_message.file_line,
BUFSIZE,
"File: %s\r\n",
&pcb->strings[pcb->file]);
- snprintf(error_message.line_line,
+ BaseString::snprintf(error_message.line_line,
BUFSIZE,
"Line: %d\r\n",
pcb->line);
@@ -452,7 +452,7 @@ extern "C" OSBOOLEAN ndb_err_hnd(bool user_called,
char *expr = ((char **)extra)[0];
char *file = ((char **)extra)[1];
unsigned line = ((unsigned *)extra)[2];
- snprintf(assert_line, BUFSIZE, "Assertion Failed: %s:%u: %s\r\n", file, line, expr);
+ BaseString::snprintf(assert_line, BUFSIZE, "Assertion Failed: %s:%u: %s\r\n", file, line, expr);
ndbout << assert_line;
}
}
@@ -467,13 +467,13 @@ extern "C" OSBOOLEAN ndb_err_hnd(bool user_called,
const char *rcv_name = &rcv->strings[rcv->name];
struct OS_pcb *snd = get_pcb(snd_);
const char *snd_name = &snd->strings[snd->name];
- snprintf(unknown_signal_line, BUFSIZE,
+ BaseString::snprintf(unknown_signal_line, BUFSIZE,
"Unknown Signal Received\r\n");
- snprintf(unknown_signal_line, BUFSIZE,
+ BaseString::snprintf(unknown_signal_line, BUFSIZE,
"Signal Number: 0x%08lx\r\n", signo);
- snprintf(unknown_signal_line, BUFSIZE,
+ BaseString::snprintf(unknown_signal_line, BUFSIZE,
"Sending Process: 0x%08lx (%s))\r\n", snd_, snd_name);
- snprintf(unknown_signal_line, BUFSIZE,
+ BaseString::snprintf(unknown_signal_line, BUFSIZE,
"Receiving Process: 0x%08lx (%s))\r\n", rcv_, rcv_name);
free_buf((union SIGNAL **)&rcv);
free_buf((union SIGNAL **)&snd); }
diff --git a/ndb/src/common/util/NdbOut.cpp b/ndb/src/common/util/NdbOut.cpp
index 6d76cf22402..fa74cb364f3 100644
--- a/ndb/src/common/util/NdbOut.cpp
+++ b/ndb/src/common/util/NdbOut.cpp
@@ -102,7 +102,7 @@ NdbOut::print(const char * fmt, ...){
va_start(ap, fmt);
if (fmt != 0)
- vsnprintf(buf, sizeof(buf)-1, fmt, ap);
+ BaseString::vsnprintf(buf, sizeof(buf)-1, fmt, ap);
ndbout << buf;
va_end(ap);
}
@@ -114,7 +114,7 @@ NdbOut::println(const char * fmt, ...){
va_start(ap, fmt);
if (fmt != 0)
- vsnprintf(buf, sizeof(buf)-1, fmt, ap);
+ BaseString::vsnprintf(buf, sizeof(buf)-1, fmt, ap);
ndbout << buf << endl;
va_end(ap);
}
@@ -127,7 +127,7 @@ ndbout_c(const char * fmt, ...){
va_start(ap, fmt);
if (fmt != 0)
- vsnprintf(buf, sizeof(buf)-1, fmt, ap);
+ BaseString::vsnprintf(buf, sizeof(buf)-1, fmt, ap);
ndbout << buf << endl;
va_end(ap);
}
diff --git a/ndb/src/common/util/OutputStream.cpp b/ndb/src/common/util/OutputStream.cpp
index bf3599dbac9..a41eef649dd 100644
--- a/ndb/src/common/util/OutputStream.cpp
+++ b/ndb/src/common/util/OutputStream.cpp
@@ -74,7 +74,7 @@ SoftOseOutputStream::print(const char * fmt, ...){
va_start(ap, fmt);
if (fmt != 0)
- vsnprintf(buf, sizeof(buf)-1, fmt, ap);
+ BaseString::vsnprintf(buf, sizeof(buf)-1, fmt, ap);
else
buf[0] = 0;
va_end(ap);
@@ -88,7 +88,7 @@ SoftOseOutputStream::println(const char * fmt, ...){
va_start(ap, fmt);
if (fmt != 0)
- vsnprintf(buf, sizeof(buf)-1, fmt, ap);
+ BaseString::vsnprintf(buf, sizeof(buf)-1, fmt, ap);
else
buf[0] = 0;
va_end(ap);
diff --git a/ndb/src/common/util/Properties.cpp b/ndb/src/common/util/Properties.cpp
index 80fb0027830..a13e31780eb 100644
--- a/ndb/src/common/util/Properties.cpp
+++ b/ndb/src/common/util/Properties.cpp
@@ -371,7 +371,7 @@ Properties::print(FILE * out, const char * prefix) const{
break;
case PropertiesType_Properties:
char buf2 [1024];
- snprintf(buf2, sizeof(buf2), "%s%s%c",buf, impl->content[i]->name,
+ BaseString::snprintf(buf2, sizeof(buf2), "%s%s%c",buf, impl->content[i]->name,
Properties::delimiter);
((Properties *)impl->content[i]->value)->print(out, buf2);
break;
@@ -994,7 +994,7 @@ bool
Properties::put(const char * name, Uint32 no, Uint32 val, bool replace){
size_t tmp_len = strlen(name)+20;
char * tmp = (char*)malloc(tmp_len);
- snprintf(tmp, tmp_len, "%s_%d", name, no);
+ BaseString::snprintf(tmp, tmp_len, "%s_%d", name, no);
bool res = put(tmp, val, replace);
free(tmp);
return res;
@@ -1004,7 +1004,7 @@ bool
Properties::put64(const char * name, Uint32 no, Uint64 val, bool replace){
size_t tmp_len = strlen(name)+20;
char * tmp = (char*)malloc(tmp_len);
- snprintf(tmp, tmp_len, "%s_%d", name, no);
+ BaseString::snprintf(tmp, tmp_len, "%s_%d", name, no);
bool res = put(tmp, val, replace);
free(tmp);
return res;
@@ -1015,7 +1015,7 @@ bool
Properties::put(const char * name, Uint32 no, const char * val, bool replace){
size_t tmp_len = strlen(name)+20;
char * tmp = (char*)malloc(tmp_len);
- snprintf(tmp, tmp_len, "%s_%d", name, no);
+ BaseString::snprintf(tmp, tmp_len, "%s_%d", name, no);
bool res = put(tmp, val, replace);
free(tmp);
return res;
@@ -1027,7 +1027,7 @@ Properties::put(const char * name, Uint32 no, const Properties * val,
bool replace){
size_t tmp_len = strlen(name)+20;
char * tmp = (char*)malloc(tmp_len);
- snprintf(tmp, tmp_len, "%s_%d", name, no);
+ BaseString::snprintf(tmp, tmp_len, "%s_%d", name, no);
bool res = put(tmp, val, replace);
free(tmp);
return res;
@@ -1039,7 +1039,7 @@ Properties::getTypeOf(const char * name, Uint32 no,
PropertiesType * type) const {
size_t tmp_len = strlen(name)+20;
char * tmp = (char*)malloc(tmp_len);
- snprintf(tmp, tmp_len, "%s_%d", name, no);
+ BaseString::snprintf(tmp, tmp_len, "%s_%d", name, no);
bool res = getTypeOf(tmp, type);
free(tmp);
return res;
@@ -1049,7 +1049,7 @@ bool
Properties::contains(const char * name, Uint32 no) const {
size_t tmp_len = strlen(name)+20;
char * tmp = (char*)malloc(tmp_len);
- snprintf(tmp, tmp_len, "%s_%d", name, no);
+ BaseString::snprintf(tmp, tmp_len, "%s_%d", name, no);
bool res = contains(tmp);
free(tmp);
return res;
@@ -1059,7 +1059,7 @@ bool
Properties::get(const char * name, Uint32 no, Uint32 * value) const{
size_t tmp_len = strlen(name)+20;
char * tmp = (char*)malloc(tmp_len);
- snprintf(tmp, tmp_len, "%s_%d", name, no);
+ BaseString::snprintf(tmp, tmp_len, "%s_%d", name, no);
bool res = get(tmp, value);
free(tmp);
return res;
@@ -1069,7 +1069,7 @@ bool
Properties::get(const char * name, Uint32 no, Uint64 * value) const{
size_t tmp_len = strlen(name)+20;
char * tmp = (char*)malloc(tmp_len);
- snprintf(tmp, tmp_len, "%s_%d", name, no);
+ BaseString::snprintf(tmp, tmp_len, "%s_%d", name, no);
bool res = get(tmp, value);
free(tmp);
return res;
@@ -1080,7 +1080,7 @@ bool
Properties::get(const char * name, Uint32 no, const char ** value) const {
size_t tmp_len = strlen(name)+20;
char * tmp = (char*)malloc(tmp_len);
- snprintf(tmp, tmp_len, "%s_%d", name, no);
+ BaseString::snprintf(tmp, tmp_len, "%s_%d", name, no);
bool res = get(tmp, value);
free(tmp);
return res;
@@ -1091,7 +1091,7 @@ bool
Properties::get(const char * name, Uint32 no, const Properties ** value) const{
size_t tmp_len = strlen(name)+20;
char * tmp = (char*)malloc(tmp_len);
- snprintf(tmp, tmp_len, "%s_%d", name, no);
+ BaseString::snprintf(tmp, tmp_len, "%s_%d", name, no);
bool res = get(tmp, value);
free(tmp);
return res;
@@ -1102,7 +1102,7 @@ bool
Properties::getCopy(const char * name, Uint32 no, char ** value) const {
size_t tmp_len = strlen(name)+20;
char * tmp = (char*)malloc(tmp_len);
- snprintf(tmp, tmp_len, "%s_%d", name, no);
+ BaseString::snprintf(tmp, tmp_len, "%s_%d", name, no);
bool res = getCopy(tmp, value);
free(tmp);
return res;
@@ -1113,7 +1113,7 @@ bool
Properties::getCopy(const char * name, Uint32 no, Properties ** value) const {
size_t tmp_len = strlen(name)+20;
char * tmp = (char*)malloc(tmp_len);
- snprintf(tmp, tmp_len, "%s_%d", name, no);
+ BaseString::snprintf(tmp, tmp_len, "%s_%d", name, no);
bool res = getCopy(tmp, value);
free(tmp);
return res;
diff --git a/ndb/src/common/util/SimpleProperties.cpp b/ndb/src/common/util/SimpleProperties.cpp
index c3980f03c4d..00c440fcb4e 100644
--- a/ndb/src/common/util/SimpleProperties.cpp
+++ b/ndb/src/common/util/SimpleProperties.cpp
@@ -293,7 +293,7 @@ SimpleProperties::Reader::printAll(NdbOut& ndbout){
break;
default:
ndbout << "Unknown type for key: " << getKey()
- << " type: " << getValueType() << endl;
+ << " type: " << (Uint32)getValueType() << endl;
}
}
}
diff --git a/ndb/src/common/util/basestring_vsnprintf.c b/ndb/src/common/util/basestring_vsnprintf.c
new file mode 100644
index 00000000000..10932226d18
--- /dev/null
+++ b/ndb/src/common/util/basestring_vsnprintf.c
@@ -0,0 +1,37 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/* define on IRIX to get posix compliant vsnprintf */
+#define _XOPEN_SOURCE 500
+#include <stdio.h>
+#include <basestring_vsnprintf.h>
+
+int
+basestring_snprintf(char *str, size_t size, const char *format, ...)
+{
+ int ret;
+ va_list ap;
+ va_start(ap, format);
+ ret= basestring_vsnprintf(str, size, format, ap);
+ va_end(ap);
+ return(ret);
+}
+
+int
+basestring_vsnprintf(char *str, size_t size, const char *format, va_list ap)
+{
+ return(vsnprintf(str, size, format, ap));
+}
diff --git a/ndb/src/common/util/socket_io.cpp b/ndb/src/common/util/socket_io.cpp
index b2f4ef91031..6f4c7e63684 100644
--- a/ndb/src/common/util/socket_io.cpp
+++ b/ndb/src/common/util/socket_io.cpp
@@ -175,13 +175,13 @@ vprint_socket(NDB_SOCKET_TYPE socket, int timeout_millis,
size_t size = sizeof(buf);
if (fmt != 0) {
- size = vsnprintf(buf, sizeof(buf), fmt, ap);
+ size = BaseString::vsnprintf(buf, sizeof(buf), fmt, ap);
/* Check if the output was truncated */
if(size >= sizeof(buf)) {
buf2 = (char *)malloc(size+1);
if(buf2 == NULL)
return -1;
- vsnprintf(buf2, size, fmt, ap);
+ BaseString::vsnprintf(buf2, size, fmt, ap);
} else
size = sizeof(buf);
} else
@@ -202,13 +202,13 @@ vprintln_socket(NDB_SOCKET_TYPE socket, int timeout_millis,
size_t size = sizeof(buf);
if (fmt != 0) {
- size = vsnprintf(buf, sizeof(buf), fmt, ap);
+ size = BaseString::vsnprintf(buf, sizeof(buf), fmt, ap);
/* Check if the output was truncated */
if(size >= sizeof(buf)-1) {
buf2 = (char *)malloc(size+2);
if(buf2 == NULL)
return -1;
- vsnprintf(buf2, size+1, fmt, ap);
+ BaseString::vsnprintf(buf2, size+1, fmt, ap);
} else
size = sizeof(buf);
} else
diff --git a/ndb/src/cw/cpcd/APIService.cpp b/ndb/src/cw/cpcd/APIService.cpp
index de0e40cebfc..63d0aaafe86 100644
--- a/ndb/src/cw/cpcd/APIService.cpp
+++ b/ndb/src/cw/cpcd/APIService.cpp
@@ -309,7 +309,7 @@ propToString(Properties *prop, const char *key) {
case PropertiesType_Uint32:
Uint32 val;
prop->get(key, &val);
- snprintf(buf, sizeof buf, "%d", val);
+ BaseString::snprintf(buf, sizeof buf, "%d", val);
retval = buf;
break;
case PropertiesType_char:
@@ -318,7 +318,7 @@ propToString(Properties *prop, const char *key) {
retval = str;
break;
default:
- snprintf(buf, sizeof buf, "(unknown)");
+ BaseString::snprintf(buf, sizeof buf, "(unknown)");
retval = buf;
}
return retval;
diff --git a/ndb/src/cw/cpcd/CPCD.cpp b/ndb/src/cw/cpcd/CPCD.cpp
index bc9f350755f..69a7b840528 100644
--- a/ndb/src/cw/cpcd/CPCD.cpp
+++ b/ndb/src/cw/cpcd/CPCD.cpp
@@ -237,9 +237,9 @@ CPCD::saveProcessList(){
FILE *f;
/* Create the filenames that we will use later */
- snprintf(newfile, sizeof(newfile), "%s.new", m_procfile.c_str());
- snprintf(oldfile, sizeof(oldfile), "%s.old", m_procfile.c_str());
- snprintf(curfile, sizeof(curfile), "%s", m_procfile.c_str());
+ BaseString::snprintf(newfile, sizeof(newfile), "%s.new", m_procfile.c_str());
+ BaseString::snprintf(oldfile, sizeof(oldfile), "%s.old", m_procfile.c_str());
+ BaseString::snprintf(curfile, sizeof(curfile), "%s", m_procfile.c_str());
f = fopen(newfile, "w");
@@ -380,7 +380,7 @@ CPCD::getProcessList() {
void
CPCD::RequestStatus::err(enum RequestStatusCode status, const char *msg) {
m_status = status;
- snprintf(m_errorstring, sizeof(m_errorstring), "%s", msg);
+ BaseString::snprintf(m_errorstring, sizeof(m_errorstring), "%s", msg);
}
#if 0
diff --git a/ndb/src/cw/cpcd/Process.cpp b/ndb/src/cw/cpcd/Process.cpp
index c38b2a45145..2d3973d1aba 100644
--- a/ndb/src/cw/cpcd/Process.cpp
+++ b/ndb/src/cw/cpcd/Process.cpp
@@ -140,7 +140,7 @@ CPCD::Process::readPid() {
memset(buf, 0, sizeof(buf));
- snprintf(filename, sizeof(filename), "%d", m_id);
+ BaseString::snprintf(filename, sizeof(filename), "%d", m_id);
f = fopen(filename, "r");
@@ -167,8 +167,8 @@ CPCD::Process::writePid(int pid) {
char filename[PATH_MAX*2+1];
FILE *f;
- snprintf(tmpfilename, sizeof(tmpfilename), "tmp.XXXXXX");
- snprintf(filename, sizeof(filename), "%d", m_id);
+ BaseString::snprintf(tmpfilename, sizeof(tmpfilename), "tmp.XXXXXX");
+ BaseString::snprintf(filename, sizeof(filename), "%d", m_id);
int fd = mkstemp(tmpfilename);
if(fd < 0) {
@@ -439,7 +439,7 @@ void
CPCD::Process::stop() {
char filename[PATH_MAX*2+1];
- snprintf(filename, sizeof(filename), "%d", m_id);
+ BaseString::snprintf(filename, sizeof(filename), "%d", m_id);
unlink(filename);
if(m_pid <= 1){
diff --git a/ndb/src/kernel/blocks/ERROR_codes.txt b/ndb/src/kernel/blocks/ERROR_codes.txt
index 43532a973f9..70f11c33cd7 100644
--- a/ndb/src/kernel/blocks/ERROR_codes.txt
+++ b/ndb/src/kernel/blocks/ERROR_codes.txt
@@ -3,7 +3,7 @@ Next NDBCNTR 1000
Next NDBFS 2000
Next DBACC 3001
Next DBTUP 4007
-Next DBLQH 5040
+Next DBLQH 5042
Next DBDICT 6006
Next DBDIH 7174
Next DBTC 8035
@@ -193,6 +193,8 @@ Delay execution of ABORTREQ signal 2 seconds to generate time-out.
5038: Drop LQHKEYREQ + set 5039
5039: Drop ABORT + set 5003
+8048: Make TC not choose own node for simple/dirty read
+5041: Crash is receiving simple read from other TC on different node
ERROR CODES FOR TESTING TIME-OUT HANDLING IN DBTC
-------------------------------------------------
diff --git a/ndb/src/kernel/blocks/backup/Backup.cpp b/ndb/src/kernel/blocks/backup/Backup.cpp
index 08a8bf83e20..e6fe63d9014 100644
--- a/ndb/src/kernel/blocks/backup/Backup.cpp
+++ b/ndb/src/kernel/blocks/backup/Backup.cpp
@@ -1307,7 +1307,7 @@ Backup::sendCreateTrig(Signal* signal,
for (int i=0; i < 3; i++) {
req->setTriggerEvent(triggerEventValues[i]);
- snprintf(triggerName, sizeof(triggerName), triggerNameFormat[i],
+ BaseString::snprintf(triggerName, sizeof(triggerName), triggerNameFormat[i],
ptr.p->backupId, tabPtr.p->tableId);
w.reset();
w.add(CreateTrigReq::TriggerNameKey, triggerName);
@@ -1945,7 +1945,7 @@ Backup::sendDropTrig(Signal* signal, BackupRecordPtr ptr, TablePtr tabPtr)
sendSignal(DBDICT_REF, GSN_DROP_TRIG_REQ,
signal, DropTrigReq::SignalLength, JBB);
} else {
- snprintf(triggerName, sizeof(triggerName), triggerNameFormat[i],
+ BaseString::snprintf(triggerName, sizeof(triggerName), triggerNameFormat[i],
ptr.p->backupId, tabPtr.p->tableId);
w.reset();
w.add(CreateTrigReq::TriggerNameKey, triggerName);
@@ -3360,7 +3360,7 @@ Backup::execBACKUP_FRAGMENT_REQ(Signal* signal)
req->senderData = filePtr.i;
req->resultRef = reference();
req->schemaVersion = table.schemaVersion;
- req->fragmentNo = fragNo;
+ req->fragmentNoKeyLen = fragNo;
req->requestInfo = 0;
req->savePointId = 0;
req->tableId = table.tableId;
diff --git a/ndb/src/kernel/blocks/backup/restore/Restore.cpp b/ndb/src/kernel/blocks/backup/restore/Restore.cpp
index 9e1ad228ee5..fb3bde6bdef 100644
--- a/ndb/src/kernel/blocks/backup/restore/Restore.cpp
+++ b/ndb/src/kernel/blocks/backup/restore/Restore.cpp
@@ -515,7 +515,7 @@ BackupFile::setCtlFile(Uint32 nodeId, Uint32 backupId, const char * path){
m_expectedFileHeader.FileType = BackupFormat::CTL_FILE;
char name[PATH_MAX]; const Uint32 sz = sizeof(name);
- snprintf(name, sz, "BACKUP-%d.%d.ctl", backupId, nodeId);
+ BaseString::snprintf(name, sz, "BACKUP-%d.%d.ctl", backupId, nodeId);
setName(path, name);
}
@@ -526,7 +526,7 @@ BackupFile::setDataFile(const BackupFile & bf, Uint32 no){
m_expectedFileHeader.FileType = BackupFormat::DATA_FILE;
char name[PATH_MAX]; const Uint32 sz = sizeof(name);
- snprintf(name, sz, "BACKUP-%d-%d.%d.Data",
+ BaseString::snprintf(name, sz, "BACKUP-%d-%d.%d.Data",
m_expectedFileHeader.BackupId, no, m_nodeId);
setName(bf.m_path, name);
}
@@ -538,7 +538,7 @@ BackupFile::setLogFile(const BackupFile & bf, Uint32 no){
m_expectedFileHeader.FileType = BackupFormat::LOG_FILE;
char name[PATH_MAX]; const Uint32 sz = sizeof(name);
- snprintf(name, sz, "BACKUP-%d.%d.log",
+ BaseString::snprintf(name, sz, "BACKUP-%d.%d.log",
m_expectedFileHeader.BackupId, m_nodeId);
setName(bf.m_path, name);
}
@@ -548,15 +548,15 @@ BackupFile::setName(const char * p, const char * n){
const Uint32 sz = sizeof(m_path);
if(p != 0 && strlen(p) > 0){
if(p[strlen(p)-1] == '/'){
- snprintf(m_path, sz, "%s", p);
+ BaseString::snprintf(m_path, sz, "%s", p);
} else {
- snprintf(m_path, sz, "%s%s", p, "/");
+ BaseString::snprintf(m_path, sz, "%s%s", p, "/");
}
} else {
m_path[0] = 0;
}
- snprintf(m_fileName, sizeof(m_fileName), "%s%s", m_path, n);
+ BaseString::snprintf(m_fileName, sizeof(m_fileName), "%s%s", m_path, n);
debug << "Filename = " << m_fileName << endl;
}
@@ -936,8 +936,9 @@ operator<<(NdbOut& ndbout, const TableS & table){
for (int j = 0; j < table.getNoOfAttributes(); j++)
{
const AttributeDesc * desc = table[j];
- ndbout << desc->m_column->getName() << ": " << desc->m_column->getType();
- ndbout << " key: " << desc->m_column->getPrimaryKey();
+ ndbout << desc->m_column->getName() << ": "
+ << (Uint32) desc->m_column->getType();
+ ndbout << " key: " << (Uint32) desc->m_column->getPrimaryKey();
ndbout << " array: " << desc->arraySize;
ndbout << " size: " << desc->size << endl;
} // for
diff --git a/ndb/src/kernel/blocks/backup/restore/Restore.hpp b/ndb/src/kernel/blocks/backup/restore/Restore.hpp
index 8ca68fd9b23..0ec1ab852e9 100644
--- a/ndb/src/kernel/blocks/backup/restore/Restore.hpp
+++ b/ndb/src/kernel/blocks/backup/restore/Restore.hpp
@@ -91,7 +91,7 @@ class TupleS {
private:
friend class RestoreDataIterator;
- TableS *m_currentTable;
+ class TableS *m_currentTable;
AttributeData *allAttrData;
bool prepareRecord(TableS &);
diff --git a/ndb/src/kernel/blocks/backup/restore/consumer_restore.cpp b/ndb/src/kernel/blocks/backup/restore/consumer_restore.cpp
index fb82570b0b9..a35d9d22c65 100644
--- a/ndb/src/kernel/blocks/backup/restore/consumer_restore.cpp
+++ b/ndb/src/kernel/blocks/backup/restore/consumer_restore.cpp
@@ -121,7 +121,7 @@ BackupRestore::get_table(const NdbDictionary::Table* tab){
int cnt, id1, id2;
char buf[256];
if((cnt = sscanf(tab->getName(), "%[^/]/%[^/]/NDB$BLOB_%d_%d", buf, buf, &id1, &id2)) == 4){
- snprintf(buf, sizeof(buf), "NDB$BLOB_%d_%d", m_new_tables[id1]->getTableId(), id2);
+ BaseString::snprintf(buf, sizeof(buf), "NDB$BLOB_%d_%d", m_new_tables[id1]->getTableId(), id2);
m_cache.m_new_table = m_ndb->getDictionary()->getTable(buf);
} else {
m_cache.m_new_table = m_new_tables[tab->getTableId()];
diff --git a/ndb/src/kernel/blocks/dbacc/Dbacc.hpp b/ndb/src/kernel/blocks/dbacc/Dbacc.hpp
index 3bf50026c4b..169b77c0d85 100644
--- a/ndb/src/kernel/blocks/dbacc/Dbacc.hpp
+++ b/ndb/src/kernel/blocks/dbacc/Dbacc.hpp
@@ -1087,10 +1087,10 @@ private:
void deleteLongKey(Signal* signal);
void removeFromPageArrayList(Signal* signal);
void insertPageArrayList(Signal* signal);
- void checkPageArrayList(Signal* signal, char *);
- void checkPageB4Insert(Uint32, char *);
- void checkPageB4Remove(Uint32, char *);
- void checkIndexInLongKeyPage(Uint32, char *);
+ void checkPageArrayList(Signal* signal, const char *);
+ void checkPageB4Insert(Uint32, const char *);
+ void checkPageB4Remove(Uint32, const char *);
+ void checkIndexInLongKeyPage(Uint32, const char *);
void printoutInfoAndShutdown(LongKeyPage *);
void releaseLongPage(Signal* signal);
void abortOperation(Signal* signal);
diff --git a/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp b/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp
index 79034c9eb36..9a1bbd86562 100644
--- a/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp
+++ b/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp
@@ -2369,7 +2369,7 @@ void Dbacc::execACC_COMMITREQ(Signal* signal)
ptrCheckGuard(rootfragrecptr, crootfragmentsize, rootfragmentrec);
rootfragrecptr.p->noOfElements++;
fragrecptr.p->slack -= operationRecPtr.p->insertDeleteLen;
- if (fragrecptr.p->slack >= (Uint32)(1 << 31)) {
+ if (fragrecptr.p->slack >= (1u << 31)) {
/* IT MEANS THAT IF SLACK < ZERO */
if (fragrecptr.p->expandFlag == 0) {
jam();
@@ -2479,7 +2479,7 @@ void Dbacc::execACC_LOCKREQ(Signal* signal)
Uint32 opCode = ZSCAN_OP;
signal->theData[0] = operationRecPtr.i;
signal->theData[1] = fragrecptr.i;
- signal->theData[2] = opCode | (lockMode << 4) | (1 << 31);
+ signal->theData[2] = opCode | (lockMode << 4) | (1u << 31);
signal->theData[3] = req->hashValue;
signal->theData[4] = 1; // fake primKeyLen
signal->theData[5] = req->transId1;
@@ -4051,7 +4051,7 @@ void Dbacc::deleteLongKey(Signal* signal)
}//Dbacc::deleteLongKey()
-void Dbacc::checkIndexInLongKeyPage(Uint32 pageId, char *calledFrom) {
+void Dbacc::checkIndexInLongKeyPage(Uint32 pageId, const char *calledFrom) {
Page8Ptr pagePtr;
LongKeyPage *page;
Uint32 indexNo;
@@ -4206,7 +4206,7 @@ void Dbacc::insertPageArrayList(Signal* signal)
// --------------------------------------------------------------------------------- */
// Check the page array list.
// --------------------------------------------------------------------------------- */
-void Dbacc::checkPageArrayList(Signal* signal, char *calledFrom)
+void Dbacc::checkPageArrayList(Signal* signal, const char *calledFrom)
{
Page8Ptr pagePtr;
Uint32 pageArrayIndex;
@@ -4251,7 +4251,7 @@ void Dbacc::checkPageArrayList(Signal* signal, char *calledFrom)
// --------------------------------------------------------------------------------- */
// Check the page to put into the pageArrayList.
// --------------------------------------------------------------------------------- */
-void Dbacc::checkPageB4Insert(Uint32 pageId, char *calledFrom) {
+void Dbacc::checkPageB4Insert(Uint32 pageId, const char *calledFrom) {
Page8Ptr pagePtr;
Uint32 pageArrayIndex;
LongKeyPage *page;
@@ -4318,7 +4318,7 @@ void Dbacc::checkPageB4Insert(Uint32 pageId, char *calledFrom) {
// --------------------------------------------------------------------------------- */
// Check the page to remove from the pageArrayList.
// --------------------------------------------------------------------------------- */
-void Dbacc::checkPageB4Remove(Uint32 pageId, char *calledFrom) {
+void Dbacc::checkPageB4Remove(Uint32 pageId, const char *calledFrom) {
Page8Ptr pagePtr;
Uint32 pageArrayIndex;
Uint32 noOfOccurrence = 0;
@@ -6510,7 +6510,7 @@ void Dbacc::endofexpLab(Signal* signal)
Uint32 noOfBuckets = (fragrecptr.p->maxp + 1) + fragrecptr.p->p;
Uint32 Thysteres = fragrecptr.p->maxloadfactor - fragrecptr.p->minloadfactor;
fragrecptr.p->slackCheck = noOfBuckets * Thysteres;
- if (fragrecptr.p->slack > (Uint32)(1 << 31)) {
+ if (fragrecptr.p->slack > (1u << 31)) {
jam();
/* IT MEANS THAT IF SLACK < ZERO */
/* --------------------------------------------------------------------------------- */
@@ -6974,7 +6974,7 @@ void Dbacc::execSHRINKCHECK2(Signal* signal)
/*--------------------------------------------------------------*/
return;
}//if
- if (fragrecptr.p->slack > (Uint32)(1 << 31)) {
+ if (fragrecptr.p->slack > (1u << 31)) {
jam();
/*--------------------------------------------------------------*/
/* THE SLACK IS NEGATIVE, IN THIS CASE WE WILL NOT NEED ANY */
@@ -7213,7 +7213,7 @@ void Dbacc::endofshrinkbucketLab(Signal* signal)
expDirRangePtr.p->dirArray[fragrecptr.p->expSenderDirIndex >> 8] = RNIL;
}//if
}//if
- if (fragrecptr.p->slack < (Uint32)(1 << 31)) {
+ if (fragrecptr.p->slack < (1u << 31)) {
jam();
/*--------------------------------------------------------------*/
/* THE SLACK IS POSITIVE, IN THIS CASE WE WILL CHECK WHETHER */
@@ -13411,8 +13411,12 @@ Dbacc::execREAD_PSUEDO_REQ(Signal* signal){
default:
tmp = 0;
}
- Uint32 * src = (Uint32*)&tmp;
- signal->theData[0] = src[0];
- signal->theData[1] = src[1];
+ memcpy(signal->theData, &tmp, 8); /* must be memcpy, gives strange results on
+ * ithanium gcc (GCC) 3.4.1 smp linux 2.4
+ * otherwise
+ */
+ // Uint32 * src = (Uint32*)&tmp;
+ // signal->theData[0] = src[0];
+ // signal->theData[1] = src[1];
}
diff --git a/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp b/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp
index 572e9f39ba5..76aa745c3e0 100644
--- a/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp
+++ b/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp
@@ -1438,7 +1438,7 @@ void Dbdih::execREAD_NODESCONF(Signal* signal)
continue;
}
char buf[255];
- snprintf(buf, sizeof(buf),
+ BaseString::snprintf(buf, sizeof(buf),
"Illegal configuration change."
" Initial start needs to be performed "
" when changing no of storage nodes (node %d)", i);
@@ -1638,7 +1638,7 @@ void Dbdih::execSTART_PERMREQ(Signal* signal)
}//if
if (getNodeStatus(nodeId) != NodeRecord::DEAD){
ndbout << "nodeStatus in START_PERMREQ = "
- << getNodeStatus(nodeId) << endl;
+ << (Uint32) getNodeStatus(nodeId) << endl;
ndbrequire(false);
}//if
@@ -3500,7 +3500,7 @@ void Dbdih::selectMasterCandidateAndSend(Signal* signal)
Uint32 count = node_groups[nodePtr.i];
if(count != 0 && count != cnoReplicas){
char buf[255];
- snprintf(buf, sizeof(buf),
+ BaseString::snprintf(buf, sizeof(buf),
"Illegal configuration change."
" Initial start needs to be performed "
" when changing no of replicas (%d != %d)",
@@ -4268,7 +4268,7 @@ void Dbdih::failedNodeLcpHandling(Signal* signal, NodeRecordPtr failedNodePtr)
failedNodePtr.p->activeStatus = Sysfile::NS_NotActive_NotTakenOver;
break;
default:
- ndbout << "activeStatus = " << failedNodePtr.p->activeStatus;
+ ndbout << "activeStatus = " << (Uint32) failedNodePtr.p->activeStatus;
ndbout << " at failure after NODE_FAILREP of node = ";
ndbout << failedNodePtr.i << endl;
ndbrequire(false);
@@ -4618,6 +4618,7 @@ void Dbdih::execMASTER_GCPREQ(Signal* signal)
/* BUT NOT YET COMPLETED. */
/*--------------------------------------------------*/
ndbrequire(false);
+ gcpState= MasterGCPConf::GCP_READY; // remove warning
break;
default:
/*------------------------------------------------*/
@@ -4627,6 +4628,7 @@ void Dbdih::execMASTER_GCPREQ(Signal* signal)
/* NODE WHICH WAS NOT A MASTER NODE. */
/*------------------------------------------------*/
ndbrequire(false);
+ gcpState= MasterGCPConf::GCP_READY; // remove warning
break;
}//switch
MasterGCPConf * const masterGCPConf = (MasterGCPConf *)&signal->theData[0];
@@ -5535,6 +5537,7 @@ Dbdih::sendMASTER_LCPCONF(Signal * signal){
* it not allowed
*/
ndbrequire(false);
+ lcpState= MasterLCPConf::LCP_STATUS_IDLE; // remove warning
break;
case LCP_COPY_GCI:
case LCP_INIT_TABLES:
@@ -5543,6 +5546,7 @@ Dbdih::sendMASTER_LCPCONF(Signal * signal){
* These two states are handled by if statements above
*/
ndbrequire(false);
+ lcpState= MasterLCPConf::LCP_STATUS_IDLE; // remove warning
break;
}//switch
ndbrequire(ok);
@@ -6198,7 +6202,8 @@ void Dbdih::execCREATE_FRAGMENTATION_REQ(Signal * signal){
if (primaryTableId == RNIL) {
if(fragmentNode == 0){
jam();
- NGPtr.i = c_nextNodeGroup;
+ // needs to be fixed for single fragment tables
+ NGPtr.i = 0; //c_nextNodeGroup;
c_nextNodeGroup = (NGPtr.i + 1 == cnoOfNodeGroups ? 0 : NGPtr.i + 1);
} else if(! (fragmentNode < MAX_NDB_NODES)) {
jam();
@@ -6255,20 +6260,22 @@ void Dbdih::execCREATE_FRAGMENTATION_REQ(Signal * signal){
//@todo use section writer
Uint32 count = 2;
Uint32 fragments[2 + 8*MAX_REPLICAS*MAX_NDB_NODES];
+ Uint32 next_replica_node[MAX_NDB_NODES];
+ memset(next_replica_node,0,sizeof(next_replica_node));
if (primaryTableId == RNIL) {
jam();
for(Uint32 fragNo = 0; fragNo<noOfFragments; fragNo++){
jam();
ptrCheckGuard(NGPtr, MAX_NDB_NODES, nodeGroupRecord);
- Uint32 ind = NGPtr.p->nextReplicaNode;
+ Uint32 ind = next_replica_node[NGPtr.i];
const Uint32 max = NGPtr.p->nodeCount;
//-------------------------------------------------------------------
// We make an extra step to ensure that the primary replicas are
// spread among the nodes.
//-------------------------------------------------------------------
- NGPtr.p->nextReplicaNode = (ind + 1 >= max ? 0 : ind + 1);
+ next_replica_node[NGPtr.i] = (ind + 1 >= max ? 0 : ind + 1);
for(Uint32 replicaNo = 0; replicaNo<noOfReplicas; replicaNo++){
jam();
@@ -7127,7 +7134,7 @@ void Dbdih::checkGcpStopLab(Signal* signal)
jam();
#ifdef VM_TRACE
ndbout << "System crash due to GCP Stop in state = ";
- ndbout << cgcpStatus << endl;
+ ndbout << (Uint32) cgcpStatus << endl;
#endif
crashSystemAtGcpStop(signal);
return;
@@ -7141,7 +7148,7 @@ void Dbdih::checkGcpStopLab(Signal* signal)
jam();
#ifdef VM_TRACE
ndbout << "System crash due to GCP Stop in state = ";
- ndbout << cgcpStatus << endl;
+ ndbout << (Uint32) cgcpStatus << endl;
#endif
crashSystemAtGcpStop(signal);
return;
@@ -8631,7 +8638,7 @@ void Dbdih::startFragment(Signal* signal, Uint32 tableId, Uint32 fragId)
/* POSSIBLE TO RESTORE THE SYSTEM. */
/* --------------------------------------------------------------------- */
char buf[100];
- snprintf(buf, sizeof(buf),
+ BaseString::snprintf(buf, sizeof(buf),
"Unable to find restorable replica for "
"table: %d fragment: %d gci: %d",
tableId, fragId, SYSFILE->newestRestorableGCI);
@@ -9074,7 +9081,7 @@ void Dbdih::checkTcCounterLab(Signal* signal)
{
CRASH_INSERTION(7009);
if (c_lcpState.lcpStatus != LCP_STATUS_IDLE) {
- ndbout << "lcpStatus = " << c_lcpState.lcpStatus;
+ ndbout << "lcpStatus = " << (Uint32) c_lcpState.lcpStatus;
ndbout << "lcpStatusUpdatedPlace = " <<
c_lcpState.lcpStatusUpdatedPlace << endl;
ndbrequire(false);
@@ -12735,6 +12742,7 @@ void Dbdih::setNodeRestartInfoBits()
break;
default:
ndbrequire(false);
+ tsnrNodeActiveStatus = Sysfile::NS_NotDefined; // remove warning
break;
}//switch
Sysfile::setNodeStatus(nodePtr.i, SYSFILE->nodeStatus,
@@ -12939,7 +12947,7 @@ Dbdih::execDUMP_STATE_ORD(Signal* signal)
snprintf(buf, sizeof(buf), " Table %d Fragment %d - ", tabPtr.i, j);
for(Uint32 k = 0; k < noOfReplicas; k++){
char tmp[100];
- snprintf(tmp, sizeof(tmp), "%d ", nodeOrder[k]);
+ BaseString::snprintf(tmp, sizeof(tmp), "%d ", nodeOrder[k]);
strcat(buf, tmp);
}
infoEvent(buf);
@@ -13155,12 +13163,12 @@ Dbdih::execDUMP_STATE_ORD(Signal* signal)
replicaPtr.i = fragPtr.p->storedReplicas;
do {
ptrCheckGuard(replicaPtr, creplicaFileSize, replicaRecord);
- snprintf(buf2, sizeof(buf2), "%s %d(on %d)=%d(%s)",
+ BaseString::snprintf(buf2, sizeof(buf2), "%s %d(on %d)=%d(%s)",
buf, num,
replicaPtr.p->procNode,
replicaPtr.p->lcpIdStarted,
replicaPtr.p->lcpOngoingFlag ? "Ongoing" : "Idle");
- snprintf(buf, sizeof(buf), "%s", buf2);
+ BaseString::snprintf(buf, sizeof(buf), "%s", buf2);
num++;
replicaPtr.i = replicaPtr.p->nextReplica;
diff --git a/ndb/src/kernel/blocks/dblqh/Dblqh.hpp b/ndb/src/kernel/blocks/dblqh/Dblqh.hpp
index a94af7b59c8..d6987f3e478 100644
--- a/ndb/src/kernel/blocks/dblqh/Dblqh.hpp
+++ b/ndb/src/kernel/blocks/dblqh/Dblqh.hpp
@@ -234,10 +234,6 @@
#define ZNODE_UP 0
#define ZNODE_DOWN 1
/* ------------------------------------------------------------------------- */
-/* OPERATION TYPES */
-/* ------------------------------------------------------------------------- */
-#define ZSIMPLE_READ 1
-/* ------------------------------------------------------------------------- */
/* START PHASES */
/* ------------------------------------------------------------------------- */
#define ZLAST_START_PHASE 255
@@ -2248,7 +2244,7 @@ private:
void sendAttrinfoLoop(Signal* signal);
void sendAttrinfoSignal(Signal* signal);
void sendLqhAttrinfoSignal(Signal* signal);
- void sendKeyinfoAcc(Signal* signal);
+ void sendKeyinfoAcc(Signal* signal, Uint32 pos);
Uint32 initScanrec(const class ScanFragReq *);
void initScanTc(Signal* signal,
Uint32 transid1,
@@ -2437,6 +2433,7 @@ private:
void abortStateHandlerLab(Signal* signal);
void writeAttrinfoLab(Signal* signal);
void scanAttrinfoLab(Signal* signal, Uint32* dataPtr, Uint32 length);
+ void abort_scan(Signal* signal, Uint32 scan_ptr_i, Uint32 errcode);
void localAbortStateHandlerLab(Signal* signal);
void logLqhkeyreqLab(Signal* signal);
void lqhAttrinfoLab(Signal* signal, Uint32* dataPtr, Uint32 length);
diff --git a/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp b/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp
index 8342870d69c..cd15ad0c3b2 100644
--- a/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp
+++ b/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp
@@ -2803,8 +2803,10 @@ void Dblqh::execKEYINFO(Signal* signal)
return;
}//if
TcConnectionrec * const regTcPtr = tcConnectptr.p;
- if (regTcPtr->transactionState !=
- TcConnectionrec::WAIT_TUPKEYINFO) {
+ TcConnectionrec::TransactionState state = regTcPtr->transactionState;
+ if (state != TcConnectionrec::WAIT_TUPKEYINFO &&
+ state != TcConnectionrec::WAIT_SCAN_AI)
+ {
jam();
/*****************************************************************************/
/* TRANSACTION WAS ABORTED, THIS IS MOST LIKELY A SIGNAL BELONGING TO THE */
@@ -2823,14 +2825,20 @@ void Dblqh::execKEYINFO(Signal* signal)
}//if
jam();
terrorCode = errorCode;
- abortErrorLab(signal);
+ if(state == TcConnectionrec::WAIT_TUPKEYINFO)
+ abortErrorLab(signal);
+ else
+ abort_scan(signal, regTcPtr->tcScanRec, errorCode);
return;
}//if
- FragrecordPtr regFragptr;
- regFragptr.i = regTcPtr->fragmentptr;
- ptrCheckGuard(regFragptr, cfragrecFileSize, fragrecord);
- fragptr = regFragptr;
- endgettupkeyLab(signal);
+ if(state == TcConnectionrec::WAIT_TUPKEYINFO)
+ {
+ FragrecordPtr regFragptr;
+ regFragptr.i = regTcPtr->fragmentptr;
+ ptrCheckGuard(regFragptr, cfragrecFileSize, fragrecord);
+ fragptr = regFragptr;
+ endgettupkeyLab(signal);
+ }
return;
}//Dblqh::execKEYINFO()
@@ -2838,9 +2846,9 @@ void Dblqh::execKEYINFO(Signal* signal)
/* FILL IN KEY DATA INTO DATA BUFFERS. */
/* ------------------------------------------------------------------------- */
Uint32 Dblqh::handleLongTupKey(Signal* signal,
- Uint32 keyLength,
- Uint32 primKeyLength,
- Uint32* dataPtr)
+ Uint32 keyLength,
+ Uint32 primKeyLength,
+ Uint32* dataPtr)
{
TcConnectionrec * const regTcPtr = tcConnectptr.p;
Uint32 dataPos = 0;
@@ -3293,12 +3301,15 @@ void Dblqh::execLQHKEYREQ(Signal* signal)
regTcPtr->dirtyOp = LqhKeyReq::getDirtyFlag(Treqinfo);
regTcPtr->opExec = LqhKeyReq::getInterpretedFlag(Treqinfo);
regTcPtr->opSimple = LqhKeyReq::getSimpleFlag(Treqinfo);
- regTcPtr->simpleRead = ((Treqinfo >> 18) & 15);
regTcPtr->operation = LqhKeyReq::getOperation(Treqinfo);
+ regTcPtr->simpleRead = regTcPtr->operation == ZREAD && regTcPtr->opSimple;
regTcPtr->seqNoReplica = LqhKeyReq::getSeqNoReplica(Treqinfo);
UintR TreclenAiLqhkey = LqhKeyReq::getAIInLqhKeyReq(Treqinfo);
regTcPtr->apiVersionNo = 0;
+ CRASH_INSERTION2(5041, regTcPtr->simpleRead &&
+ refToNode(signal->senderBlockRef()) != cownNodeid);
+
regTcPtr->reclenAiLqhkey = TreclenAiLqhkey;
regTcPtr->currReclenAi = TreclenAiLqhkey;
UintR TitcKeyLen = LqhKeyReq::getKeyLen(Treqinfo);
@@ -3425,7 +3436,7 @@ void Dblqh::execLQHKEYREQ(Signal* signal)
if ((tfragDistKey != TdistKey) &&
(regTcPtr->seqNoReplica == 0) &&
(regTcPtr->dirtyOp == ZFALSE) &&
- (regTcPtr->simpleRead != ZSIMPLE_READ)) {
+ (regTcPtr->simpleRead == ZFALSE)) {
/* ----------------------------------------------------------------------
* WE HAVE DIFFERENT OPINION THAN THE DIH THAT STARTED THE TRANSACTION.
* THE REASON COULD BE THAT THIS IS AN OLD DISTRIBUTION WHICH IS NO LONGER
@@ -3433,7 +3444,7 @@ void Dblqh::execLQHKEYREQ(Signal* signal)
* ONE IS ADDED TO THE DISTRIBUTION KEY EVERY TIME WE ADD A NEW REPLICA.
* FAILED REPLICAS DO NOT AFFECT THE DISTRIBUTION KEY. THIS MEANS THAT THE
* MAXIMUM DEVIATION CAN BE ONE BETWEEN THOSE TWO VALUES.
- * ---------------------------------------------------------------------- */
+ * --------------------------------------------------------------------- */
Int32 tmp = TdistKey - tfragDistKey;
tmp = (tmp < 0 ? - tmp : tmp);
if ((tmp <= 1) || (tfragDistKey == 0)) {
@@ -3686,7 +3697,7 @@ void Dblqh::prepareContinueAfterBlockedLab(Signal* signal)
signal->theData[9] = sig3;
signal->theData[10] = sig4;
if (regTcPtr->primKeyLen > 4) {
- sendKeyinfoAcc(signal);
+ sendKeyinfoAcc(signal, 11);
}//if
EXECUTE_DIRECT(refToBlock(regTcPtr->tcAccBlockref), GSN_ACCKEYREQ,
signal, 7 + regTcPtr->primKeyLen);
@@ -3708,9 +3719,8 @@ void Dblqh::prepareContinueAfterBlockedLab(Signal* signal)
/* ======= SEND KEYINFO TO ACC ======= */
/* */
/* ========================================================================== */
-void Dblqh::sendKeyinfoAcc(Signal* signal)
+void Dblqh::sendKeyinfoAcc(Signal* signal, Uint32 Ti)
{
- UintR Ti = 11;
DatabufPtr regDatabufptr;
regDatabufptr.i = tcConnectptr.p->firstTupkeybuf;
@@ -3874,7 +3884,7 @@ void Dblqh::tupkeyConfLab(Signal* signal)
/* ---- GET OPERATION TYPE AND CHECK WHAT KIND OF OPERATION IS REQUESTED ---- */
const TupKeyConf * const tupKeyConf = (TupKeyConf *)&signal->theData[0];
TcConnectionrec * const regTcPtr = tcConnectptr.p;
- if (regTcPtr->simpleRead == ZSIMPLE_READ) {
+ if (regTcPtr->simpleRead) {
jam();
/* ----------------------------------------------------------------------
* THE OPERATION IS A SIMPLE READ. WE WILL IMMEDIATELY COMMIT THE OPERATION.
@@ -5462,6 +5472,8 @@ void Dblqh::commitContinueAfterBlockedLab(Signal* signal)
TcConnectionrec * const regTcPtr = tcConnectptr.p;
Fragrecord * const regFragptr = fragptr.p;
Uint32 operation = regTcPtr->operation;
+ Uint32 simpleRead = regTcPtr->simpleRead;
+ Uint32 dirtyOp = regTcPtr->dirtyOp;
if (regTcPtr->activeCreat == ZFALSE) {
if ((cCommitBlocked == true) &&
(regFragptr->fragActiveStatus == ZTRUE)) {
@@ -5499,13 +5511,18 @@ void Dblqh::commitContinueAfterBlockedLab(Signal* signal)
tupCommitReq->hashValue = regTcPtr->hashValue;
EXECUTE_DIRECT(tup, GSN_TUP_COMMITREQ, signal,
TupCommitReq::SignalLength);
- }//if
- Uint32 acc = refToBlock(regTcPtr->tcAccBlockref);
- signal->theData[0] = regTcPtr->accConnectrec;
- EXECUTE_DIRECT(acc, GSN_ACC_COMMITREQ, signal, 1);
- Uint32 simpleRead = regTcPtr->simpleRead;
+ Uint32 acc = refToBlock(regTcPtr->tcAccBlockref);
+ signal->theData[0] = regTcPtr->accConnectrec;
+ EXECUTE_DIRECT(acc, GSN_ACC_COMMITREQ, signal, 1);
+ } else {
+ if(!dirtyOp){
+ Uint32 acc = refToBlock(regTcPtr->tcAccBlockref);
+ signal->theData[0] = regTcPtr->accConnectrec;
+ EXECUTE_DIRECT(acc, GSN_ACC_COMMITREQ, signal, 1);
+ }
+ }
jamEntry();
- if (simpleRead == ZSIMPLE_READ) {
+ if (simpleRead) {
jam();
/* ------------------------------------------------------------------------- */
/*THE OPERATION WAS A SIMPLE READ THUS THE COMMIT PHASE IS ONLY NEEDED TO */
@@ -5518,7 +5535,6 @@ void Dblqh::commitContinueAfterBlockedLab(Signal* signal)
return;
}//if
}//if
- Uint32 dirtyOp = regTcPtr->dirtyOp;
Uint32 seqNoReplica = regTcPtr->seqNoReplica;
if (regTcPtr->gci > regFragptr->newestGci) {
jam();
@@ -6087,7 +6103,7 @@ void Dblqh::abortStateHandlerLab(Signal* signal)
/* ------------------------------------------------------------------------- */
return;
}//if
- if (regTcPtr->simpleRead == ZSIMPLE_READ) {
+ if (regTcPtr->simpleRead) {
jam();
/* ------------------------------------------------------------------------- */
/*A SIMPLE READ IS CURRENTLY RELEASING THE LOCKS OR WAITING FOR ACCESS TO */
@@ -6373,7 +6389,7 @@ void Dblqh::continueAbortLab(Signal* signal)
void Dblqh::continueAfterLogAbortWriteLab(Signal* signal)
{
TcConnectionrec * const regTcPtr = tcConnectptr.p;
- if (regTcPtr->simpleRead == ZSIMPLE_READ) {
+ if (regTcPtr->simpleRead) {
jam();
TcKeyRef * const tcKeyRef = (TcKeyRef *) signal->getDataPtrSend();
@@ -7409,7 +7425,8 @@ void Dblqh::execSCAN_FRAGREQ(Signal* signal)
jamEntry();
const Uint32 reqinfo = scanFragReq->requestInfo;
- const Uint32 fragId = scanFragReq->fragmentNo;
+ const Uint32 fragId = (scanFragReq->fragmentNoKeyLen & 0xFFFF);
+ const Uint32 keyLen = (scanFragReq->fragmentNoKeyLen >> 16);
tabptr.i = scanFragReq->tableId;
const Uint32 max_rows = scanFragReq->batch_size_rows;
const Uint32 scanLockMode = ScanFragReq::getLockMode(reqinfo);
@@ -7473,6 +7490,8 @@ void Dblqh::execSCAN_FRAGREQ(Signal* signal)
transid2,
fragId,
ZNIL);
+ tcConnectptr.p->save1 = 4;
+ tcConnectptr.p->primKeyLen = keyLen + 4; // hard coded in execKEYINFO
errorCode = initScanrec(scanFragReq);
if (errorCode != ZOK) {
jam();
@@ -7585,23 +7604,29 @@ void Dblqh::scanAttrinfoLab(Signal* signal, Uint32* dataPtr, Uint32 length)
}//if
return;
}//if
- terrorCode = ZGET_ATTRINBUF_ERROR;
+ abort_scan(signal, scanptr.i, ZGET_ATTRINBUF_ERROR);
+}
+
+void Dblqh::abort_scan(Signal* signal, Uint32 scan_ptr_i, Uint32 errcode){
+ jam();
+ scanptr.i = scan_ptr_i;
+ c_scanRecordPool.getPtr(scanptr);
finishScanrec(signal);
releaseScanrec(signal);
tcConnectptr.p->transactionState = TcConnectionrec::IDLE;
tcConnectptr.p->abortState = TcConnectionrec::ABORT_ACTIVE;
-
+
ScanFragRef * ref = (ScanFragRef*)&signal->theData[0];
ref->senderData = tcConnectptr.p->clientConnectrec;
ref->transId1 = tcConnectptr.p->transid[0];
ref->transId2 = tcConnectptr.p->transid[1];
- ref->errorCode = terrorCode;
+ ref->errorCode = errcode;
sendSignal(tcConnectptr.p->clientBlockref, GSN_SCAN_FRAGREF, signal,
ScanFragRef::SignalLength, JBB);
deleteTransidHash(signal);
releaseOprec(signal);
releaseTcrec(signal, tcConnectptr);
-}//Dblqh::scanAttrinfoLab()
+}
/*---------------------------------------------------------------------*/
/* Send this 'I am alive' signal to TC when it is received from ACC */
@@ -7672,34 +7697,17 @@ void Dblqh::accScanConfScanLab(Signal* signal)
return;
}//if
scanptr.p->scanAccPtr = accScanConf->accPtr;
- AttrbufPtr regAttrinbufptr;
- regAttrinbufptr.i = tcConnectptr.p->firstAttrinbuf;
- Uint32 boundAiLength = 0;
+ Uint32 boundAiLength = tcConnectptr.p->primKeyLen - 4;
if (scanptr.p->rangeScan) {
jam();
- // bound info length is in first of the 5 header words
- ptrCheckGuard(regAttrinbufptr, cattrinbufFileSize, attrbuf);
- boundAiLength = regAttrinbufptr.p->attrbuf[0];
TuxBoundInfo* const req = (TuxBoundInfo*)signal->getDataPtrSend();
req->errorCode = RNIL;
req->tuxScanPtrI = scanptr.p->scanAccPtr;
req->boundAiLength = boundAiLength;
- Uint32* out = (Uint32*)req + TuxBoundInfo::SignalLength;
- Uint32 sz = 0;
- while (sz < boundAiLength) {
- jam();
- ptrCheckGuard(regAttrinbufptr, cattrinbufFileSize, attrbuf);
- Uint32 dataLen = regAttrinbufptr.p->attrbuf[ZINBUF_DATA_LEN];
- MEMCOPY_NO_WORDS(&out[sz],
- &regAttrinbufptr.p->attrbuf[0],
- dataLen);
- sz += dataLen;
- regAttrinbufptr.i = regAttrinbufptr.p->attrbuf[ZINBUF_NEXT];
- ptrCheckGuard(regAttrinbufptr, cattrinbufFileSize, attrbuf);
- }
- ndbrequire(sz == boundAiLength);
+ if(boundAiLength > 0)
+ sendKeyinfoAcc(signal, TuxBoundInfo::SignalLength);
EXECUTE_DIRECT(DBTUX, GSN_TUX_BOUND_INFO,
- signal, TuxBoundInfo::SignalLength + boundAiLength);
+ signal, TuxBoundInfo::SignalLength + boundAiLength);
jamEntry();
if (req->errorCode != 0) {
jam();
@@ -7716,12 +7724,14 @@ void Dblqh::accScanConfScanLab(Signal* signal)
signal->theData[1] = tcConnectptr.p->tableref;
signal->theData[2] = scanptr.p->scanSchemaVersion;
signal->theData[3] = ZSTORED_PROC_SCAN;
- ndbrequire(boundAiLength <= scanptr.p->scanAiLength);
- signal->theData[4] = scanptr.p->scanAiLength - boundAiLength;
+
+ signal->theData[4] = scanptr.p->scanAiLength;
sendSignal(tcConnectptr.p->tcTupBlockref,
GSN_STORED_PROCREQ, signal, 5, JBB);
signal->theData[0] = tcConnectptr.p->tupConnectrec;
+ AttrbufPtr regAttrinbufptr;
+ regAttrinbufptr.i = tcConnectptr.p->firstAttrinbuf;
while (regAttrinbufptr.i != RNIL) {
ptrCheckGuard(regAttrinbufptr, cattrinbufFileSize, attrbuf);
jam();
@@ -14797,7 +14807,7 @@ void Dblqh::execDEBUG_SIG(Signal* signal)
tdebug = logPagePtr.p->logPageWord[0];
char buf[100];
- snprintf(buf, 100,
+ BaseString::snprintf(buf, 100,
"Error while reading REDO log.\n"
"D=%d, F=%d Mb=%d FP=%d W1=%d W2=%d",
signal->theData[2], signal->theData[3], signal->theData[4],
diff --git a/ndb/src/kernel/blocks/dbtc/Dbtc.hpp b/ndb/src/kernel/blocks/dbtc/Dbtc.hpp
index a5f07f8e9e1..a209df24c44 100644
--- a/ndb/src/kernel/blocks/dbtc/Dbtc.hpp
+++ b/ndb/src/kernel/blocks/dbtc/Dbtc.hpp
@@ -192,7 +192,8 @@ public:
OS_WAIT_ATTR = 14,
OS_WAIT_COMMIT_CONF = 15,
OS_WAIT_ABORT_CONF = 16,
- OS_WAIT_COMPLETE_CONF = 17
+ OS_WAIT_COMPLETE_CONF = 17,
+ OS_WAIT_SCAN = 18
};
enum AbortState {
@@ -1169,6 +1170,8 @@ public:
// Length of expected attribute information
Uint32 scanAiLength;
+ Uint32 scanKeyLen;
+
// Reference to ApiConnectRecord
Uint32 scanApiRec;
@@ -1194,18 +1197,7 @@ public:
Uint16 first_batch_size;
Uint32 batch_byte_size;
- // Shall the locks be held until the application have read the
- // records
- Uint8 scanLockHold;
-
- // Shall the locks be read or write locks
- Uint8 scanLockMode;
-
- // Skip locks by other transactions and read latest committed
- Uint8 readCommitted;
-
- // Scan is on ordered index
- Uint8 rangeScan;
+ Uint32 scanRequestInfo; // ScanFrag format
// Close is ordered
bool m_close_scan_req;
@@ -1467,7 +1459,7 @@ private:
void releaseAttrinfo();
void releaseGcp(Signal* signal);
void releaseKeys();
- void releaseSimpleRead(Signal* signal);
+ void releaseSimpleRead(Signal*, ApiConnectRecordPtr, TcConnectRecord*);
void releaseDirtyWrite(Signal* signal);
void releaseTcCon();
void releaseTcConnectFail(Signal* signal);
@@ -1571,7 +1563,7 @@ private:
void diFcountReqLab(Signal* signal, ScanRecordPtr);
void signalErrorRefuseLab(Signal* signal);
void abort080Lab(Signal* signal);
- void packKeyData000Lab(Signal* signal, BlockReference TBRef);
+ void packKeyData000Lab(Signal* signal, BlockReference TBRef, Uint32 len);
void abortScanLab(Signal* signal, ScanRecordPtr, Uint32 errCode);
void sendAbortedAfterTimeout(Signal* signal, int Tcheck);
void abort010Lab(Signal* signal);
diff --git a/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp b/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp
index d270c6acc61..d8b3ee10532 100644
--- a/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp
+++ b/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp
@@ -274,6 +274,12 @@ void Dbtc::execCONTINUEB(Signal* signal)
transPtr.p->triggerPending = false;
executeTriggers(signal, &transPtr);
return;
+ case TcContinueB::DelayTCKEYCONF:
+ jam();
+ apiConnectptr.i = Tdata0;
+ ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
+ sendtckeyconf(signal, Tdata1);
+ return;
default:
ndbrequire(false);
}//switch
@@ -1759,6 +1765,7 @@ void Dbtc::execKEYINFO(Signal* signal)
switch (apiConnectptr.p->apiConnectstate) {
case CS_RECEIVING:
case CS_REC_COMMITTING:
+ case CS_START_SCAN:
jam();
/*empty*/;
break;
@@ -1812,12 +1819,54 @@ void Dbtc::execKEYINFO(Signal* signal)
jam();
tckeyreq020Lab(signal);
return;
+ case OS_WAIT_SCAN:
+ break;
default:
jam();
terrorCode = ZSTATE_ERROR;
abortErrorLab(signal);
return;
}//switch
+
+ UintR TdataPos = 0;
+ UintR TkeyLen = regCachePtr->keylen;
+ UintR Tlen = regCachePtr->save1;
+
+ do {
+ if (cfirstfreeDatabuf == RNIL) {
+ jam();
+ abort();
+ seizeDatabuferrorLab(signal);
+ return;
+ }//if
+ linkKeybuf(signal);
+ arrGuard(TdataPos, 19);
+ databufptr.p->data[0] = signal->theData[TdataPos + 3];
+ databufptr.p->data[1] = signal->theData[TdataPos + 4];
+ databufptr.p->data[2] = signal->theData[TdataPos + 5];
+ databufptr.p->data[3] = signal->theData[TdataPos + 6];
+ Tlen = Tlen + 4;
+ TdataPos = TdataPos + 4;
+ if (Tlen < TkeyLen) {
+ jam();
+ if (TdataPos >= tmaxData) {
+ jam();
+ /*----------------------------------------------------*/
+ /** EXIT AND WAIT FOR SIGNAL KEYINFO OR KEYINFO9 **/
+ /** WHEN EITHER OF THE SIGNALS IS RECEIVED A JUMP **/
+ /** TO LABEL "KEYINFO_LABEL" IS DONE. THEN THE **/
+ /** PROGRAM RETURNS TO LABEL TCKEYREQ020 **/
+ /*----------------------------------------------------*/
+ setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
+ regCachePtr->save1 = Tlen;
+ return;
+ }//if
+ } else {
+ jam();
+ return;
+ }//if
+ } while (1);
+ return;
}//Dbtc::execKEYINFO()
/*---------------------------------------------------------------------------*/
@@ -1826,45 +1875,45 @@ void Dbtc::execKEYINFO(Signal* signal)
/* WE WILL ALWAYS PACK 4 WORDS AT A TIME. */
/*---------------------------------------------------------------------------*/
void Dbtc::packKeyData000Lab(Signal* signal,
- BlockReference TBRef)
+ BlockReference TBRef,
+ Uint32 totalLen)
{
CacheRecord * const regCachePtr = cachePtr.p;
UintR Tmp;
- Uint16 tdataPos;
jam();
- tdataPos = 0;
- Tmp = regCachePtr->keylen;
+ Uint32 len = 0;
databufptr.i = regCachePtr->firstKeybuf;
+ signal->theData[0] = tcConnectptr.i;
+ signal->theData[1] = apiConnectptr.p->transid[0];
+ signal->theData[2] = apiConnectptr.p->transid[1];
+ Uint32 * dst = signal->theData+3;
+ ptrCheckGuard(databufptr, cdatabufFilesize, databufRecord);
+
do {
jam();
- if (tdataPos == 20) {
- jam();
- /*---------------------------------------------------------------------*/
- /* 4 MORE WORDS WILL NOT FIT IN THE 24 DATA WORDS IN A SIGNAL */
- /*---------------------------------------------------------------------*/
- sendKeyinfo(signal, TBRef, 20);
- tdataPos = 0;
- }//if
- Tmp = Tmp - 4;
- ptrCheckGuard(databufptr, cdatabufFilesize, databufRecord);
- cdata[tdataPos ] = databufptr.p->data[0];
- cdata[tdataPos + 1] = databufptr.p->data[1];
- cdata[tdataPos + 2] = databufptr.p->data[2];
- cdata[tdataPos + 3] = databufptr.p->data[3];
- tdataPos = tdataPos + 4;
- if (Tmp <= 4) {
+ databufptr.i = databufptr.p->nextDatabuf;
+ dst[len + 0] = databufptr.p->data[0];
+ dst[len + 1] = databufptr.p->data[1];
+ dst[len + 2] = databufptr.p->data[2];
+ dst[len + 3] = databufptr.p->data[3];
+ len += 4;
+ if (totalLen <= 4) {
jam();
/*---------------------------------------------------------------------*/
/* LAST PACK OF KEY DATA HAVE BEEN SENT */
/*---------------------------------------------------------------------*/
/* THERE WERE UNSENT INFORMATION, SEND IT. */
/*---------------------------------------------------------------------*/
- sendKeyinfo(signal, TBRef, tdataPos);
- releaseKeys();
+ sendSignal(TBRef, GSN_KEYINFO, signal, 3 + len, JBB);
return;
- }//if
- databufptr.i = databufptr.p->nextDatabuf;
+ } else if(len == KeyInfo::DataLength){
+ jam();
+ len = 0;
+ sendSignal(TBRef, GSN_KEYINFO, signal, 3 + KeyInfo::DataLength, JBB);
+ }
+ totalLen -= 4;
+ ptrCheckGuard(databufptr, cdatabufFilesize, databufRecord);
} while (1);
}//Dbtc::packKeyData000Lab()
@@ -2247,6 +2296,7 @@ void Dbtc::initApiConnectRec(Signal* signal,
regApiPtr->m_exec_flag = 0;
regApiPtr->returncode = 0;
regApiPtr->returnsignal = RS_TCKEYCONF;
+ ndbassert(regApiPtr->firstTcConnect == RNIL);
regApiPtr->firstTcConnect = RNIL;
regApiPtr->lastTcConnect = RNIL;
regApiPtr->globalcheckpointid = 0;
@@ -2441,18 +2491,30 @@ void Dbtc::execTCKEYREQ(Signal* signal)
}
break;
case CS_STARTED:
- //------------------------------------------------------------------------
- // Transaction is started already. Check that the operation is on the same
- // transaction.
- //------------------------------------------------------------------------
- compare_transid1 = regApiPtr->transid[0] ^ tcKeyReq->transId1;
- compare_transid2 = regApiPtr->transid[1] ^ tcKeyReq->transId2;
- jam();
- compare_transid1 = compare_transid1 | compare_transid2;
- if (compare_transid1 != 0) {
- TCKEY_abort(signal, 1);
- return;
- }//if
+ if(TstartFlag == 1 && regApiPtr->firstTcConnect == RNIL)
+ {
+ /**
+ * If last operation in last transaction was a simple/dirty read
+ * it does not have to be committed or rollbacked hence,
+ * the state will be CS_STARTED
+ */
+ jam();
+ initApiConnectRec(signal, regApiPtr);
+ regApiPtr->m_exec_flag = TexecFlag;
+ } else {
+ //----------------------------------------------------------------------
+ // Transaction is started already.
+ // Check that the operation is on the same transaction.
+ //-----------------------------------------------------------------------
+ compare_transid1 = regApiPtr->transid[0] ^ tcKeyReq->transId1;
+ compare_transid2 = regApiPtr->transid[1] ^ tcKeyReq->transId2;
+ jam();
+ compare_transid1 = compare_transid1 | compare_transid2;
+ if (compare_transid1 != 0) {
+ TCKEY_abort(signal, 1);
+ return;
+ }//if
+ }
break;
case CS_ABORTING:
if (regApiPtr->abortState == AS_IDLE) {
@@ -2601,7 +2663,7 @@ void Dbtc::execTCKEYREQ(Signal* signal)
regCachePtr->schemaVersion = TtableSchemaVersion;
regTcPtr->operation = TOperationType;
- // Uint8 TSimpleFlag = tcKeyReq->getSimpleFlag(Treqinfo);
+ Uint8 TSimpleFlag = tcKeyReq->getSimpleFlag(Treqinfo);
Uint8 TDirtyFlag = tcKeyReq->getDirtyFlag(Treqinfo);
Uint8 TInterpretedFlag = tcKeyReq->getInterpretedFlag(Treqinfo);
Uint8 TDistrGroupFlag = tcKeyReq->getDistributionGroupFlag(Treqinfo);
@@ -2609,11 +2671,9 @@ void Dbtc::execTCKEYREQ(Signal* signal)
Uint8 TDistrKeyFlag = tcKeyReq->getDistributionKeyFlag(Treqinfo);
Uint8 TexecuteFlag = TexecFlag;
- //RONM_TEST Disable simple reads temporarily
- regCachePtr->opSimple = 0;
- // regCachePtr->opSimple = TSimpleFlag;
- regTcPtr->dirtyOp = TDirtyFlag;
+ regCachePtr->opSimple = TSimpleFlag;
regCachePtr->opExec = TInterpretedFlag;
+ regTcPtr->dirtyOp = TDirtyFlag;
regCachePtr->distributionGroupIndicator = TDistrGroupFlag;
regCachePtr->distributionGroupType = TDistrGroupTypeFlag;
@@ -2714,7 +2774,6 @@ void Dbtc::execTCKEYREQ(Signal* signal)
}
}
- UintR Tattrlength = regCachePtr->attrlength;
UintR TwriteCount = c_counters.cwriteCount;
UintR Toperationsize = coperationsize;
/* --------------------------------------------------------------------
@@ -2723,13 +2782,13 @@ void Dbtc::execTCKEYREQ(Signal* signal)
* TEMP TABLES DON'T PARTICIPATE.
* -------------------------------------------------------------------- */
if (localTabptr.p->storedTable) {
- coperationsize = ((Toperationsize + Tattrlength) + TkeyLength) + 17;
+ coperationsize = ((Toperationsize + TattrLen) + TkeyLength) + 17;
}
c_counters.cwriteCount = TwriteCount + 1;
switch (TOperationType) {
case ZUPDATE:
jam();
- if (Tattrlength == 0) {
+ if (TattrLen == 0) {
//TCKEY_abort(signal, 5);
//return;
}//if
@@ -2775,7 +2834,6 @@ void Dbtc::execTCKEYREQ(Signal* signal)
if (regApiPtr->apiConnectstate == CS_START_COMMITTING) {
jam();
// Trigger execution at commit
-
regApiPtr->apiConnectstate = CS_REC_COMMITTING;
} else {
jam();
@@ -2895,12 +2953,13 @@ void Dbtc::tckeyreq050Lab(Signal* signal)
regTcPtr->tcNodedata[3] = Tdata6;
Uint8 Toperation = regTcPtr->operation;
+ Uint8 Tdirty = regTcPtr->dirtyOp;
tnoOfBackup = tnodeinfo & 3;
tnoOfStandby = (tnodeinfo >> 8) & 3;
regCachePtr->distributionKey = (tnodeinfo >> 16) & 255;
if (Toperation == ZREAD) {
- if (regCachePtr->opSimple == 1) {
+ if (Tdirty == 1) {
jam();
/*-------------------------------------------------------------*/
/* A SIMPLE READ CAN SELECT ANY OF THE PRIMARY AND */
@@ -2910,23 +2969,28 @@ void Dbtc::tckeyreq050Lab(Signal* signal)
/*-------------------------------------------------------------*/
arrGuard(tnoOfBackup, 4);
UintR Tindex;
+ UintR TownNode = cownNodeid;
for (Tindex = 1; Tindex <= tnoOfBackup; Tindex++) {
UintR Tnode = regTcPtr->tcNodedata[Tindex];
- UintR TownNode = cownNodeid;
jam();
if (Tnode == TownNode) {
jam();
regTcPtr->tcNodedata[0] = Tnode;
}//if
}//for
- if (regCachePtr->attrlength == 0) {
- /*-------------------------------------------------------------*/
- // A simple read which does not read anything is a strange
- // creature and we abort rather than continue.
- /*-------------------------------------------------------------*/
- TCKEY_abort(signal, 12);
- return;
- }//if
+ if(ERROR_INSERTED(8048) || ERROR_INSERTED(8049))
+ {
+ for (Tindex = 0; Tindex <= tnoOfBackup; Tindex++)
+ {
+ UintR Tnode = regTcPtr->tcNodedata[Tindex];
+ jam();
+ if (Tnode != TownNode) {
+ jam();
+ regTcPtr->tcNodedata[0] = Tnode;
+ ndbout_c("Choosing %d", Tnode);
+ }//if
+ }//for
+ }
}//if
jam();
regTcPtr->lastReplicaNo = 0;
@@ -3014,7 +3078,8 @@ void Dbtc::packLqhkeyreq(Signal* signal,
UintR TfirstAttrbuf = regCachePtr->firstAttrbuf;
sendlqhkeyreq(signal, TBRef);
if (Tkeylen > 4) {
- packKeyData000Lab(signal, TBRef);
+ packKeyData000Lab(signal, TBRef, Tkeylen - 4);
+ releaseKeys();
}//if
packLqhkeyreq040Lab(signal,
TfirstAttrbuf,
@@ -3235,7 +3300,7 @@ void Dbtc::packLqhkeyreq040Lab(Signal* signal,
releaseAttrinfo();
if (Tboth) {
jam();
- releaseSimpleRead(signal);
+ releaseSimpleRead(signal, apiConnectptr, tcConnectptr.p);
return;
}//if
regTcPtr->tcConnectstate = OS_OPERATING;
@@ -3297,8 +3362,21 @@ void Dbtc::releaseAttrinfo()
/* ========================================================================= */
/* ------- RELEASE ALL RECORDS CONNECTED TO A SIMPLE OPERATION ------- */
/* ========================================================================= */
-void Dbtc::releaseSimpleRead(Signal* signal)
-{
+void Dbtc::releaseSimpleRead(Signal* signal,
+ ApiConnectRecordPtr regApiPtr,
+ TcConnectRecord* regTcPtr)
+{
+ Uint32 Ttckeyrec = regApiPtr.p->tckeyrec;
+ Uint32 TclientData = regTcPtr->clientData;
+ Uint32 Tnode = regTcPtr->tcNodedata[0];
+ Uint32 Tlqhkeyreqrec = regApiPtr.p->lqhkeyreqrec;
+ Uint32 TsimpleReadCount = c_counters.csimpleReadCount;
+ ConnectionState state = regApiPtr.p->apiConnectstate;
+
+ regApiPtr.p->tcSendArray[Ttckeyrec] = TclientData;
+ regApiPtr.p->tcSendArray[Ttckeyrec + 1] = TcKeyConf::SimpleReadBit | Tnode;
+ regApiPtr.p->tckeyrec = Ttckeyrec + 2;
+
unlinkReadyTcCon(signal);
releaseTcCon();
@@ -3306,31 +3384,27 @@ void Dbtc::releaseSimpleRead(Signal* signal)
* No LQHKEYCONF in Simple/Dirty read
* Therefore decrese no LQHKEYCONF(REF) we are waiting for
*/
- ApiConnectRecord * const regApiPtr = apiConnectptr.p;
- UintR TsimpleReadCount = c_counters.csimpleReadCount;
- UintR Tlqhkeyreqrec = regApiPtr->lqhkeyreqrec;
-
c_counters.csimpleReadCount = TsimpleReadCount + 1;
- regApiPtr->lqhkeyreqrec = Tlqhkeyreqrec - 1;
-
- /**
- * If start committing and no operation in lists
- * simply return
- */
- if (regApiPtr->apiConnectstate == CS_START_COMMITTING &&
- regApiPtr->firstTcConnect == RNIL) {
+ regApiPtr.p->lqhkeyreqrec = --Tlqhkeyreqrec;
+
+ if(Tlqhkeyreqrec == 0)
+ {
+ /**
+ * Special case of lqhKeyConf_checkTransactionState:
+ * - commit with zero operations: handle only for simple read
+ */
+ sendtckeyconf(signal, state == CS_START_COMMITTING);
+ regApiPtr.p->apiConnectstate =
+ (state == CS_START_COMMITTING ? CS_CONNECTED : state);
+ setApiConTimer(regApiPtr.i, 0, __LINE__);
- jam();
- setApiConTimer(apiConnectptr.i, 0, __LINE__);
- regApiPtr->apiConnectstate = CS_CONNECTED;
return;
- }//if
-
+ }
+
/**
- * Else Emulate LQHKEYCONF
+ * Emulate LQHKEYCONF
*/
- lqhKeyConf_checkTransactionState(signal, regApiPtr);
-
+ lqhKeyConf_checkTransactionState(signal, regApiPtr.p);
}//Dbtc::releaseSimpleRead()
/* ------------------------------------------------------------------------- */
@@ -3766,6 +3840,15 @@ Dbtc::lqhKeyConf_checkTransactionState(Signal * signal,
void Dbtc::sendtckeyconf(Signal* signal, UintR TcommitFlag)
{
+ if(ERROR_INSERTED(8049)){
+ CLEAR_ERROR_INSERT_VALUE;
+ signal->theData[0] = TcContinueB::DelayTCKEYCONF;
+ signal->theData[1] = apiConnectptr.i;
+ signal->theData[2] = TcommitFlag;
+ sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 3000, 3);
+ return;
+ }
+
HostRecordPtr localHostptr;
ApiConnectRecord * const regApiPtr = apiConnectptr.p;
const UintR TopWords = (UintR)regApiPtr->tckeyrec;
@@ -5024,27 +5107,15 @@ void Dbtc::execLQHKEYREF(Signal* signal)
*---------------------------------------------------------------------*/
regApiPtr->lqhkeyreqrec--;
if (regApiPtr->lqhkeyconfrec == regApiPtr->lqhkeyreqrec) {
- if ((regApiPtr->lqhkeyconfrec == 0) &&
- (regApiPtr->apiConnectstate == CS_START_COMMITTING)) {
-
- if(abort == TcKeyReq::IgnoreError){
+ if (regApiPtr->apiConnectstate == CS_START_COMMITTING) {
+ if(regApiPtr->lqhkeyconfrec) {
jam();
- regApiPtr->returnsignal = RS_NO_RETURN;
- abort010Lab(signal);
- return;
+ diverify010Lab(signal);
+ } else {
+ jam();
+ sendtckeyconf(signal, 1);
+ regApiPtr->apiConnectstate = CS_CONNECTED;
}
-
- /*----------------------------------------------------------------
- * Not a single operation was successful.
- * This we report as an aborted transaction
- * to avoid performing a commit of zero operations.
- *----------------------------------------------------------------*/
- TCKEY_abort(signal, 54);
- return;
- }//if
- if (regApiPtr->apiConnectstate == CS_START_COMMITTING) {
- jam();
- diverify010Lab(signal);
return;
} else if (regApiPtr->tckeyrec > 0 || regApiPtr->m_exec_flag) {
jam();
@@ -6045,6 +6116,7 @@ void Dbtc::timeOutFoundLab(Signal* signal, Uint32 TapiConPtr)
<< " - place: " << c_apiConTimer_line[apiConnectptr.i]);
switch (apiConnectptr.p->apiConnectstate) {
case CS_STARTED:
+ ndbrequire(c_apiConTimer_line[apiConnectptr.i] != 3615);
if(apiConnectptr.p->lqhkeyreqrec == apiConnectptr.p->lqhkeyconfrec){
jam();
/*
@@ -6297,8 +6369,8 @@ void Dbtc::sendAbortedAfterTimeout(Signal* signal, int Tcheck)
snprintf(buf, sizeof(buf), "TC %d: %d ops:",
__LINE__, apiConnectptr.i);
for(Uint32 i = 0; i<TloopCount; i++){
- snprintf(buf2, sizeof(buf2), "%s %d", buf, tmp[i]);
- snprintf(buf, sizeof(buf), buf2);
+ BaseString::snprintf(buf2, sizeof(buf2), "%s %d", buf, tmp[i]);
+ BaseString::snprintf(buf, sizeof(buf), buf2);
}
warningEvent(buf);
ndbout_c(buf);
@@ -8406,7 +8478,8 @@ void Dbtc::execSCAN_TABREQ(Signal* signal)
{
const ScanTabReq * const scanTabReq = (ScanTabReq *)&signal->theData[0];
const Uint32 reqinfo = scanTabReq->requestInfo;
- const Uint32 aiLength = scanTabReq->attrLen;
+ const Uint32 aiLength = (scanTabReq->attrLenKeyLen & 0xFFFF);
+ const Uint32 keyLen = scanTabReq->attrLenKeyLen >> 16;
const Uint32 schemaVersion = scanTabReq->tableSchemaVersion;
const Uint32 transid1 = scanTabReq->transId1;
const Uint32 transid2 = scanTabReq->transId2;
@@ -8444,6 +8517,10 @@ void Dbtc::execSCAN_TABREQ(Signal* signal)
if (transP->apiConnectstate == CS_ABORTING &&
transP->abortState == AS_IDLE) {
jam();
+ } else if(transP->apiConnectstate == CS_STARTED &&
+ transP->firstTcConnect == RNIL){
+ jam();
+ // left over from simple/dirty read
} else {
jam();
errCode = ZSTATE_ERROR;
@@ -8480,8 +8557,12 @@ void Dbtc::execSCAN_TABREQ(Signal* signal)
seizeTcConnect(signal);
tcConnectptr.p->apiConnect = apiConnectptr.i;
+ tcConnectptr.p->tcConnectstate = OS_WAIT_SCAN;
+ apiConnectptr.p->lastTcConnect = tcConnectptr.i;
seizeCacheRecord(signal);
+ cachePtr.p->keylen = keyLen;
+ cachePtr.p->save1 = 0;
scanptr = seizeScanrec(signal);
ndbrequire(transP->apiScanRec == RNIL);
@@ -8558,21 +8639,27 @@ void Dbtc::initScanrec(ScanRecordPtr scanptr,
UintR scanParallel,
UintR noOprecPerFrag)
{
- const UintR reqinfo = scanTabReq->requestInfo;
-
scanptr.p->scanTcrec = tcConnectptr.i;
scanptr.p->scanApiRec = apiConnectptr.i;
- scanptr.p->scanAiLength = scanTabReq->attrLen;
+ scanptr.p->scanAiLength = scanTabReq->attrLenKeyLen & 0xFFFF;
+ scanptr.p->scanKeyLen = scanTabReq->attrLenKeyLen >> 16;
scanptr.p->scanTableref = tabptr.i;
scanptr.p->scanSchemaVersion = scanTabReq->tableSchemaVersion;
scanptr.p->scanParallel = scanParallel;
scanptr.p->noOprecPerFrag = noOprecPerFrag;
scanptr.p->first_batch_size= scanTabReq->first_batch_size;
scanptr.p->batch_byte_size= scanTabReq->batch_byte_size;
- scanptr.p->scanLockMode = ScanTabReq::getLockMode(reqinfo);
- scanptr.p->scanLockHold = ScanTabReq::getHoldLockFlag(reqinfo);
- scanptr.p->readCommitted = ScanTabReq::getReadCommittedFlag(reqinfo);
- scanptr.p->rangeScan = ScanTabReq::getRangeScanFlag(reqinfo);
+
+ Uint32 tmp = 0;
+ const UintR ri = scanTabReq->requestInfo;
+ ScanFragReq::setLockMode(tmp, ScanTabReq::getLockMode(ri));
+ ScanFragReq::setHoldLockFlag(tmp, ScanTabReq::getHoldLockFlag(ri));
+ ScanFragReq::setKeyinfoFlag(tmp, ScanTabReq::getKeyinfoFlag(ri));
+ ScanFragReq::setReadCommittedFlag(tmp,ScanTabReq::getReadCommittedFlag(ri));
+ ScanFragReq::setRangeScanFlag(tmp, ScanTabReq::getRangeScanFlag(ri));
+ ScanFragReq::setAttrLen(tmp, scanTabReq->attrLenKeyLen & 0xFFFF);
+
+ scanptr.p->scanRequestInfo = tmp;
scanptr.p->scanStoredProcId = scanTabReq->storedProcId;
scanptr.p->scanState = ScanRecord::RUNNING;
scanptr.p->m_queued_count = 0;
@@ -8589,7 +8676,7 @@ void Dbtc::initScanrec(ScanRecordPtr scanptr,
ptr.p->m_apiPtr = cdata[i];
}//for
- (* (scanptr.p->rangeScan ?
+ (* (ScanTabReq::getRangeScanFlag(ri) ?
&c_counters.c_range_scan_count :
&c_counters.c_scan_count))++;
}//Dbtc::initScanrec()
@@ -8807,6 +8894,7 @@ void Dbtc::releaseScanResources(ScanRecordPtr scanPtr)
if (apiConnectptr.p->cachePtr != RNIL) {
cachePtr.i = apiConnectptr.p->cachePtr;
ptrCheckGuard(cachePtr, ccacheFilesize, cacheRecord);
+ releaseKeys();
releaseAttrinfo();
}//if
tcConnectptr.i = scanPtr.p->scanTcrec;
@@ -9448,17 +9536,8 @@ void Dbtc::sendScanFragReq(Signal* signal,
ScanRecord* scanP,
ScanFragRec* scanFragP)
{
- Uint32 requestInfo = 0;
ScanFragReq * const req = (ScanFragReq *)&signal->theData[0];
- ScanFragReq::setLockMode(requestInfo, scanP->scanLockMode);
- ScanFragReq::setHoldLockFlag(requestInfo, scanP->scanLockHold);
- if(scanP->scanLockMode == 1){ // Not read -> keyinfo
- jam();
- ScanFragReq::setKeyinfoFlag(requestInfo, 1);
- }
- ScanFragReq::setReadCommittedFlag(requestInfo, scanP->readCommitted);
- ScanFragReq::setRangeScanFlag(requestInfo, scanP->rangeScan);
- ScanFragReq::setAttrLen(requestInfo, scanP->scanAiLength);
+ Uint32 requestInfo = scanP->scanRequestInfo;
ScanFragReq::setScanPrio(requestInfo, 1);
apiConnectptr.i = scanP->scanApiRec;
req->tableId = scanP->scanTableref;
@@ -9466,7 +9545,7 @@ void Dbtc::sendScanFragReq(Signal* signal,
ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
req->senderData = scanFragptr.i;
req->requestInfo = requestInfo;
- req->fragmentNo = scanFragP->scanFragId;
+ req->fragmentNoKeyLen = scanFragP->scanFragId | (scanP->scanKeyLen << 16);
req->resultRef = apiConnectptr.p->ndbapiBlockref;
req->savePointId = apiConnectptr.p->currSavePointId;
req->transId1 = apiConnectptr.p->transid[0];
@@ -9476,6 +9555,11 @@ void Dbtc::sendScanFragReq(Signal* signal,
req->batch_size_bytes= scanP->batch_byte_size;
sendSignal(scanFragP->lqhBlockref, GSN_SCAN_FRAGREQ, signal,
ScanFragReq::SignalLength, JBB);
+ if(scanP->scanKeyLen > 0)
+ {
+ tcConnectptr.i = scanFragptr.i;
+ packKeyData000Lab(signal, scanFragP->lqhBlockref, scanP->scanKeyLen);
+ }
updateBuddyTimer(apiConnectptr);
scanFragP->startFragTimer(ctcTimer);
}//Dbtc::sendScanFragReq()
@@ -9586,6 +9670,7 @@ void Dbtc::initApiConnect(Signal* signal)
apiConnectptr.p->ndbapiBlockref = 0xFFFFFFFF; // Invalid ref
apiConnectptr.p->commitAckMarker = RNIL;
apiConnectptr.p->firstTcConnect = RNIL;
+ apiConnectptr.p->lastTcConnect = RNIL;
apiConnectptr.p->triggerPending = false;
apiConnectptr.p->isIndexOp = false;
apiConnectptr.p->accumulatingIndexOp = RNIL;
@@ -9612,6 +9697,7 @@ void Dbtc::initApiConnect(Signal* signal)
apiConnectptr.p->ndbapiBlockref = 0xFFFFFFFF; // Invalid ref
apiConnectptr.p->commitAckMarker = RNIL;
apiConnectptr.p->firstTcConnect = RNIL;
+ apiConnectptr.p->lastTcConnect = RNIL;
apiConnectptr.p->triggerPending = false;
apiConnectptr.p->isIndexOp = false;
apiConnectptr.p->accumulatingIndexOp = RNIL;
@@ -9638,6 +9724,7 @@ void Dbtc::initApiConnect(Signal* signal)
apiConnectptr.p->ndbapiBlockref = 0xFFFFFFFF; // Invalid ref
apiConnectptr.p->commitAckMarker = RNIL;
apiConnectptr.p->firstTcConnect = RNIL;
+ apiConnectptr.p->lastTcConnect = RNIL;
apiConnectptr.p->triggerPending = false;
apiConnectptr.p->isIndexOp = false;
apiConnectptr.p->accumulatingIndexOp = RNIL;
@@ -10422,9 +10509,6 @@ Dbtc::execDUMP_STATE_ORD(Signal* signal)
sp.p->scanSchemaVersion,
sp.p->scanTableref,
sp.p->scanStoredProcId);
- infoEvent(" lhold=%d, lmode=%d",
- sp.p->scanLockHold,
- sp.p->scanLockMode);
infoEvent(" apiRec=%d, next=%d",
sp.p->scanApiRec, sp.p->nextScan);
@@ -10995,9 +11079,11 @@ void Dbtc::execTCINDXREQ(Signal* signal)
// Seize index operation
TcIndexOperationPtr indexOpPtr;
if ((startFlag == 1) &&
- ((regApiPtr->apiConnectstate == CS_CONNECTED) ||
- ((regApiPtr->apiConnectstate == CS_ABORTING) &&
- (regApiPtr->abortState == AS_IDLE)))) {
+ (regApiPtr->apiConnectstate == CS_CONNECTED ||
+ (regApiPtr->apiConnectstate == CS_STARTED &&
+ regApiPtr->firstTcConnect == RNIL)) ||
+ (regApiPtr->apiConnectstate == CS_ABORTING &&
+ regApiPtr->abortState == AS_IDLE)) {
jam();
// This is a newly started transaction, clean-up
releaseAllSeizedIndexOperations(regApiPtr);
@@ -11652,7 +11738,7 @@ void Dbtc::readIndexTable(Signal* signal,
tcKeyLength += MIN(keyLength, keyBufSize);
tcKeyReq->tableSchemaVersion = indexOp->tcIndxReq.indexSchemaVersion;
TcKeyReq::setOperationType(tcKeyRequestInfo,
- opType == ZREAD ? opType : ZREAD_EX);
+ opType == ZREAD ? ZREAD : ZREAD_EX);
TcKeyReq::setAIInTcKeyReq(tcKeyRequestInfo, 1); // Allways send one AttrInfo
TcKeyReq::setExecutingTrigger(tcKeyRequestInfo, 0);
BlockReference originalReceiver = regApiPtr->ndbapiBlockref;
@@ -11677,6 +11763,9 @@ void Dbtc::readIndexTable(Signal* signal,
AttributeHeader::init(dataPtr, indexData->primaryKeyPos, 0);
tcKeyLength++;
tcKeyReq->requestInfo = tcKeyRequestInfo;
+
+ ndbassert(TcKeyReq::getDirtyFlag(tcKeyRequestInfo) == 0);
+ ndbassert(TcKeyReq::getSimpleFlag(tcKeyRequestInfo) == 0);
EXECUTE_DIRECT(DBTC, GSN_TCKEYREQ, signal, tcKeyLength);
/**
@@ -11828,6 +11917,9 @@ void Dbtc::executeIndexOperation(Signal* signal,
TcKeyReq::setExecutingTrigger(tcKeyRequestInfo, 0);
tcKeyReq->requestInfo = tcKeyRequestInfo;
+ ndbassert(TcKeyReq::getDirtyFlag(tcKeyRequestInfo) == 0);
+ ndbassert(TcKeyReq::getSimpleFlag(tcKeyRequestInfo) == 0);
+
/**
* Decrease lqhkeyreqrec to compensate for addition
* during read of index table
diff --git a/ndb/src/kernel/blocks/dbtup/Dbtup.hpp b/ndb/src/kernel/blocks/dbtup/Dbtup.hpp
index 0e8dd5fbbe8..55ad1d0910a 100644
--- a/ndb/src/kernel/blocks/dbtup/Dbtup.hpp
+++ b/ndb/src/kernel/blocks/dbtup/Dbtup.hpp
@@ -35,14 +35,6 @@
#define ZMIN_PAGE_LIMIT_TUPKEYREQ 5
#define ZTUP_VERSION_BITS 15
-typedef bool (Dbtup::* ReadFunction)(Uint32*,
- AttributeHeader*,
- Uint32,
- Uint32);
-typedef bool (Dbtup::* UpdateFunction)(Uint32*,
- Uint32,
- Uint32);
-
#ifdef DBTUP_C
//------------------------------------------------------------------
// Jam Handling:
@@ -351,6 +343,14 @@ typedef bool (Dbtup::* UpdateFunction)(Uint32*,
class Dbtup: public SimulatedBlock {
public:
+
+ typedef bool (Dbtup::* ReadFunction)(Uint32*,
+ AttributeHeader*,
+ Uint32,
+ Uint32);
+ typedef bool (Dbtup::* UpdateFunction)(Uint32*,
+ Uint32,
+ Uint32);
// State values
enum State {
NOT_INITIALIZED = 0,
diff --git a/ndb/src/kernel/blocks/dbtup/DbtupDebug.cpp b/ndb/src/kernel/blocks/dbtup/DbtupDebug.cpp
index a50bb2fe52c..808cfd33696 100644
--- a/ndb/src/kernel/blocks/dbtup/DbtupDebug.cpp
+++ b/ndb/src/kernel/blocks/dbtup/DbtupDebug.cpp
@@ -353,11 +353,11 @@ operator<<(NdbOut& out, const Dbtup::Operationrec& op)
out << " [interpretedExec " << dec << op.interpretedExec << "]";
out << " [opSimple " << dec << op.opSimple << "]";
// state
- out << " [tupleState " << dec << op.tupleState << "]";
- out << " [transstate " << dec << op.transstate << "]";
+ out << " [tupleState " << dec << (Uint32) op.tupleState << "]";
+ out << " [transstate " << dec << (Uint32) op.transstate << "]";
out << " [inFragList " << dec << op.inFragList << "]";
out << " [inActiveOpList " << dec << op.inActiveOpList << "]";
- out << " [undoLogged " << dec << op.undoLogged << "]";
+ out << " [undoLogged " << dec << (Uint32) op.undoLogged << "]";
// links
out << " [prevActiveOp " << hex << op.prevActiveOp << "]";
out << " [nextActiveOp " << hex << op.nextActiveOp << "]";
diff --git a/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp b/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp
index 0061ebe812d..49de0d80bcd 100644
--- a/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp
+++ b/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp
@@ -893,19 +893,19 @@ int Dbtup::handleReadReq(Signal* signal,
if (regOperPtr->interpretedExec != 1) {
jam();
-
- Uint32 TnoOfDataRead = readAttributes(pagePtr,
- Ttupheadoffset,
- &cinBuffer[0],
- regOperPtr->attrinbufLen,
- dst,
- dstLen,
- false);
- if (TnoOfDataRead != (Uint32)-1) {
+ int ret = readAttributes(pagePtr,
+ Ttupheadoffset,
+ &cinBuffer[0],
+ regOperPtr->attrinbufLen,
+ dst,
+ dstLen,
+ false);
+ if (ret != -1) {
/* ------------------------------------------------------------------------- */
// We have read all data into coutBuffer. Now send it to the API.
/* ------------------------------------------------------------------------- */
jam();
+ Uint32 TnoOfDataRead= (Uint32) ret;
regOperPtr->attroutbufLen = TnoOfDataRead;
sendReadAttrinfo(signal, TnoOfDataRead, regOperPtr);
return 0;
@@ -1100,7 +1100,7 @@ Dbtup::updateStartLab(Signal* signal,
Tablerec* const regTabPtr,
Page* const pagePtr)
{
- Uint32 retValue;
+ int retValue;
if (regOperPtr->optype == ZINSERT) {
jam();
setNullBits(pagePtr, regTabPtr, regOperPtr->pageOffset);
@@ -1111,7 +1111,7 @@ Dbtup::updateStartLab(Signal* signal,
regOperPtr->pageOffset,
&cinBuffer[0],
regOperPtr->attrinbufLen);
- if (retValue == (Uint32)-1) {
+ if (retValue == -1) {
tupkeyErrorLab(signal);
}//if
} else {
@@ -1215,7 +1215,7 @@ int Dbtup::interpreterStartLab(Signal* signal,
{
Operationrec * const regOperPtr = operPtr.p;
Uint32 RtotalLen;
- Uint32 TnoDataRW;
+ int TnoDataRW;
Uint32 RinitReadLen = cinBuffer[0];
Uint32 RexecRegionLen = cinBuffer[1];
@@ -1273,7 +1273,7 @@ int Dbtup::interpreterStartLab(Signal* signal,
&dst[0],
dstLen,
false);
- if (TnoDataRW != (Uint32)-1) {
+ if (TnoDataRW != -1) {
RattroutCounter = TnoDataRW;
RinstructionCounter += RinitReadLen;
} else {
@@ -1300,7 +1300,7 @@ int Dbtup::interpreterStartLab(Signal* signal,
RsubLen,
&coutBuffer[0],
sizeof(coutBuffer) / 4);
- if (TnoDataRW != (Uint32)-1) {
+ if (TnoDataRW != -1) {
RinstructionCounter += RexecRegionLen;
RlogSize = TnoDataRW;
} else {
@@ -1319,7 +1319,7 @@ int Dbtup::interpreterStartLab(Signal* signal,
TupHeadOffset,
&cinBuffer[RinstructionCounter],
RfinalUpdateLen);
- if (TnoDataRW != (Uint32)-1) {
+ if (TnoDataRW != -1) {
MEMCOPY_NO_WORDS(&clogMemBuffer[RlogSize],
&cinBuffer[RinstructionCounter],
RfinalUpdateLen);
@@ -1347,7 +1347,7 @@ int Dbtup::interpreterStartLab(Signal* signal,
&dst[RattroutCounter],
(dstLen - RattroutCounter),
false);
- if (TnoDataRW != (Uint32)-1) {
+ if (TnoDataRW != -1) {
RattroutCounter += TnoDataRW;
} else {
jam();
@@ -1480,14 +1480,13 @@ int Dbtup::interpreterNextLab(Signal* signal,
/* ---------------------------------------------------------------- */
{
Uint32 theAttrinfo = theInstruction;
- Uint32 TnoDataRW;
- TnoDataRW = readAttributes(pagePtr,
- TupHeadOffset,
- &theAttrinfo,
- (Uint32)1,
- &TregMemBuffer[theRegister],
- (Uint32)3,
- false);
+ int TnoDataRW= readAttributes(pagePtr,
+ TupHeadOffset,
+ &theAttrinfo,
+ (Uint32)1,
+ &TregMemBuffer[theRegister],
+ (Uint32)3,
+ false);
if (TnoDataRW == 2) {
/* ------------------------------------------------------------- */
// Two words read means that we get the instruction plus one 32
@@ -1511,7 +1510,7 @@ int Dbtup::interpreterNextLab(Signal* signal,
TregMemBuffer[theRegister] = 0;
TregMemBuffer[theRegister + 2] = 0;
TregMemBuffer[theRegister + 3] = 0;
- } else if (TnoDataRW == (Uint32)-1) {
+ } else if (TnoDataRW == -1) {
jam();
tupkeyErrorLab(signal);
return -1;
@@ -1564,12 +1563,11 @@ int Dbtup::interpreterNextLab(Signal* signal,
ah.setNULL();
Tlen = 1;
}//if
- Uint32 TnoDataRW;
- TnoDataRW = updateAttributes(pagePtr,
- TupHeadOffset,
- &TdataForUpdate[0],
- Tlen);
- if (TnoDataRW != (Uint32)-1) {
+ int TnoDataRW= updateAttributes(pagePtr,
+ TupHeadOffset,
+ &TdataForUpdate[0],
+ Tlen);
+ if (TnoDataRW != -1) {
/* --------------------------------------------------------- */
// Write the written data also into the log buffer so that it
// will be logged.
diff --git a/ndb/src/kernel/blocks/dbtup/DbtupIndex.cpp b/ndb/src/kernel/blocks/dbtup/DbtupIndex.cpp
index 2dd707ebafc..5a8642c4d2e 100644
--- a/ndb/src/kernel/blocks/dbtup/DbtupIndex.cpp
+++ b/ndb/src/kernel/blocks/dbtup/DbtupIndex.cpp
@@ -166,7 +166,7 @@ Dbtup::tuxReadAttrs(Uint32 fragPtrI, Uint32 pageId, Uint32 pageOffset, Uint32 tu
fragptr = fragptr_old;
operPtr = operPtr_old;
// done
- if (ret == (Uint32)-1) {
+ if (ret == -1) {
ret = terrorCode ? (-(int)terrorCode) : -1;
}
return ret;
@@ -200,13 +200,14 @@ Dbtup::tuxReadPk(Uint32 fragPtrI, Uint32 pageId, Uint32 pageOffset, Uint32* data
operPtr.i = RNIL;
operPtr.p = NULL;
// do it
- int ret = readAttributes(pagePtr.p, pageOffset, attrIds, numAttrs, dataOut, ZNIL, true);
+ int ret = readAttributes(pagePtr.p, pageOffset, attrIds,
+ numAttrs, dataOut, ZNIL, true);
// restore globals
tabptr = tabptr_old;
fragptr = fragptr_old;
operPtr = operPtr_old;
// done
- if (ret != (Uint32)-1) {
+ if (ret != -1) {
// remove headers
Uint32 n = 0;
Uint32 i = 0;
@@ -220,7 +221,7 @@ Dbtup::tuxReadPk(Uint32 fragPtrI, Uint32 pageId, Uint32 pageOffset, Uint32* data
n += 1;
i += 1 + size;
}
- ndbrequire(i == ret);
+ ndbrequire((int)i == ret);
ret -= numAttrs;
} else {
ret = terrorCode ? (-(int)terrorCode) : -1;
diff --git a/ndb/src/kernel/blocks/dbtup/DbtupLCP.cpp b/ndb/src/kernel/blocks/dbtup/DbtupLCP.cpp
index f8f2b9bdbd2..370ef4c4ba5 100644
--- a/ndb/src/kernel/blocks/dbtup/DbtupLCP.cpp
+++ b/ndb/src/kernel/blocks/dbtup/DbtupLCP.cpp
@@ -265,7 +265,8 @@ void Dbtup::lcpSaveCopyListLab(Signal* signal, CheckpointInfoPtr ciPtr)
// We ensure that we have actually allocated the tuple header and
// also found it. Otherwise we will fill the undo log with garbage.
/* ---------------------------------------------------------------- */
- if (regOpPtr.p->optype == ZUPDATE) {
+ if (regOpPtr.p->optype == ZUPDATE ||
+ (regOpPtr.p->optype == ZINSERT && regOpPtr.p->deleteInsertFlag)) {
ljam();
if (regOpPtr.p->realPageIdC != RNIL) {
/* ---------------------------------------------------------------- */
diff --git a/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp b/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp
index a4e7cb47249..e6cc6f68842 100644
--- a/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp
+++ b/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp
@@ -156,12 +156,12 @@ Dbtup::setUpQueryRoutines(Tablerec* const regTabPtr)
// tabptr.p Table record pointer
/* ---------------------------------------------------------------- */
int Dbtup::readAttributes(Page* const pagePtr,
- Uint32 tupHeadOffset,
- const Uint32* inBuffer,
- Uint32 inBufLen,
- Uint32* outBuffer,
- Uint32 maxRead,
- bool xfrmFlag)
+ Uint32 tupHeadOffset,
+ const Uint32* inBuffer,
+ Uint32 inBufLen,
+ Uint32* outBuffer,
+ Uint32 maxRead,
+ bool xfrmFlag)
{
Tablerec* const regTabPtr = tabptr.p;
Uint32 numAttributes = regTabPtr->noOfAttr;
@@ -198,7 +198,7 @@ int Dbtup::readAttributes(Page* const pagePtr,
attributeOffset)) {
continue;
} else {
- return (Uint32)-1;
+ return -1;
}//if
} else if(attributeId & AttributeHeader::PSUEDO){
Uint32 sz = read_psuedo(attributeId,
@@ -207,7 +207,7 @@ int Dbtup::readAttributes(Page* const pagePtr,
tOutBufIndex = tmpAttrBufIndex + 1 + sz;
} else {
terrorCode = ZATTRIBUTE_ID_ERROR;
- return (Uint32)-1;
+ return -1;
}//if
}//while
return tOutBufIndex;
@@ -256,11 +256,11 @@ int Dbtup::readAttributesWithoutHeader(Page* const pagePtr,
attributeOffset)) {
continue;
} else {
- return (Uint32)-1;
+ return -1;
}//if
} else {
terrorCode = ZATTRIBUTE_ID_ERROR;
- return (Uint32)-1;
+ return -1;
}//if
}//while
ndbrequire(attrBufIndex == inBufLen);
@@ -678,12 +678,12 @@ int Dbtup::updateAttributes(Page* const pagePtr,
continue;
} else {
ljam();
- return (Uint32)-1;
+ return -1;
}//if
} else {
ljam();
terrorCode = ZATTRIBUTE_ID_ERROR;
- return (Uint32)-1;
+ return -1;
}//if
}//while
return 0;
diff --git a/ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp b/ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp
index c0b49364ee6..aac5c326cad 100644
--- a/ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp
+++ b/ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp
@@ -652,6 +652,7 @@ void Dbtup::executeTrigger(Signal* signal,
return;
default:
ndbrequire(false);
+ executeDirect= false; // remove warning
}//switch
regOperPtr->noFiredTriggers++;
@@ -746,14 +747,15 @@ bool Dbtup::readTriggerInfo(TupTriggerData* const trigPtr,
//--------------------------------------------------------------------
// Read Primary Key Values
//--------------------------------------------------------------------
- noPrimKey = readAttributes(pagep.p,
- tupheadoffset,
- &tableDescriptor[regTabPtr->readKeyArray].tabDescr,
- regTabPtr->noOfKeyAttr,
- keyBuffer,
- ZATTR_BUFFER_SIZE,
- true);
- ndbrequire(noPrimKey != (Uint32)-1);
+ int ret= readAttributes(pagep.p,
+ tupheadoffset,
+ &tableDescriptor[regTabPtr->readKeyArray].tabDescr,
+ regTabPtr->noOfKeyAttr,
+ keyBuffer,
+ ZATTR_BUFFER_SIZE,
+ true);
+ ndbrequire(ret != -1);
+ noPrimKey= ret;
Uint32 numAttrsToRead;
if ((regOperPtr->optype == ZUPDATE) &&
@@ -788,14 +790,15 @@ bool Dbtup::readTriggerInfo(TupTriggerData* const trigPtr,
if ((regOperPtr->optype != ZDELETE) ||
(trigPtr->sendBeforeValues)) {
ljam();
- noMainWords = readAttributes(pagep.p,
- tupheadoffset,
- &readBuffer[0],
- numAttrsToRead,
- mainBuffer,
- ZATTR_BUFFER_SIZE,
- true);
- ndbrequire(noMainWords != (Uint32)-1);
+ int ret= readAttributes(pagep.p,
+ tupheadoffset,
+ &readBuffer[0],
+ numAttrsToRead,
+ mainBuffer,
+ ZATTR_BUFFER_SIZE,
+ true);
+ ndbrequire(ret != -1);
+ noMainWords= ret;
} else {
ljam();
noMainWords = 0;
@@ -813,15 +816,16 @@ bool Dbtup::readTriggerInfo(TupTriggerData* const trigPtr,
pagep.i = regOperPtr->realPageIdC;
ptrCheckGuard(pagep, cnoOfPage, page);
- noCopyWords = readAttributes(pagep.p,
- tupheadoffset,
- &readBuffer[0],
- numAttrsToRead,
- copyBuffer,
- ZATTR_BUFFER_SIZE,
- true);
+ int ret= readAttributes(pagep.p,
+ tupheadoffset,
+ &readBuffer[0],
+ numAttrsToRead,
+ copyBuffer,
+ ZATTR_BUFFER_SIZE,
+ true);
- ndbrequire(noCopyWords != (Uint32)-1);
+ ndbrequire(ret != -1);
+ noCopyWords = ret;
if ((noMainWords == noCopyWords) &&
(memcmp(mainBuffer, copyBuffer, noMainWords << 2) == 0)) {
//--------------------------------------------------------------------
@@ -1074,6 +1078,7 @@ Dbtup::executeTuxCommitTriggers(Signal* signal,
ndbrequire(tupVersion == regOperPtr->tupVersion);
} else {
ndbrequire(false);
+ tupVersion= 0; // remove warning
}
// fill in constant part
req->tableId = regOperPtr->tableRef;
@@ -1118,6 +1123,7 @@ Dbtup::executeTuxAbortTriggers(Signal* signal,
return;
} else {
ndbrequire(false);
+ tupVersion= 0; // remove warning
}
// fill in constant part
req->tableId = regOperPtr->tableRef;
diff --git a/ndb/src/kernel/blocks/dbtux/Dbtux.hpp b/ndb/src/kernel/blocks/dbtux/Dbtux.hpp
index 8dca52cec04..2b4c86e1394 100644
--- a/ndb/src/kernel/blocks/dbtux/Dbtux.hpp
+++ b/ndb/src/kernel/blocks/dbtux/Dbtux.hpp
@@ -32,7 +32,6 @@
// signal classes
#include <signaldata/DictTabInfo.hpp>
#include <signaldata/TuxContinueB.hpp>
-#include <signaldata/BuildIndx.hpp>
#include <signaldata/TupFrag.hpp>
#include <signaldata/AlterIndx.hpp>
#include <signaldata/DropTab.hpp>
@@ -172,12 +171,21 @@ private:
* Physical tuple address in TUP. Provides fast access to table tuple
* or index node. Valid within the db node and across timeslices.
* Not valid between db nodes or across restarts.
+ *
+ * To avoid wasting an Uint16 the pageid is split in two.
*/
struct TupLoc {
- Uint32 m_pageId; // page i-value
+ private:
+ Uint16 m_pageId1; // page i-value (big-endian)
+ Uint16 m_pageId2;
Uint16 m_pageOffset; // page offset in words
+ public:
TupLoc();
TupLoc(Uint32 pageId, Uint16 pageOffset);
+ Uint32 getPageId() const;
+ void setPageId(Uint32 pageId);
+ Uint32 getPageOffset() const;
+ void setPageOffset(Uint32 pageOffset);
bool operator==(const TupLoc& loc) const;
bool operator!=(const TupLoc& loc) const;
};
@@ -224,20 +232,15 @@ private:
* work entry part 5
*
* There are 3 links to other nodes: left child, right child, parent.
- * These are in TupLoc format but the pageIds and pageOffsets are
- * stored in separate arrays (saves 1 word).
- *
* Occupancy (number of entries) is at least 1 except temporarily when
- * a node is about to be removed. If occupancy is 1, only max entry
- * is present but both min and max prefixes are set.
+ * a node is about to be removed.
*/
struct TreeNode;
friend struct TreeNode;
struct TreeNode {
- Uint32 m_linkPI[3]; // link to 0-left child 1-right child 2-parent
- Uint16 m_linkPO[3]; // page offsets for above real page ids
+ TupLoc m_link[3]; // link to 0-left child 1-right child 2-parent
unsigned m_side : 2; // we are 0-left child 1-right child 2-root
- int m_balance : 2; // balance -1, 0, +1
+ unsigned m_balance : 2; // balance -1, 0, +1 plus 1 for Solaris CC
unsigned pad1 : 4;
Uint8 m_occup; // current number of entries
Uint32 m_nodeScan; // list of scans at this node
@@ -246,8 +249,8 @@ private:
static const unsigned NodeHeadSize = sizeof(TreeNode) >> 2;
/*
- * Tree nodes are not always accessed fully, for cache reasons. There
- * are 3 access sizes.
+ * Tree node "access size" was for an early version with signal
+ * interface to TUP. It is now used only to compute sizes.
*/
enum AccSize {
AccNone = 0,
@@ -280,7 +283,7 @@ private:
* m_occup), and whether the position is at an existing entry or
* before one (if any). Position m_occup points past the node and is
* also represented by position 0 of next node. Includes direction
- * and copy of entry used by scan.
+ * used by scan.
*/
struct TreePos;
friend struct TreePos;
@@ -288,8 +291,7 @@ private:
TupLoc m_loc; // physical node address
Uint16 m_pos; // position 0 to m_occup
Uint8 m_match; // at an existing entry
- Uint8 m_dir; // from link (0-2) or within node (3)
- TreeEnt m_ent; // copy of current entry
+ Uint8 m_dir; // see scanNext()
TreePos();
};
@@ -370,6 +372,10 @@ private:
* a separate lock wait flag. It may be for current entry or it may
* be for an entry we were moved away from. In any case nothing
* happens with current entry before lock wait flag is cleared.
+ *
+ * An unfinished scan is always linked to some tree node, and has
+ * current position and direction (see comments at scanNext). There
+ * is also a copy of latest entry found.
*/
struct ScanOp;
friend struct ScanOp;
@@ -398,8 +404,6 @@ private:
Uint32 m_savePointId;
// lock waited for or obtained and not yet passed to LQH
Uint32 m_accLockOp;
- // locks obtained and passed to LQH but not yet returned by LQH
- Uint32 m_accLockOps[MaxAccLockOps];
Uint8 m_readCommitted; // no locking
Uint8 m_lockMode;
Uint8 m_keyInfo;
@@ -408,13 +412,20 @@ private:
ScanBound* m_bound[2]; // pointers to above 2
Uint16 m_boundCnt[2]; // number of bounds in each
TreePos m_scanPos; // position
- TreeEnt m_lastEnt; // last entry returned
+ TreeEnt m_scanEnt; // latest entry found
Uint32 m_nodeScan; // next scan at node (single-linked)
union {
Uint32 nextPool;
Uint32 nextList;
};
Uint32 prevList;
+ /*
+ * Locks obtained and passed to LQH but not yet returned by LQH.
+ * The max was increased from 16 to 992 (default 64). Record max
+ * ever used in this scan. TODO fix quadratic behaviour
+ */
+ Uint32 m_maxAccLockOps;
+ Uint32 m_accLockOps[MaxAccLockOps];
ScanOp(ScanBoundPool& scanBoundPool);
};
typedef Ptr<ScanOp> ScanOpPtr;
@@ -471,7 +482,7 @@ private:
Uint16 m_numAttrs;
bool m_storeNullKey;
TreeHead m_tree;
- TupLoc m_freeLoc; // one node pre-allocated for insert
+ TupLoc m_freeLoc; // list of free index nodes
DLList<ScanOp> m_scanList; // current scans on this fragment
Uint32 m_tupIndexFragPtrI;
Uint32 m_tupTableFragPtrI[2];
@@ -515,7 +526,6 @@ private:
Frag& m_frag; // fragment using the node
TupLoc m_loc; // physical node address
TreeNode* m_node; // pointer to node storage
- AccSize m_acc; // accessed size
NodeHandle(Frag& frag);
NodeHandle(const NodeHandle& node);
NodeHandle& operator=(const NodeHandle& node);
@@ -576,18 +586,24 @@ private:
* DbtuxNode.cpp
*/
int allocNode(Signal* signal, NodeHandle& node);
- void accessNode(Signal* signal, NodeHandle& node, AccSize acc);
- void selectNode(Signal* signal, NodeHandle& node, TupLoc loc, AccSize acc);
- void insertNode(Signal* signal, NodeHandle& node, AccSize acc);
- void deleteNode(Signal* signal, NodeHandle& node);
- void setNodePref(Signal* signal, NodeHandle& node);
+ void selectNode(NodeHandle& node, TupLoc loc);
+ void insertNode(NodeHandle& node);
+ void deleteNode(NodeHandle& node);
+ void setNodePref(NodeHandle& node);
// node operations
- void nodePushUp(Signal* signal, NodeHandle& node, unsigned pos, const TreeEnt& ent);
- void nodePopDown(Signal* signal, NodeHandle& node, unsigned pos, TreeEnt& ent);
- void nodePushDown(Signal* signal, NodeHandle& node, unsigned pos, TreeEnt& ent);
- void nodePopUp(Signal* signal, NodeHandle& node, unsigned pos, TreeEnt& ent);
- void nodeSlide(Signal* signal, NodeHandle& dstNode, NodeHandle& srcNode, unsigned i);
+ void nodePushUp(NodeHandle& node, unsigned pos, const TreeEnt& ent, Uint32 scanList);
+ void nodePushUpScans(NodeHandle& node, unsigned pos);
+ void nodePopDown(NodeHandle& node, unsigned pos, TreeEnt& en, Uint32* scanList);
+ void nodePopDownScans(NodeHandle& node, unsigned pos);
+ void nodePushDown(NodeHandle& node, unsigned pos, TreeEnt& ent, Uint32& scanList);
+ void nodePushDownScans(NodeHandle& node, unsigned pos);
+ void nodePopUp(NodeHandle& node, unsigned pos, TreeEnt& ent, Uint32 scanList);
+ void nodePopUpScans(NodeHandle& node, unsigned pos);
+ void nodeSlide(NodeHandle& dstNode, NodeHandle& srcNode, unsigned cnt, unsigned i);
// scans linked to node
+ void addScanList(NodeHandle& node, unsigned pos, Uint32 scanList);
+ void removeScanList(NodeHandle& node, unsigned pos, Uint32& scanList);
+ void moveScanList(NodeHandle& node, unsigned pos);
void linkScan(NodeHandle& node, ScanOpPtr scanPtr);
void unlinkScan(NodeHandle& node, ScanOpPtr scanPtr);
bool islinkScan(NodeHandle& node, ScanOpPtr scanPtr);
@@ -595,10 +611,21 @@ private:
/*
* DbtuxTree.cpp
*/
- void treeAdd(Signal* signal, Frag& frag, TreePos treePos, TreeEnt ent);
- void treeRemove(Signal* signal, Frag& frag, TreePos treePos);
- void treeRotateSingle(Signal* signal, Frag& frag, NodeHandle& node, unsigned i);
- void treeRotateDouble(Signal* signal, Frag& frag, NodeHandle& node, unsigned i);
+ // add entry
+ void treeAdd(Frag& frag, TreePos treePos, TreeEnt ent);
+ void treeAddFull(Frag& frag, NodeHandle lubNode, unsigned pos, TreeEnt ent);
+ void treeAddNode(Frag& frag, NodeHandle lubNode, unsigned pos, TreeEnt ent, NodeHandle parentNode, unsigned i);
+ void treeAddRebalance(Frag& frag, NodeHandle node, unsigned i);
+ // remove entry
+ void treeRemove(Frag& frag, TreePos treePos);
+ void treeRemoveInner(Frag& frag, NodeHandle lubNode, unsigned pos);
+ void treeRemoveSemi(Frag& frag, NodeHandle node, unsigned i);
+ void treeRemoveLeaf(Frag& frag, NodeHandle node);
+ void treeRemoveNode(Frag& frag, NodeHandle node);
+ void treeRemoveRebalance(Frag& frag, NodeHandle node, unsigned i);
+ // rotate
+ void treeRotateSingle(Frag& frag, NodeHandle& node, unsigned i);
+ void treeRotateDouble(Frag& frag, NodeHandle& node, unsigned i);
/*
* DbtuxScan.cpp
@@ -610,9 +637,9 @@ private:
void execACCKEYCONF(Signal* signal);
void execACCKEYREF(Signal* signal);
void execACC_ABORTCONF(Signal* signal);
- void scanFirst(Signal* signal, ScanOpPtr scanPtr);
- void scanNext(Signal* signal, ScanOpPtr scanPtr);
- bool scanVisible(Signal* signal, ScanOpPtr scanPtr, TreeEnt ent);
+ void scanFirst(ScanOpPtr scanPtr);
+ void scanNext(ScanOpPtr scanPtr);
+ bool scanVisible(ScanOpPtr scanPtr, TreeEnt ent);
void scanClose(Signal* signal, ScanOpPtr scanPtr);
void addAccLockOp(ScanOp& scan, Uint32 accLockOp);
void removeAccLockOp(ScanOp& scan, Uint32 accLockOp);
@@ -621,9 +648,9 @@ private:
/*
* DbtuxSearch.cpp
*/
- void searchToAdd(Signal* signal, Frag& frag, ConstData searchKey, TreeEnt searchEnt, TreePos& treePos);
- void searchToRemove(Signal* signal, Frag& frag, ConstData searchKey, TreeEnt searchEnt, TreePos& treePos);
- void searchToScan(Signal* signal, Frag& frag, ConstData boundInfo, unsigned boundCount, TreePos& treePos);
+ void searchToAdd(Frag& frag, ConstData searchKey, TreeEnt searchEnt, TreePos& treePos);
+ void searchToRemove(Frag& frag, ConstData searchKey, TreeEnt searchEnt, TreePos& treePos);
+ void searchToScan(Frag& frag, ConstData boundInfo, unsigned boundCount, TreePos& treePos);
/*
* DbtuxCmp.cpp
@@ -647,7 +674,7 @@ private:
PrintPar();
};
void printTree(Signal* signal, Frag& frag, NdbOut& out);
- void printNode(Signal* signal, Frag& frag, NdbOut& out, TupLoc loc, PrintPar& par);
+ void printNode(Frag& frag, NdbOut& out, TupLoc loc, PrintPar& par);
friend class NdbOut& operator<<(NdbOut&, const TupLoc&);
friend class NdbOut& operator<<(NdbOut&, const TreeEnt&);
friend class NdbOut& operator<<(NdbOut&, const TreeNode&);
@@ -805,22 +832,52 @@ Dbtux::ConstData::operator=(Data data)
inline
Dbtux::TupLoc::TupLoc() :
- m_pageId(RNIL),
+ m_pageId1(RNIL >> 16),
+ m_pageId2(RNIL & 0xFFFF),
m_pageOffset(0)
{
}
inline
Dbtux::TupLoc::TupLoc(Uint32 pageId, Uint16 pageOffset) :
- m_pageId(pageId),
+ m_pageId1(pageId >> 16),
+ m_pageId2(pageId & 0xFFFF),
m_pageOffset(pageOffset)
{
}
+inline Uint32
+Dbtux::TupLoc::getPageId() const
+{
+ return (m_pageId1 << 16) | m_pageId2;
+}
+
+inline void
+Dbtux::TupLoc::setPageId(Uint32 pageId)
+{
+ m_pageId1 = (pageId >> 16);
+ m_pageId2 = (pageId & 0xFFFF);
+}
+
+inline Uint32
+Dbtux::TupLoc::getPageOffset() const
+{
+ return (Uint32)m_pageOffset;
+}
+
+inline void
+Dbtux::TupLoc::setPageOffset(Uint32 pageOffset)
+{
+ m_pageOffset = (Uint16)pageOffset;
+}
+
inline bool
Dbtux::TupLoc::operator==(const TupLoc& loc) const
{
- return m_pageId == loc.m_pageId && m_pageOffset == loc.m_pageOffset;
+ return
+ m_pageId1 == loc.m_pageId1 &&
+ m_pageId2 == loc.m_pageId2 &&
+ m_pageOffset == loc.m_pageOffset;
}
inline bool
@@ -851,13 +908,13 @@ Dbtux::TreeEnt::eq(const TreeEnt ent) const
inline int
Dbtux::TreeEnt::cmp(const TreeEnt ent) const
{
- if (m_tupLoc.m_pageId < ent.m_tupLoc.m_pageId)
+ if (m_tupLoc.getPageId() < ent.m_tupLoc.getPageId())
return -1;
- if (m_tupLoc.m_pageId > ent.m_tupLoc.m_pageId)
+ if (m_tupLoc.getPageId() > ent.m_tupLoc.getPageId())
return +1;
- if (m_tupLoc.m_pageOffset < ent.m_tupLoc.m_pageOffset)
+ if (m_tupLoc.getPageOffset() < ent.m_tupLoc.getPageOffset())
return -1;
- if (m_tupLoc.m_pageOffset > ent.m_tupLoc.m_pageOffset)
+ if (m_tupLoc.getPageOffset() > ent.m_tupLoc.getPageOffset())
return +1;
if (m_tupVersion < ent.m_tupVersion)
return -1;
@@ -875,17 +932,14 @@ Dbtux::TreeEnt::cmp(const TreeEnt ent) const
inline
Dbtux::TreeNode::TreeNode() :
m_side(2),
- m_balance(0),
+ m_balance(0 + 1),
pad1(0),
m_occup(0),
m_nodeScan(RNIL)
{
- m_linkPI[0] = NullTupLoc.m_pageId;
- m_linkPO[0] = NullTupLoc.m_pageOffset;
- m_linkPI[1] = NullTupLoc.m_pageId;
- m_linkPO[1] = NullTupLoc.m_pageOffset;
- m_linkPI[2] = NullTupLoc.m_pageId;
- m_linkPO[2] = NullTupLoc.m_pageOffset;
+ m_link[0] = NullTupLoc;
+ m_link[1] = NullTupLoc;
+ m_link[2] = NullTupLoc;
}
// Dbtux::TreeHead
@@ -913,7 +967,6 @@ Dbtux::TreeHead::getSize(AccSize acc) const
case AccFull:
return m_nodeSize;
}
- abort();
return 0;
}
@@ -938,8 +991,7 @@ Dbtux::TreePos::TreePos() :
m_loc(),
m_pos(ZNIL),
m_match(false),
- m_dir(255),
- m_ent()
+ m_dir(255)
{
}
@@ -980,16 +1032,19 @@ Dbtux::ScanOp::ScanOp(ScanBoundPool& scanBoundPool) :
m_boundMin(scanBoundPool),
m_boundMax(scanBoundPool),
m_scanPos(),
- m_lastEnt(),
- m_nodeScan(RNIL)
+ m_scanEnt(),
+ m_nodeScan(RNIL),
+ m_maxAccLockOps(0)
{
m_bound[0] = &m_boundMin;
m_bound[1] = &m_boundMax;
m_boundCnt[0] = 0;
m_boundCnt[1] = 0;
+#ifdef VM_TRACE
for (unsigned i = 0; i < MaxAccLockOps; i++) {
- m_accLockOps[i] = RNIL;
+ m_accLockOps[i] = 0x1f1f1f1f;
}
+#endif
}
// Dbtux::Index
@@ -1054,8 +1109,7 @@ inline
Dbtux::NodeHandle::NodeHandle(Frag& frag) :
m_frag(frag),
m_loc(),
- m_node(0),
- m_acc(AccNone)
+ m_node(0)
{
}
@@ -1063,8 +1117,7 @@ inline
Dbtux::NodeHandle::NodeHandle(const NodeHandle& node) :
m_frag(node.m_frag),
m_loc(node.m_loc),
- m_node(node.m_node),
- m_acc(node.m_acc)
+ m_node(node.m_node)
{
}
@@ -1074,7 +1127,6 @@ Dbtux::NodeHandle::operator=(const NodeHandle& node)
ndbassert(&m_frag == &node.m_frag);
m_loc = node.m_loc;
m_node = node.m_node;
- m_acc = node.m_acc;
return *this;
}
@@ -1088,13 +1140,13 @@ inline Dbtux::TupLoc
Dbtux::NodeHandle::getLink(unsigned i)
{
ndbrequire(i <= 2);
- return TupLoc(m_node->m_linkPI[i], m_node->m_linkPO[i]);
+ return m_node->m_link[i];
}
inline unsigned
Dbtux::NodeHandle::getChilds()
{
- return (getLink(0) != NullTupLoc) + (getLink(1) != NullTupLoc);
+ return (m_node->m_link[0] != NullTupLoc) + (m_node->m_link[1] != NullTupLoc);
}
inline unsigned
@@ -1112,7 +1164,7 @@ Dbtux::NodeHandle::getOccup()
inline int
Dbtux::NodeHandle::getBalance()
{
- return m_node->m_balance;
+ return (int)m_node->m_balance - 1;
}
inline Uint32
@@ -1125,8 +1177,7 @@ inline void
Dbtux::NodeHandle::setLink(unsigned i, TupLoc loc)
{
ndbrequire(i <= 2);
- m_node->m_linkPI[i] = loc.m_pageId;
- m_node->m_linkPO[i] = loc.m_pageOffset;
+ m_node->m_link[i] = loc;
}
inline void
@@ -1148,7 +1199,7 @@ inline void
Dbtux::NodeHandle::setBalance(int b)
{
ndbrequire(abs(b) <= 1);
- m_node->m_balance = b;
+ m_node->m_balance = (unsigned)(b + 1);
}
inline void
@@ -1161,7 +1212,6 @@ inline Dbtux::Data
Dbtux::NodeHandle::getPref()
{
TreeHead& tree = m_frag.m_tree;
- ndbrequire(m_acc >= AccPref);
return tree.getPref(m_node);
}
@@ -1172,11 +1222,6 @@ Dbtux::NodeHandle::getEnt(unsigned pos)
TreeEnt* entList = tree.getEntList(m_node);
const unsigned occup = m_node->m_occup;
ndbrequire(pos < occup);
- if (pos == 0 || pos == occup - 1) {
- ndbrequire(m_acc >= AccPref)
- } else {
- ndbrequire(m_acc == AccFull)
- }
return entList[(1 + pos) % occup];
}
@@ -1224,7 +1269,7 @@ Dbtux::getTupAddr(const Frag& frag, TreeEnt ent)
const Uint32 tableFragPtrI = frag.m_tupTableFragPtrI[ent.m_fragBit];
const TupLoc tupLoc = ent.m_tupLoc;
Uint32 tupAddr = NullTupAddr;
- c_tup->tuxGetTupAddr(tableFragPtrI, tupLoc.m_pageId, tupLoc.m_pageOffset, tupAddr);
+ c_tup->tuxGetTupAddr(tableFragPtrI, tupLoc.getPageId(), tupLoc.getPageOffset(), tupAddr);
jamEntry();
return tupAddr;
}
diff --git a/ndb/src/kernel/blocks/dbtux/DbtuxCmp.cpp b/ndb/src/kernel/blocks/dbtux/DbtuxCmp.cpp
index 549720cc17c..ddab77b97b5 100644
--- a/ndb/src/kernel/blocks/dbtux/DbtuxCmp.cpp
+++ b/ndb/src/kernel/blocks/dbtux/DbtuxCmp.cpp
@@ -87,21 +87,23 @@ Dbtux::cmpSearchKey(const Frag& frag, unsigned& start, ConstData searchKey, Cons
/*
* Scan bound vs node prefix or entry.
*
- * Compare lower or upper bound and index attribute data. The attribute
- * data may be partial in which case CmpUnknown may be returned.
- * Returns -1 if the boundary is to the left of the compared key and +1
- * if the boundary is to the right of the compared key.
+ * Compare lower or upper bound and index entry data. The entry data
+ * may be partial in which case CmpUnknown may be returned. Otherwise
+ * returns -1 if the bound is to the left of the entry and +1 if the
+ * bound is to the right of the entry.
*
- * To get this behaviour we treat equality a little bit special. If the
- * boundary is a lower bound then the boundary is to the left of all
- * equal keys and if it is an upper bound then the boundary is to the
- * right of all equal keys.
+ * The routine is similar to cmpSearchKey, but 0 is never returned.
+ * Suppose all attributes compare equal. Recall that all bounds except
+ * possibly the last one are non-strict. Use the given bound direction
+ * (0-lower 1-upper) and strictness of last bound to return -1 or +1.
*
- * When searching for the first key we are using the lower bound to try
- * to find the first key that is to the right of the boundary. Then we
- * start scanning from this tuple (including the tuple itself) until we
- * find the first key which is to the right of the boundary. Then we
- * stop and do not include that key in the scan result.
+ * Following example illustrates this. We are at (a=2, b=3).
+ *
+ * dir bounds strict return
+ * 0 a >= 2 and b >= 3 no -1
+ * 0 a >= 2 and b > 3 yes +1
+ * 1 a <= 2 and b <= 3 no +1
+ * 1 a <= 2 and b < 3 yes -1
*/
int
Dbtux::cmpScanBound(const Frag& frag, unsigned dir, ConstData boundInfo, unsigned boundCount, ConstData entryData, unsigned maxlen)
@@ -111,12 +113,7 @@ Dbtux::cmpScanBound(const Frag& frag, unsigned dir, ConstData boundInfo, unsigne
ndbrequire(dir <= 1);
// number of words of data left
unsigned len2 = maxlen;
- /*
- * No boundary means full scan, low boundary is to the right of all
- * keys. Thus we should always return -1. For upper bound we are to
- * the right of all keys, thus we should always return +1. We achieve
- * this behaviour by initializing type to 4.
- */
+ // in case of no bounds, init last type to something non-strict
unsigned type = 4;
while (boundCount != 0) {
if (len2 <= AttributeHeaderSize) {
@@ -124,7 +121,7 @@ Dbtux::cmpScanBound(const Frag& frag, unsigned dir, ConstData boundInfo, unsigne
return NdbSqlUtil::CmpUnknown;
}
len2 -= AttributeHeaderSize;
- // get and skip bound type
+ // get and skip bound type (it is used after the loop)
type = boundInfo[0];
boundInfo += 1;
if (! boundInfo.ah().isNULL()) {
@@ -166,30 +163,7 @@ Dbtux::cmpScanBound(const Frag& frag, unsigned dir, ConstData boundInfo, unsigne
entryData += AttributeHeaderSize + entryData.ah().getDataSize();
boundCount -= 1;
}
- if (dir == 0) {
- jam();
- /*
- * Looking for the lower bound. If strict lower bound then the
- * boundary is to the right of the compared key and otherwise (equal
- * included in range) then the boundary is to the left of the key.
- */
- if (type == 1) {
- jam();
- return +1;
- }
- return -1;
- } else {
- jam();
- /*
- * Looking for the upper bound. If strict upper bound then the
- * boundary is to the left of all equal keys and otherwise (equal
- * included in the range) then the boundary is to the right of all
- * equal keys.
- */
- if (type == 3) {
- jam();
- return -1;
- }
- return +1;
- }
+ // all attributes were equal
+ const int strict = (type & 0x1);
+ return (dir == 0 ? (strict == 0 ? -1 : +1) : (strict == 0 ? +1 : -1));
}
diff --git a/ndb/src/kernel/blocks/dbtux/DbtuxDebug.cpp b/ndb/src/kernel/blocks/dbtux/DbtuxDebug.cpp
index 8d31d2c6a55..c5c22264460 100644
--- a/ndb/src/kernel/blocks/dbtux/DbtuxDebug.cpp
+++ b/ndb/src/kernel/blocks/dbtux/DbtuxDebug.cpp
@@ -98,7 +98,7 @@ Dbtux::printTree(Signal* signal, Frag& frag, NdbOut& out)
strcpy(par.m_path, ".");
par.m_side = 2;
par.m_parent = NullTupLoc;
- printNode(signal, frag, out, tree.m_root, par);
+ printNode(frag, out, tree.m_root, par);
out.m_out->flush();
if (! par.m_ok) {
if (debugFile == 0) {
@@ -114,7 +114,7 @@ Dbtux::printTree(Signal* signal, Frag& frag, NdbOut& out)
}
void
-Dbtux::printNode(Signal* signal, Frag& frag, NdbOut& out, TupLoc loc, PrintPar& par)
+Dbtux::printNode(Frag& frag, NdbOut& out, TupLoc loc, PrintPar& par)
{
if (loc == NullTupLoc) {
par.m_depth = 0;
@@ -122,7 +122,7 @@ Dbtux::printNode(Signal* signal, Frag& frag, NdbOut& out, TupLoc loc, PrintPar&
}
TreeHead& tree = frag.m_tree;
NodeHandle node(frag);
- selectNode(signal, node, loc, AccFull);
+ selectNode(node, loc);
out << par.m_path << " " << node << endl;
// check children
PrintPar cpar[2];
@@ -132,7 +132,7 @@ Dbtux::printNode(Signal* signal, Frag& frag, NdbOut& out, TupLoc loc, PrintPar&
cpar[i].m_side = i;
cpar[i].m_depth = 0;
cpar[i].m_parent = loc;
- printNode(signal, frag, out, node.getLink(i), cpar[i]);
+ printNode(frag, out, node.getLink(i), cpar[i]);
if (! cpar[i].m_ok) {
par.m_ok = false;
}
@@ -178,16 +178,19 @@ Dbtux::printNode(Signal* signal, Frag& frag, NdbOut& out, TupLoc loc, PrintPar&
out << "occupancy " << node.getOccup() << " of interior node";
out << " less than min " << tree.m_minOccup << endl;
}
- // check missed half-leaf/leaf merge
+#ifdef dbtux_totally_groks_t_trees
+ // check missed semi-leaf/leaf merge
for (unsigned i = 0; i <= 1; i++) {
if (node.getLink(i) != NullTupLoc &&
node.getLink(1 - i) == NullTupLoc &&
- node.getOccup() + cpar[i].m_occup <= tree.m_maxOccup) {
+ // our semi-leaf seems to satify interior minOccup condition
+ node.getOccup() < tree.m_minOccup) {
par.m_ok = false;
out << par.m_path << sep;
out << "missed merge with child " << i << endl;
}
}
+#endif
// check inline prefix
{ ConstData data1 = node.getPref();
Uint32 data2[MaxPrefSize];
@@ -256,8 +259,8 @@ operator<<(NdbOut& out, const Dbtux::TupLoc& loc)
if (loc == Dbtux::NullTupLoc) {
out << "null";
} else {
- out << dec << loc.m_pageId;
- out << "." << dec << loc.m_pageOffset;
+ out << dec << loc.getPageId();
+ out << "." << dec << loc.getPageOffset();
}
return out;
}
@@ -274,16 +277,13 @@ operator<<(NdbOut& out, const Dbtux::TreeEnt& ent)
NdbOut&
operator<<(NdbOut& out, const Dbtux::TreeNode& node)
{
- Dbtux::TupLoc link0(node.m_linkPI[0], node.m_linkPO[0]);
- Dbtux::TupLoc link1(node.m_linkPI[1], node.m_linkPO[1]);
- Dbtux::TupLoc link2(node.m_linkPI[2], node.m_linkPO[2]);
out << "[TreeNode " << hex << &node;
- out << " [left " << link0 << "]";
- out << " [right " << link1 << "]";
- out << " [up " << link2 << "]";
+ out << " [left " << node.m_link[0] << "]";
+ out << " [right " << node.m_link[1] << "]";
+ out << " [up " << node.m_link[2] << "]";
out << " [side " << dec << node.m_side << "]";
out << " [occup " << dec << node.m_occup << "]";
- out << " [balance " << dec << (int)node.m_balance << "]";
+ out << " [balance " << dec << (int)node.m_balance - 1 << "]";
out << " [nodeScan " << hex << node.m_nodeScan << "]";
out << "]";
return out;
@@ -313,7 +313,6 @@ operator<<(NdbOut& out, const Dbtux::TreePos& pos)
out << " [pos " << dec << pos.m_pos << "]";
out << " [match " << dec << pos.m_match << "]";
out << " [dir " << dec << pos.m_dir << "]";
- out << " [ent " << pos.m_ent << "]";
out << "]";
return out;
}
@@ -350,6 +349,7 @@ operator<<(NdbOut& out, const Dbtux::ScanOp& scan)
out << " [lockMode " << dec << scan.m_lockMode << "]";
out << " [keyInfo " << dec << scan.m_keyInfo << "]";
out << " [pos " << scan.m_scanPos << "]";
+ out << " [ent " << scan.m_scanEnt << "]";
for (unsigned i = 0; i <= 1; i++) {
out << " [bound " << dec << i;
Dbtux::ScanBound& bound = *scan.m_bound[i];
@@ -410,27 +410,21 @@ operator<<(NdbOut& out, const Dbtux::NodeHandle& node)
const Dbtux::TreeHead& tree = frag.m_tree;
out << "[NodeHandle " << hex << &node;
out << " [loc " << node.m_loc << "]";
- out << " [acc " << dec << node.m_acc << "]";
out << " [node " << *node.m_node << "]";
- if (node.m_acc >= Dbtux::AccPref) {
- const Uint32* data;
- out << " [pref";
- data = (const Uint32*)node.m_node + Dbtux::NodeHeadSize;
- for (unsigned j = 0; j < tree.m_prefSize; j++)
- out << " " << hex << data[j];
- out << "]";
- out << " [entList";
- unsigned numpos = node.m_node->m_occup;
- if (node.m_acc < Dbtux::AccFull && numpos > 2) {
- numpos = 2;
- out << "(" << dec << numpos << ")";
- }
- data = (const Uint32*)node.m_node + Dbtux::NodeHeadSize + tree.m_prefSize;
- const Dbtux::TreeEnt* entList = (const Dbtux::TreeEnt*)data;
- for (unsigned pos = 0; pos < numpos; pos++)
- out << " " << entList[pos];
- out << "]";
- }
+ const Uint32* data;
+ out << " [pref";
+ data = (const Uint32*)node.m_node + Dbtux::NodeHeadSize;
+ for (unsigned j = 0; j < tree.m_prefSize; j++)
+ out << " " << hex << data[j];
+ out << "]";
+ out << " [entList";
+ unsigned numpos = node.m_node->m_occup;
+ data = (const Uint32*)node.m_node + Dbtux::NodeHeadSize + tree.m_prefSize;
+ const Dbtux::TreeEnt* entList = (const Dbtux::TreeEnt*)data;
+ // print entries in logical order
+ for (unsigned pos = 1; pos <= numpos; pos++)
+ out << " " << entList[pos % numpos];
+ out << "]";
out << "]";
return out;
}
diff --git a/ndb/src/kernel/blocks/dbtux/DbtuxGen.cpp b/ndb/src/kernel/blocks/dbtux/DbtuxGen.cpp
index 39cd8e25184..ded02696a89 100644
--- a/ndb/src/kernel/blocks/dbtux/DbtuxGen.cpp
+++ b/ndb/src/kernel/blocks/dbtux/DbtuxGen.cpp
@@ -245,7 +245,7 @@ Dbtux::readKeyAttrs(const Frag& frag, TreeEnt ent, unsigned start, Data keyData)
const Uint32 numAttrs = frag.m_numAttrs - start;
// skip to start position in keyAttrs only
keyAttrs += start;
- int ret = c_tup->tuxReadAttrs(tableFragPtrI, tupLoc.m_pageId, tupLoc.m_pageOffset, tupVersion, keyAttrs, numAttrs, keyData);
+ int ret = c_tup->tuxReadAttrs(tableFragPtrI, tupLoc.getPageId(), tupLoc.getPageOffset(), tupVersion, keyAttrs, numAttrs, keyData);
jamEntry();
// TODO handle error
ndbrequire(ret > 0);
@@ -256,7 +256,7 @@ Dbtux::readTablePk(const Frag& frag, TreeEnt ent, Data pkData, unsigned& pkSize)
{
const Uint32 tableFragPtrI = frag.m_tupTableFragPtrI[ent.m_fragBit];
const TupLoc tupLoc = ent.m_tupLoc;
- int ret = c_tup->tuxReadPk(tableFragPtrI, tupLoc.m_pageId, tupLoc.m_pageOffset, pkData);
+ int ret = c_tup->tuxReadPk(tableFragPtrI, tupLoc.getPageId(), tupLoc.getPageOffset(), pkData);
jamEntry();
// TODO handle error
ndbrequire(ret > 0);
diff --git a/ndb/src/kernel/blocks/dbtux/DbtuxMaint.cpp b/ndb/src/kernel/blocks/dbtux/DbtuxMaint.cpp
index 24b030bf8ec..30afb51e7d7 100644
--- a/ndb/src/kernel/blocks/dbtux/DbtuxMaint.cpp
+++ b/ndb/src/kernel/blocks/dbtux/DbtuxMaint.cpp
@@ -117,10 +117,10 @@ Dbtux::execTUX_MAINT_REQ(Signal* signal)
switch (opCode) {
case TuxMaintReq::OpAdd:
jam();
- searchToAdd(signal, frag, c_searchKey, ent, treePos);
+ searchToAdd(frag, c_searchKey, ent, treePos);
#ifdef VM_TRACE
if (debugFlags & DebugMaint) {
- debugOut << treePos << endl;
+ debugOut << treePos << (treePos.m_match ? " - error" : "") << endl;
}
#endif
if (treePos.m_match) {
@@ -133,8 +133,8 @@ Dbtux::execTUX_MAINT_REQ(Signal* signal)
break;
}
/*
- * At most one new node is inserted in the operation. We keep one
- * free node pre-allocated so the operation cannot fail.
+ * At most one new node is inserted in the operation. Pre-allocate
+ * it so that the operation cannot fail.
*/
if (frag.m_freeLoc == NullTupLoc) {
jam();
@@ -144,17 +144,19 @@ Dbtux::execTUX_MAINT_REQ(Signal* signal)
jam();
break;
}
+ // link to freelist
+ node.setLink(0, frag.m_freeLoc);
frag.m_freeLoc = node.m_loc;
ndbrequire(frag.m_freeLoc != NullTupLoc);
}
- treeAdd(signal, frag, treePos, ent);
+ treeAdd(frag, treePos, ent);
break;
case TuxMaintReq::OpRemove:
jam();
- searchToRemove(signal, frag, c_searchKey, ent, treePos);
+ searchToRemove(frag, c_searchKey, ent, treePos);
#ifdef VM_TRACE
if (debugFlags & DebugMaint) {
- debugOut << treePos << endl;
+ debugOut << treePos << (! treePos.m_match ? " - error" : "") << endl;
}
#endif
if (! treePos.m_match) {
@@ -166,7 +168,7 @@ Dbtux::execTUX_MAINT_REQ(Signal* signal)
}
break;
}
- treeRemove(signal, frag, treePos);
+ treeRemove(frag, treePos);
break;
default:
ndbrequire(false);
diff --git a/ndb/src/kernel/blocks/dbtux/DbtuxMeta.cpp b/ndb/src/kernel/blocks/dbtux/DbtuxMeta.cpp
index 3c0af3ca79d..1577c5045e0 100644
--- a/ndb/src/kernel/blocks/dbtux/DbtuxMeta.cpp
+++ b/ndb/src/kernel/blocks/dbtux/DbtuxMeta.cpp
@@ -211,11 +211,7 @@ Dbtux::execTUX_ADD_ATTRREQ(Signal* signal)
// make these configurable later
tree.m_nodeSize = MAX_TTREE_NODE_SIZE;
tree.m_prefSize = MAX_TTREE_PREF_SIZE;
-#ifdef dbtux_min_occup_less_max_occup
const unsigned maxSlack = MAX_TTREE_NODE_SLACK;
-#else
- const unsigned maxSlack = 0;
-#endif
// size up to and including first 2 entries
const unsigned pref = tree.getSize(AccPref);
if (! (pref <= tree.m_nodeSize)) {
@@ -235,6 +231,20 @@ Dbtux::execTUX_ADD_ATTRREQ(Signal* signal)
tree.m_minOccup = tree.m_maxOccup - maxSlack;
// root node does not exist (also set by ctor)
tree.m_root = NullTupLoc;
+#ifdef VM_TRACE
+ if (debugFlags & DebugMeta) {
+ if (fragOpPtr.p->m_fragNo == 0) {
+ debugOut << "Index id=" << indexPtr.i;
+ debugOut << " nodeSize=" << tree.m_nodeSize;
+ debugOut << " headSize=" << NodeHeadSize;
+ debugOut << " prefSize=" << tree.m_prefSize;
+ debugOut << " entrySize=" << TreeEntSize;
+ debugOut << " minOccup=" << tree.m_minOccup;
+ debugOut << " maxOccup=" << tree.m_maxOccup;
+ debugOut << endl;
+ }
+ }
+#endif
// fragment is defined
c_fragOpPool.release(fragOpPtr);
}
diff --git a/ndb/src/kernel/blocks/dbtux/DbtuxNode.cpp b/ndb/src/kernel/blocks/dbtux/DbtuxNode.cpp
index a1bfa2179bb..389192fd0cf 100644
--- a/ndb/src/kernel/blocks/dbtux/DbtuxNode.cpp
+++ b/ndb/src/kernel/blocks/dbtux/DbtuxNode.cpp
@@ -24,8 +24,8 @@ int
Dbtux::allocNode(Signal* signal, NodeHandle& node)
{
Frag& frag = node.m_frag;
- Uint32 pageId = NullTupLoc.m_pageId;
- Uint32 pageOffset = NullTupLoc.m_pageOffset;
+ Uint32 pageId = NullTupLoc.getPageId();
+ Uint32 pageOffset = NullTupLoc.getPageOffset();
Uint32* node32 = 0;
int errorCode = c_tup->tuxAllocNode(signal, frag.m_tupIndexFragPtrI, pageId, pageOffset, node32);
jamEntry();
@@ -33,55 +33,39 @@ Dbtux::allocNode(Signal* signal, NodeHandle& node)
jam();
node.m_loc = TupLoc(pageId, pageOffset);
node.m_node = reinterpret_cast<TreeNode*>(node32);
- node.m_acc = AccNone;
ndbrequire(node.m_loc != NullTupLoc && node.m_node != 0);
}
return errorCode;
}
/*
- * Access more of the node.
- */
-void
-Dbtux::accessNode(Signal* signal, NodeHandle& node, AccSize acc)
-{
- ndbrequire(node.m_loc != NullTupLoc && node.m_node != 0);
- if (node.m_acc >= acc)
- return;
- // XXX could do prefetch
- node.m_acc = acc;
-}
-
-/*
* Set handle to point to existing node.
*/
void
-Dbtux::selectNode(Signal* signal, NodeHandle& node, TupLoc loc, AccSize acc)
+Dbtux::selectNode(NodeHandle& node, TupLoc loc)
{
Frag& frag = node.m_frag;
ndbrequire(loc != NullTupLoc);
- Uint32 pageId = loc.m_pageId;
- Uint32 pageOffset = loc.m_pageOffset;
+ Uint32 pageId = loc.getPageId();
+ Uint32 pageOffset = loc.getPageOffset();
Uint32* node32 = 0;
c_tup->tuxGetNode(frag.m_tupIndexFragPtrI, pageId, pageOffset, node32);
jamEntry();
node.m_loc = loc;
node.m_node = reinterpret_cast<TreeNode*>(node32);
- node.m_acc = AccNone;
ndbrequire(node.m_loc != NullTupLoc && node.m_node != 0);
- accessNode(signal, node, acc);
}
/*
- * Set handle to point to new node. Uses the pre-allocated node.
+ * Set handle to point to new node. Uses a pre-allocated node.
*/
void
-Dbtux::insertNode(Signal* signal, NodeHandle& node, AccSize acc)
+Dbtux::insertNode(NodeHandle& node)
{
Frag& frag = node.m_frag;
- TupLoc loc = frag.m_freeLoc;
- frag.m_freeLoc = NullTupLoc;
- selectNode(signal, node, loc, acc);
+ // unlink from freelist
+ selectNode(node, frag.m_freeLoc);
+ frag.m_freeLoc = node.getLink(0);
new (node.m_node) TreeNode();
#ifdef VM_TRACE
TreeHead& tree = frag.m_tree;
@@ -92,20 +76,17 @@ Dbtux::insertNode(Signal* signal, NodeHandle& node, AccSize acc)
}
/*
- * Delete existing node.
+ * Delete existing node. Simply put it on the freelist.
*/
void
-Dbtux::deleteNode(Signal* signal, NodeHandle& node)
+Dbtux::deleteNode(NodeHandle& node)
{
Frag& frag = node.m_frag;
ndbrequire(node.getOccup() == 0);
- TupLoc loc = node.m_loc;
- Uint32 pageId = loc.m_pageId;
- Uint32 pageOffset = loc.m_pageOffset;
- Uint32* node32 = reinterpret_cast<Uint32*>(node.m_node);
- c_tup->tuxFreeNode(signal, frag.m_tupIndexFragPtrI, pageId, pageOffset, node32);
- jamEntry();
- // invalidate handle and storage
+ // link to freelist
+ node.setLink(0, frag.m_freeLoc);
+ frag.m_freeLoc = node.m_loc;
+ // invalidate the handle
node.m_loc = NullTupLoc;
node.m_node = 0;
}
@@ -115,7 +96,7 @@ Dbtux::deleteNode(Signal* signal, NodeHandle& node)
* attribute headers for now. XXX use null mask instead
*/
void
-Dbtux::setNodePref(Signal* signal, NodeHandle& node)
+Dbtux::setNodePref(NodeHandle& node)
{
const Frag& frag = node.m_frag;
const TreeHead& tree = frag.m_tree;
@@ -133,18 +114,45 @@ Dbtux::setNodePref(Signal* signal, NodeHandle& node)
* v
* A B C D E _ _ => A B C X D E _
* 0 1 2 3 4 5 6 0 1 2 3 4 5 6
+ *
+ * Add list of scans at the new entry.
*/
void
-Dbtux::nodePushUp(Signal* signal, NodeHandle& node, unsigned pos, const TreeEnt& ent)
+Dbtux::nodePushUp(NodeHandle& node, unsigned pos, const TreeEnt& ent, Uint32 scanList)
{
Frag& frag = node.m_frag;
TreeHead& tree = frag.m_tree;
const unsigned occup = node.getOccup();
ndbrequire(occup < tree.m_maxOccup && pos <= occup);
- // fix scans
+ // fix old scans
+ if (node.getNodeScan() != RNIL)
+ nodePushUpScans(node, pos);
+ // fix node
+ TreeEnt* const entList = tree.getEntList(node.m_node);
+ entList[occup] = entList[0];
+ TreeEnt* const tmpList = entList + 1;
+ for (unsigned i = occup; i > pos; i--) {
+ jam();
+ tmpList[i] = tmpList[i - 1];
+ }
+ tmpList[pos] = ent;
+ entList[0] = entList[occup + 1];
+ node.setOccup(occup + 1);
+ // add new scans
+ if (scanList != RNIL)
+ addScanList(node, pos, scanList);
+ // fix prefix
+ if (occup == 0 || pos == 0)
+ setNodePref(node);
+}
+
+void
+Dbtux::nodePushUpScans(NodeHandle& node, unsigned pos)
+{
+ const unsigned occup = node.getOccup();
ScanOpPtr scanPtr;
scanPtr.i = node.getNodeScan();
- while (scanPtr.i != RNIL) {
+ do {
jam();
c_scanOpPool.getPtr(scanPtr);
TreePos& scanPos = scanPtr.p->m_scanPos;
@@ -160,21 +168,7 @@ Dbtux::nodePushUp(Signal* signal, NodeHandle& node, unsigned pos, const TreeEnt&
scanPos.m_pos++;
}
scanPtr.i = scanPtr.p->m_nodeScan;
- }
- // fix node
- TreeEnt* const entList = tree.getEntList(node.m_node);
- entList[occup] = entList[0];
- TreeEnt* const tmpList = entList + 1;
- for (unsigned i = occup; i > pos; i--) {
- jam();
- tmpList[i] = tmpList[i - 1];
- }
- tmpList[pos] = ent;
- entList[0] = entList[occup + 1];
- node.setOccup(occup + 1);
- // fix prefix
- if (occup == 0 || pos == 0)
- setNodePref(signal, node);
+ } while (scanPtr.i != RNIL);
}
/*
@@ -185,42 +179,55 @@ Dbtux::nodePushUp(Signal* signal, NodeHandle& node, unsigned pos, const TreeEnt&
* ^ ^
* A B C D E F _ => A B C E F _ _
* 0 1 2 3 4 5 6 0 1 2 3 4 5 6
+ *
+ * Scans at removed entry are returned if non-zero location is passed or
+ * else moved forward.
*/
void
-Dbtux::nodePopDown(Signal* signal, NodeHandle& node, unsigned pos, TreeEnt& ent)
+Dbtux::nodePopDown(NodeHandle& node, unsigned pos, TreeEnt& ent, Uint32* scanList)
{
Frag& frag = node.m_frag;
TreeHead& tree = frag.m_tree;
const unsigned occup = node.getOccup();
ndbrequire(occup <= tree.m_maxOccup && pos < occup);
- ScanOpPtr scanPtr;
- // move scans whose entry disappears
- scanPtr.i = node.getNodeScan();
- while (scanPtr.i != RNIL) {
+ if (node.getNodeScan() != RNIL) {
+ // remove or move scans at this position
+ if (scanList == 0)
+ moveScanList(node, pos);
+ else
+ removeScanList(node, pos, *scanList);
+ // fix other scans
+ if (node.getNodeScan() != RNIL)
+ nodePopDownScans(node, pos);
+ }
+ // fix node
+ TreeEnt* const entList = tree.getEntList(node.m_node);
+ entList[occup] = entList[0];
+ TreeEnt* const tmpList = entList + 1;
+ ent = tmpList[pos];
+ for (unsigned i = pos; i < occup - 1; i++) {
jam();
- c_scanOpPool.getPtr(scanPtr);
- TreePos& scanPos = scanPtr.p->m_scanPos;
- ndbrequire(scanPos.m_loc == node.m_loc && scanPos.m_pos < occup);
- const Uint32 nextPtrI = scanPtr.p->m_nodeScan;
- if (scanPos.m_pos == pos) {
- jam();
-#ifdef VM_TRACE
- if (debugFlags & DebugScan) {
- debugOut << "Move scan " << scanPtr.i << " " << *scanPtr.p << endl;
- debugOut << "At popDown pos=" << pos << " " << node << endl;
- }
-#endif
- scanNext(signal, scanPtr);
- }
- scanPtr.i = nextPtrI;
+ tmpList[i] = tmpList[i + 1];
}
- // fix other scans
+ entList[0] = entList[occup - 1];
+ node.setOccup(occup - 1);
+ // fix prefix
+ if (occup != 1 && pos == 0)
+ setNodePref(node);
+}
+
+void
+Dbtux::nodePopDownScans(NodeHandle& node, unsigned pos)
+{
+ const unsigned occup = node.getOccup();
+ ScanOpPtr scanPtr;
scanPtr.i = node.getNodeScan();
- while (scanPtr.i != RNIL) {
+ do {
jam();
c_scanOpPool.getPtr(scanPtr);
TreePos& scanPos = scanPtr.p->m_scanPos;
ndbrequire(scanPos.m_loc == node.m_loc && scanPos.m_pos < occup);
+ // handled before
ndbrequire(scanPos.m_pos != pos);
if (scanPos.m_pos > pos) {
jam();
@@ -233,21 +240,7 @@ Dbtux::nodePopDown(Signal* signal, NodeHandle& node, unsigned pos, TreeEnt& ent)
scanPos.m_pos--;
}
scanPtr.i = scanPtr.p->m_nodeScan;
- }
- // fix node
- TreeEnt* const entList = tree.getEntList(node.m_node);
- entList[occup] = entList[0];
- TreeEnt* const tmpList = entList + 1;
- ent = tmpList[pos];
- for (unsigned i = pos; i < occup - 1; i++) {
- jam();
- tmpList[i] = tmpList[i + 1];
- }
- entList[0] = entList[occup - 1];
- node.setOccup(occup - 1);
- // fix prefix
- if (occup != 1 && pos == 0)
- setNodePref(signal, node);
+ } while (scanPtr.i != RNIL);
}
/*
@@ -258,43 +251,52 @@ Dbtux::nodePopDown(Signal* signal, NodeHandle& node, unsigned pos, TreeEnt& ent)
* ^ v ^
* A B C D E _ _ => B C D X E _ _
* 0 1 2 3 4 5 6 0 1 2 3 4 5 6
+ *
+ * Return list of scans at the removed position 0.
*/
void
-Dbtux::nodePushDown(Signal* signal, NodeHandle& node, unsigned pos, TreeEnt& ent)
+Dbtux::nodePushDown(NodeHandle& node, unsigned pos, TreeEnt& ent, Uint32& scanList)
{
Frag& frag = node.m_frag;
TreeHead& tree = frag.m_tree;
const unsigned occup = node.getOccup();
ndbrequire(occup <= tree.m_maxOccup && pos < occup);
- ScanOpPtr scanPtr;
- // move scans whose entry disappears
- scanPtr.i = node.getNodeScan();
- while (scanPtr.i != RNIL) {
+ if (node.getNodeScan() != RNIL) {
+ // remove scans at 0
+ removeScanList(node, 0, scanList);
+ // fix other scans
+ if (node.getNodeScan() != RNIL)
+ nodePushDownScans(node, pos);
+ }
+ // fix node
+ TreeEnt* const entList = tree.getEntList(node.m_node);
+ entList[occup] = entList[0];
+ TreeEnt* const tmpList = entList + 1;
+ TreeEnt oldMin = tmpList[0];
+ for (unsigned i = 0; i < pos; i++) {
jam();
- c_scanOpPool.getPtr(scanPtr);
- TreePos& scanPos = scanPtr.p->m_scanPos;
- ndbrequire(scanPos.m_loc == node.m_loc && scanPos.m_pos < occup);
- const Uint32 nextPtrI = scanPtr.p->m_nodeScan;
- if (scanPos.m_pos == 0) {
- jam();
-#ifdef VM_TRACE
- if (debugFlags & DebugScan) {
- debugOut << "Move scan " << scanPtr.i << " " << *scanPtr.p << endl;
- debugOut << "At pushDown pos=" << pos << " " << node << endl;
- }
-#endif
- // here we may miss a valid entry "X" XXX known bug
- scanNext(signal, scanPtr);
- }
- scanPtr.i = nextPtrI;
+ tmpList[i] = tmpList[i + 1];
}
- // fix other scans
+ tmpList[pos] = ent;
+ ent = oldMin;
+ entList[0] = entList[occup];
+ // fix prefix
+ if (true)
+ setNodePref(node);
+}
+
+void
+Dbtux::nodePushDownScans(NodeHandle& node, unsigned pos)
+{
+ const unsigned occup = node.getOccup();
+ ScanOpPtr scanPtr;
scanPtr.i = node.getNodeScan();
- while (scanPtr.i != RNIL) {
+ do {
jam();
c_scanOpPool.getPtr(scanPtr);
TreePos& scanPos = scanPtr.p->m_scanPos;
ndbrequire(scanPos.m_loc == node.m_loc && scanPos.m_pos < occup);
+ // handled before
ndbrequire(scanPos.m_pos != 0);
if (scanPos.m_pos <= pos) {
jam();
@@ -307,22 +309,7 @@ Dbtux::nodePushDown(Signal* signal, NodeHandle& node, unsigned pos, TreeEnt& ent
scanPos.m_pos--;
}
scanPtr.i = scanPtr.p->m_nodeScan;
- }
- // fix node
- TreeEnt* const entList = tree.getEntList(node.m_node);
- entList[occup] = entList[0];
- TreeEnt* const tmpList = entList + 1;
- TreeEnt oldMin = tmpList[0];
- for (unsigned i = 0; i < pos; i++) {
- jam();
- tmpList[i] = tmpList[i + 1];
- }
- tmpList[pos] = ent;
- ent = oldMin;
- entList[0] = entList[occup];
- // fix prefix
- if (true)
- setNodePref(signal, node);
+ } while (scanPtr.i != RNIL);
}
/*
@@ -334,39 +321,50 @@ Dbtux::nodePushDown(Signal* signal, NodeHandle& node, unsigned pos, TreeEnt& ent
* v ^ ^
* A B C D E _ _ => X A B C E _ _
* 0 1 2 3 4 5 6 0 1 2 3 4 5 6
+ *
+ * Move scans at removed entry and add scans at the new entry.
*/
void
-Dbtux::nodePopUp(Signal* signal, NodeHandle& node, unsigned pos, TreeEnt& ent)
+Dbtux::nodePopUp(NodeHandle& node, unsigned pos, TreeEnt& ent, Uint32 scanList)
{
Frag& frag = node.m_frag;
TreeHead& tree = frag.m_tree;
const unsigned occup = node.getOccup();
ndbrequire(occup <= tree.m_maxOccup && pos < occup);
- ScanOpPtr scanPtr;
- // move scans whose entry disappears
- scanPtr.i = node.getNodeScan();
- while (scanPtr.i != RNIL) {
+ if (node.getNodeScan() != RNIL) {
+ // move scans whose entry disappears
+ moveScanList(node, pos);
+ // fix other scans
+ if (node.getNodeScan() != RNIL)
+ nodePopUpScans(node, pos);
+ }
+ // fix node
+ TreeEnt* const entList = tree.getEntList(node.m_node);
+ entList[occup] = entList[0];
+ TreeEnt* const tmpList = entList + 1;
+ TreeEnt newMin = ent;
+ ent = tmpList[pos];
+ for (unsigned i = pos; i > 0; i--) {
jam();
- c_scanOpPool.getPtr(scanPtr);
- TreePos& scanPos = scanPtr.p->m_scanPos;
- ndbrequire(scanPos.m_loc == node.m_loc && scanPos.m_pos < occup);
- const Uint32 nextPtrI = scanPtr.p->m_nodeScan;
- if (scanPos.m_pos == pos) {
- jam();
-#ifdef VM_TRACE
- if (debugFlags & DebugScan) {
- debugOut << "Move scan " << scanPtr.i << " " << *scanPtr.p << endl;
- debugOut << "At popUp pos=" << pos << " " << node << endl;
- }
-#endif
- // here we may miss a valid entry "X" XXX known bug
- scanNext(signal, scanPtr);
- }
- scanPtr.i = nextPtrI;
+ tmpList[i] = tmpList[i - 1];
}
- // fix other scans
+ tmpList[0] = newMin;
+ entList[0] = entList[occup];
+ // add scans
+ if (scanList != RNIL)
+ addScanList(node, 0, scanList);
+ // fix prefix
+ if (true)
+ setNodePref(node);
+}
+
+void
+Dbtux::nodePopUpScans(NodeHandle& node, unsigned pos)
+{
+ const unsigned occup = node.getOccup();
+ ScanOpPtr scanPtr;
scanPtr.i = node.getNodeScan();
- while (scanPtr.i != RNIL) {
+ do {
jam();
c_scanOpPool.getPtr(scanPtr);
TreePos& scanPos = scanPtr.p->m_scanPos;
@@ -383,41 +381,123 @@ Dbtux::nodePopUp(Signal* signal, NodeHandle& node, unsigned pos, TreeEnt& ent)
scanPos.m_pos++;
}
scanPtr.i = scanPtr.p->m_nodeScan;
- }
- // fix node
- TreeEnt* const entList = tree.getEntList(node.m_node);
- entList[occup] = entList[0];
- TreeEnt* const tmpList = entList + 1;
- TreeEnt newMin = ent;
- ent = tmpList[pos];
- for (unsigned i = pos; i > 0; i--) {
- jam();
- tmpList[i] = tmpList[i - 1];
- }
- tmpList[0] = newMin;
- entList[0] = entList[occup];
- // fix prefix
- if (true)
- setNodePref(signal, node);
+ } while (scanPtr.i != RNIL);
}
/*
- * Move all possible entries from another node before the min (i=0) or
- * after the max (i=1). XXX can be optimized
+ * Move number of entries from another node to this node before the min
+ * (i=0) or after the max (i=1). Expensive but not often used.
*/
void
-Dbtux::nodeSlide(Signal* signal, NodeHandle& dstNode, NodeHandle& srcNode, unsigned i)
+Dbtux::nodeSlide(NodeHandle& dstNode, NodeHandle& srcNode, unsigned cnt, unsigned i)
{
Frag& frag = dstNode.m_frag;
TreeHead& tree = frag.m_tree;
ndbrequire(i <= 1);
- while (dstNode.getOccup() < tree.m_maxOccup && srcNode.getOccup() != 0) {
+ while (cnt != 0) {
TreeEnt ent;
- nodePopDown(signal, srcNode, i == 0 ? srcNode.getOccup() - 1 : 0, ent);
- nodePushUp(signal, dstNode, i == 0 ? 0 : dstNode.getOccup(), ent);
+ Uint32 scanList = RNIL;
+ nodePopDown(srcNode, i == 0 ? srcNode.getOccup() - 1 : 0, ent, &scanList);
+ nodePushUp(dstNode, i == 0 ? 0 : dstNode.getOccup(), ent, scanList);
+ cnt--;
}
}
+// scans linked to node
+
+
+/*
+ * Add list of scans to node at given position.
+ */
+void
+Dbtux::addScanList(NodeHandle& node, unsigned pos, Uint32 scanList)
+{
+ ScanOpPtr scanPtr;
+ scanPtr.i = scanList;
+ do {
+ jam();
+ c_scanOpPool.getPtr(scanPtr);
+#ifdef VM_TRACE
+ if (debugFlags & DebugScan) {
+ debugOut << "Add scan " << scanPtr.i << " " << *scanPtr.p << endl;
+ debugOut << "To pos=" << pos << " " << node << endl;
+ }
+#endif
+ const Uint32 nextPtrI = scanPtr.p->m_nodeScan;
+ scanPtr.p->m_nodeScan = RNIL;
+ linkScan(node, scanPtr);
+ TreePos& scanPos = scanPtr.p->m_scanPos;
+ // set position but leave direction alone
+ scanPos.m_loc = node.m_loc;
+ scanPos.m_pos = pos;
+ scanPtr.i = nextPtrI;
+ } while (scanPtr.i != RNIL);
+}
+
+/*
+ * Remove list of scans from node at given position. The return
+ * location must point to existing list (in fact RNIL always).
+ */
+void
+Dbtux::removeScanList(NodeHandle& node, unsigned pos, Uint32& scanList)
+{
+ ScanOpPtr scanPtr;
+ scanPtr.i = node.getNodeScan();
+ do {
+ jam();
+ c_scanOpPool.getPtr(scanPtr);
+ const Uint32 nextPtrI = scanPtr.p->m_nodeScan;
+ TreePos& scanPos = scanPtr.p->m_scanPos;
+ ndbrequire(scanPos.m_loc == node.m_loc);
+ if (scanPos.m_pos == pos) {
+ jam();
+#ifdef VM_TRACE
+ if (debugFlags & DebugScan) {
+ debugOut << "Remove scan " << scanPtr.i << " " << *scanPtr.p << endl;
+ debugOut << "Fron pos=" << pos << " " << node << endl;
+ }
+#endif
+ unlinkScan(node, scanPtr);
+ scanPtr.p->m_nodeScan = scanList;
+ scanList = scanPtr.i;
+ // unset position but leave direction alone
+ scanPos.m_loc = NullTupLoc;
+ scanPos.m_pos = ZNIL;
+ }
+ scanPtr.i = nextPtrI;
+ } while (scanPtr.i != RNIL);
+}
+
+/*
+ * Move list of scans away from entry about to be removed. Uses scan
+ * method scanNext().
+ */
+void
+Dbtux::moveScanList(NodeHandle& node, unsigned pos)
+{
+ ScanOpPtr scanPtr;
+ scanPtr.i = node.getNodeScan();
+ do {
+ jam();
+ c_scanOpPool.getPtr(scanPtr);
+ TreePos& scanPos = scanPtr.p->m_scanPos;
+ const Uint32 nextPtrI = scanPtr.p->m_nodeScan;
+ ndbrequire(scanPos.m_loc == node.m_loc);
+ if (scanPos.m_pos == pos) {
+ jam();
+#ifdef VM_TRACE
+ if (debugFlags & DebugScan) {
+ debugOut << "Move scan " << scanPtr.i << " " << *scanPtr.p << endl;
+ debugOut << "At pos=" << pos << " " << node << endl;
+ }
+#endif
+ scanNext(scanPtr);
+ ndbrequire(! (scanPos.m_loc == node.m_loc && scanPos.m_pos == pos));
+ }
+ scanPtr.i = nextPtrI;
+ } while (scanPtr.i != RNIL);
+}
+
/*
* Link scan to the list under the node. The list is single-linked and
* ordering does not matter.
diff --git a/ndb/src/kernel/blocks/dbtux/DbtuxScan.cpp b/ndb/src/kernel/blocks/dbtux/DbtuxScan.cpp
index 5b161d3c4ce..afde88c47a2 100644
--- a/ndb/src/kernel/blocks/dbtux/DbtuxScan.cpp
+++ b/ndb/src/kernel/blocks/dbtux/DbtuxScan.cpp
@@ -108,15 +108,23 @@ Dbtux::execACC_SCANREQ(Signal* signal)
/*
* Receive bounds for scan in single direct call. The bounds can arrive
* in any order. Attribute ids are those of index table.
+ *
+ * Replace EQ by equivalent LE + GE. Check for conflicting bounds.
+ * Check that sets of lower and upper bounds are on initial sequences of
+ * keys and that all but possibly last bound is non-strict.
+ *
+ * Finally save the sets of lower and upper bounds (i.e. start key and
+ * end key). Full bound type (< 4) is included but only the strict bit
+ * is used since lower and upper have now been separated.
*/
void
Dbtux::execTUX_BOUND_INFO(Signal* signal)
{
jamEntry();
struct BoundInfo {
+ int type;
unsigned offset;
unsigned size;
- int type;
};
TuxBoundInfo* const sig = (TuxBoundInfo*)signal->getDataPtrSend();
const TuxBoundInfo reqCopy = *(const TuxBoundInfo*)sig;
@@ -124,19 +132,12 @@ Dbtux::execTUX_BOUND_INFO(Signal* signal)
// get records
ScanOp& scan = *c_scanOpPool.getPtr(req->tuxScanPtrI);
Index& index = *c_indexPool.getPtr(scan.m_indexId);
- // collect bound info for each index attribute
- BoundInfo boundInfo[MaxIndexAttributes][2];
+ // collect lower and upper bounds
+ BoundInfo boundInfo[2][MaxIndexAttributes];
// largest attrId seen plus one
- Uint32 maxAttrId = 0;
- // skip 5 words
- if (req->boundAiLength < 5) {
- jam();
- scan.m_state = ScanOp::Invalid;
- sig->errorCode = TuxBoundInfo::InvalidAttrInfo;
- return;
- }
+ Uint32 maxAttrId[2] = { 0, 0 };
+ unsigned offset = 0;
const Uint32* const data = (Uint32*)sig + TuxBoundInfo::SignalLength;
- unsigned offset = 5;
// walk through entries
while (offset + 2 <= req->boundAiLength) {
jam();
@@ -156,32 +157,35 @@ Dbtux::execTUX_BOUND_INFO(Signal* signal)
sig->errorCode = TuxBoundInfo::InvalidAttrInfo;
return;
}
- while (maxAttrId <= attrId) {
- BoundInfo* b = boundInfo[maxAttrId++];
- b[0].type = b[1].type = -1;
- }
- BoundInfo* b = boundInfo[attrId];
- if (type == 0 || type == 1 || type == 4) {
- if (b[0].type != -1) {
- jam();
- scan.m_state = ScanOp::Invalid;
- sig->errorCode = TuxBoundInfo::InvalidBounds;
- return;
+ for (unsigned j = 0; j <= 1; j++) {
+ // check if lower/upper bit matches
+ const unsigned luBit = (j << 1);
+ if ((type & 0x2) != luBit && type != 4)
+ continue;
+ // EQ -> LE, GE
+ const unsigned type2 = (type & 0x1) | luBit;
+ // fill in any gap
+ while (maxAttrId[j] <= attrId) {
+ BoundInfo& b = boundInfo[j][maxAttrId[j]++];
+ b.type = -1;
}
- b[0].offset = offset;
- b[0].size = 2 + dataSize;
- b[0].type = type;
- }
- if (type == 2 || type == 3 || type == 4) {
- if (b[1].type != -1) {
- jam();
- scan.m_state = ScanOp::Invalid;
- sig->errorCode = TuxBoundInfo::InvalidBounds;
- return;
+ BoundInfo& b = boundInfo[j][attrId];
+ if (b.type != -1) {
+ // compare with previous bound
+ if (b.type != type2 ||
+ b.size != 2 + dataSize ||
+ memcmp(&data[b.offset + 2], &data[offset + 2], dataSize << 2) != 0) {
+ jam();
+ scan.m_state = ScanOp::Invalid;
+ sig->errorCode = TuxBoundInfo::InvalidBounds;
+ return;
+ }
+ } else {
+ // enter new bound
+ b.type = type2;
+ b.offset = offset;
+ b.size = 2 + dataSize;
}
- b[1].offset = offset;
- b[1].size = 2 + dataSize;
- b[1].type = type;
}
// jump to next
offset += 2 + dataSize;
@@ -192,34 +196,27 @@ Dbtux::execTUX_BOUND_INFO(Signal* signal)
sig->errorCode = TuxBoundInfo::InvalidAttrInfo;
return;
}
- // save the bounds in index attribute id order
- scan.m_boundCnt[0] = 0;
- scan.m_boundCnt[1] = 0;
- for (unsigned i = 0; i < maxAttrId; i++) {
- jam();
- const BoundInfo* b = boundInfo[i];
- // current limitation - check all but last is equality
- if (i + 1 < maxAttrId) {
- if (b[0].type != 4 || b[1].type != 4) {
+ for (unsigned j = 0; j <= 1; j++) {
+ // save lower/upper bound in index attribute id order
+ for (unsigned i = 0; i < maxAttrId[j]; i++) {
+ jam();
+ const BoundInfo& b = boundInfo[j][i];
+ // check for gap or strict bound before last
+ if (b.type == -1 || (i + 1 < maxAttrId[j] && (b.type & 0x1))) {
jam();
scan.m_state = ScanOp::Invalid;
sig->errorCode = TuxBoundInfo::InvalidBounds;
return;
}
- }
- for (unsigned j = 0; j <= 1; j++) {
- if (b[j].type != -1) {
+ bool ok = scan.m_bound[j]->append(&data[b.offset], b.size);
+ if (! ok) {
jam();
- bool ok = scan.m_bound[j]->append(&data[b[j].offset], b[j].size);
- if (! ok) {
- jam();
- scan.m_state = ScanOp::Invalid;
- sig->errorCode = TuxBoundInfo::OutOfBuffers;
- return;
- }
- scan.m_boundCnt[j]++;
+ scan.m_state = ScanOp::Invalid;
+ sig->errorCode = TuxBoundInfo::OutOfBuffers;
+ return;
}
}
+ scan.m_boundCnt[j] = maxAttrId[j];
}
// no error
sig->errorCode = 0;
@@ -278,7 +275,7 @@ Dbtux::execNEXT_SCANREQ(Signal* signal)
jam();
const TupLoc loc = scan.m_scanPos.m_loc;
NodeHandle node(frag);
- selectNode(signal, node, loc, AccHead);
+ selectNode(node, loc);
unlinkScan(node, scanPtr);
scan.m_scanPos.m_loc = NullTupLoc;
}
@@ -353,7 +350,7 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal)
if (scan.m_lockwait) {
jam();
// LQH asks if we are waiting for lock and we tell it to ask again
- const TreeEnt ent = scan.m_scanPos.m_ent;
+ const TreeEnt ent = scan.m_scanEnt;
NextScanConf* const conf = (NextScanConf*)signal->getDataPtrSend();
conf->scanPtr = scan.m_userPtr;
conf->accOperationPtr = RNIL; // no tuple returned
@@ -367,7 +364,7 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal)
if (scan.m_state == ScanOp::First) {
jam();
// search is done only once in single range scan
- scanFirst(signal, scanPtr);
+ scanFirst(scanPtr);
#ifdef VM_TRACE
if (debugFlags & DebugScan) {
debugOut << "First scan " << scanPtr.i << " " << scan << endl;
@@ -377,7 +374,7 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal)
if (scan.m_state == ScanOp::Next) {
jam();
// look for next
- scanNext(signal, scanPtr);
+ scanNext(scanPtr);
}
// for reading tuple key in Current or Locked state
Data pkData = c_dataBuffer;
@@ -388,7 +385,7 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal)
ndbrequire(scan.m_accLockOp == RNIL);
if (! scan.m_readCommitted) {
jam();
- const TreeEnt ent = scan.m_scanPos.m_ent;
+ const TreeEnt ent = scan.m_scanEnt;
// read tuple key
readTablePk(frag, ent, pkData, pkSize);
// get read lock or exclusive lock
@@ -476,7 +473,7 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal)
// we have lock or do not need one
jam();
// read keys if not already done (uses signal)
- const TreeEnt ent = scan.m_scanPos.m_ent;
+ const TreeEnt ent = scan.m_scanEnt;
if (scan.m_keyInfo) {
jam();
if (pkSize == 0) {
@@ -539,8 +536,6 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal)
total += length;
}
}
- // remember last entry returned
- scan.m_lastEnt = ent;
// next time look for next entry
scan.m_state = ScanOp::Next;
return;
@@ -685,7 +680,7 @@ Dbtux::execACC_ABORTCONF(Signal* signal)
* by scanNext.
*/
void
-Dbtux::scanFirst(Signal* signal, ScanOpPtr scanPtr)
+Dbtux::scanFirst(ScanOpPtr scanPtr)
{
ScanOp& scan = *scanPtr.p;
Frag& frag = *c_fragPool.getPtr(scan.m_fragPtrI);
@@ -703,7 +698,7 @@ Dbtux::scanFirst(Signal* signal, ScanOpPtr scanPtr)
}
// search for scan start position
TreePos treePos;
- searchToScan(signal, frag, c_dataBuffer, scan.m_boundCnt[0], treePos);
+ searchToScan(frag, c_dataBuffer, scan.m_boundCnt[0], treePos);
if (treePos.m_loc == NullTupLoc) {
// empty tree
jam();
@@ -715,23 +710,27 @@ Dbtux::scanFirst(Signal* signal, ScanOpPtr scanPtr)
scan.m_state = ScanOp::Next;
// link the scan to node found
NodeHandle node(frag);
- selectNode(signal, node, treePos.m_loc, AccFull);
+ selectNode(node, treePos.m_loc);
linkScan(node, scanPtr);
}
/*
* Move to next entry. The scan is already linked to some node. When
- * we leave, if any entry was found, it will be linked to a possibly
- * different node. The scan has a direction, one of:
+ * we leave, if an entry was found, it will be linked to a possibly
+ * different node. The scan has a position, and a direction which tells
+ * from where we came to this position. This is one of:
+ *
+ * 0 - up from left child (scan this node next)
+ * 1 - up from right child (proceed to parent)
+ * 2 - up from root (the scan ends)
+ * 3 - left to right within node (at end proceed to right child)
+ * 4 - down from parent (proceed to left child)
*
- * 0 - coming up from left child
- * 1 - coming up from right child (proceed to parent immediately)
- * 2 - coming up from root (the scan ends)
- * 3 - left to right within node
- * 4 - coming down from parent to left or right child
+ * If an entry was found, scan direction is 3. Therefore tree
+ * re-organizations need not worry about scan direction.
*/
void
-Dbtux::scanNext(Signal* signal, ScanOpPtr scanPtr)
+Dbtux::scanNext(ScanOpPtr scanPtr)
{
ScanOp& scan = *scanPtr.p;
Frag& frag = *c_fragPool.getPtr(scan.m_fragPtrI);
@@ -740,22 +739,8 @@ Dbtux::scanNext(Signal* signal, ScanOpPtr scanPtr)
debugOut << "Next in scan " << scanPtr.i << " " << scan << endl;
}
#endif
- if (scan.m_state == ScanOp::Locked) {
- jam();
- // version of a tuple locked by us cannot disappear (assert only)
-#ifdef dbtux_wl_1942_is_done
- ndbassert(false);
-#endif
- AccLockReq* const lockReq = (AccLockReq*)signal->getDataPtrSend();
- lockReq->returnCode = RNIL;
- lockReq->requestInfo = AccLockReq::Unlock;
- lockReq->accOpPtr = scan.m_accLockOp;
- EXECUTE_DIRECT(DBACC, GSN_ACC_LOCKREQ, signal, AccLockReq::UndoSignalLength);
- jamEntry();
- ndbrequire(lockReq->returnCode == AccLockReq::Success);
- scan.m_accLockOp = RNIL;
- scan.m_state = ScanOp::Current;
- }
+ // cannot be moved away from tuple we have locked
+ ndbrequire(scan.m_state != ScanOp::Locked);
// set up index keys for this operation
setKeyAttrs(frag);
// unpack upper bound into c_dataBuffer
@@ -771,10 +756,12 @@ Dbtux::scanNext(Signal* signal, ScanOpPtr scanPtr)
TreePos pos = scan.m_scanPos;
// get and remember original node
NodeHandle origNode(frag);
- selectNode(signal, origNode, pos.m_loc, AccHead);
+ selectNode(origNode, pos.m_loc);
ndbrequire(islinkScan(origNode, scanPtr));
// current node in loop
NodeHandle node = origNode;
+ // copy of entry found
+ TreeEnt ent;
while (true) {
jam();
if (pos.m_dir == 2) {
@@ -786,7 +773,7 @@ Dbtux::scanNext(Signal* signal, ScanOpPtr scanPtr)
}
if (node.m_loc != pos.m_loc) {
jam();
- selectNode(signal, node, pos.m_loc, AccHead);
+ selectNode(node, pos.m_loc);
}
if (pos.m_dir == 4) {
// coming down from parent proceed to left child
@@ -802,7 +789,7 @@ Dbtux::scanNext(Signal* signal, ScanOpPtr scanPtr)
pos.m_dir = 0;
}
if (pos.m_dir == 0) {
- // coming from left child scan current node
+ // coming up from left child scan current node
jam();
pos.m_pos = 0;
pos.m_match = false;
@@ -813,8 +800,6 @@ Dbtux::scanNext(Signal* signal, ScanOpPtr scanPtr)
jam();
unsigned occup = node.getOccup();
ndbrequire(occup >= 1);
- // access full node
- accessNode(signal, node, AccFull);
// advance position
if (! pos.m_match)
pos.m_match = true;
@@ -822,10 +807,10 @@ Dbtux::scanNext(Signal* signal, ScanOpPtr scanPtr)
pos.m_pos++;
if (pos.m_pos < occup) {
jam();
- pos.m_ent = node.getEnt(pos.m_pos);
+ ent = node.getEnt(pos.m_pos);
pos.m_dir = 3; // unchanged
// read and compare all attributes
- readKeyAttrs(frag, pos.m_ent, 0, c_entryKey);
+ readKeyAttrs(frag, ent, 0, c_entryKey);
int ret = cmpScanBound(frag, 1, c_dataBuffer, scan.m_boundCnt[1], c_entryKey);
ndbrequire(ret != NdbSqlUtil::CmpUnknown);
if (ret < 0) {
@@ -836,7 +821,7 @@ Dbtux::scanNext(Signal* signal, ScanOpPtr scanPtr)
break;
}
// can we see it
- if (! scanVisible(signal, scanPtr, pos.m_ent)) {
+ if (! scanVisible(scanPtr, ent)) {
jam();
continue;
}
@@ -856,7 +841,7 @@ Dbtux::scanNext(Signal* signal, ScanOpPtr scanPtr)
pos.m_dir = 1;
}
if (pos.m_dir == 1) {
- // coming from right child proceed to parent
+ // coming up from right child proceed to parent
jam();
pos.m_loc = node.getLink(2);
pos.m_dir = node.getSide();
@@ -868,12 +853,15 @@ Dbtux::scanNext(Signal* signal, ScanOpPtr scanPtr)
scan.m_scanPos = pos;
// relink
if (scan.m_state == ScanOp::Current) {
+ ndbrequire(pos.m_match == true && pos.m_dir == 3);
ndbrequire(pos.m_loc == node.m_loc);
if (origNode.m_loc != node.m_loc) {
jam();
unlinkScan(origNode, scanPtr);
linkScan(node, scanPtr);
}
+ // copy found entry
+ scan.m_scanEnt = ent;
} else if (scan.m_state == ScanOp::Last) {
jam();
ndbrequire(pos.m_loc == NullTupLoc);
@@ -891,12 +879,12 @@ Dbtux::scanNext(Signal* signal, ScanOpPtr scanPtr)
/*
* Check if an entry is visible to the scan.
*
- * There is a special check to never return same tuple twice in a row.
+ * There is a special check to never accept same tuple twice in a row.
* This is faster than asking TUP. It also fixes some special cases
* which are not analyzed or handled yet.
*/
bool
-Dbtux::scanVisible(Signal* signal, ScanOpPtr scanPtr, TreeEnt ent)
+Dbtux::scanVisible(ScanOpPtr scanPtr, TreeEnt ent)
{
const ScanOp& scan = *scanPtr.p;
const Frag& frag = *c_fragPool.getPtr(scan.m_fragPtrI);
@@ -906,8 +894,8 @@ Dbtux::scanVisible(Signal* signal, ScanOpPtr scanPtr, TreeEnt ent)
Uint32 tupAddr = getTupAddr(frag, ent);
Uint32 tupVersion = ent.m_tupVersion;
// check for same tuple twice in row
- if (scan.m_lastEnt.m_tupLoc == ent.m_tupLoc &&
- scan.m_lastEnt.m_fragBit == fragBit) {
+ if (scan.m_scanEnt.m_tupLoc == ent.m_tupLoc &&
+ scan.m_scanEnt.m_fragBit == fragBit) {
jam();
return false;
}
@@ -929,7 +917,7 @@ Dbtux::scanClose(Signal* signal, ScanOpPtr scanPtr)
ScanOp& scan = *scanPtr.p;
ndbrequire(! scan.m_lockwait && scan.m_accLockOp == RNIL);
// unlock all not unlocked by LQH
- for (unsigned i = 0; i < MaxAccLockOps; i++) {
+ for (unsigned i = 0; i < scan.m_maxAccLockOps; i++) {
if (scan.m_accLockOps[i] != RNIL) {
jam();
AccLockReq* const lockReq = (AccLockReq*)signal->getDataPtrSend();
@@ -959,7 +947,7 @@ Dbtux::addAccLockOp(ScanOp& scan, Uint32 accLockOp)
ndbrequire(accLockOp != RNIL);
Uint32* list = scan.m_accLockOps;
bool ok = false;
- for (unsigned i = 0; i < MaxAccLockOps; i++) {
+ for (unsigned i = 0; i < scan.m_maxAccLockOps; i++) {
ndbrequire(list[i] != accLockOp);
if (! ok && list[i] == RNIL) {
list[i] = accLockOp;
@@ -967,6 +955,14 @@ Dbtux::addAccLockOp(ScanOp& scan, Uint32 accLockOp)
// continue check for duplicates
}
}
+ if (! ok) {
+ unsigned i = scan.m_maxAccLockOps;
+ if (i < MaxAccLockOps) {
+ list[i] = accLockOp;
+ ok = true;
+ scan.m_maxAccLockOps = i + 1;
+ }
+ }
ndbrequire(ok);
}
@@ -976,7 +972,7 @@ Dbtux::removeAccLockOp(ScanOp& scan, Uint32 accLockOp)
ndbrequire(accLockOp != RNIL);
Uint32* list = scan.m_accLockOps;
bool ok = false;
- for (unsigned i = 0; i < MaxAccLockOps; i++) {
+ for (unsigned i = 0; i < scan.m_maxAccLockOps; i++) {
if (list[i] == accLockOp) {
list[i] = RNIL;
ok = true;
diff --git a/ndb/src/kernel/blocks/dbtux/DbtuxSearch.cpp b/ndb/src/kernel/blocks/dbtux/DbtuxSearch.cpp
index bffbb8f5594..7057d74c3ad 100644
--- a/ndb/src/kernel/blocks/dbtux/DbtuxSearch.cpp
+++ b/ndb/src/kernel/blocks/dbtux/DbtuxSearch.cpp
@@ -25,16 +25,17 @@
* TODO optimize for initial equal attrs in node min/max
*/
void
-Dbtux::searchToAdd(Signal* signal, Frag& frag, ConstData searchKey, TreeEnt searchEnt, TreePos& treePos)
+Dbtux::searchToAdd(Frag& frag, ConstData searchKey, TreeEnt searchEnt, TreePos& treePos)
{
const TreeHead& tree = frag.m_tree;
const unsigned numAttrs = frag.m_numAttrs;
NodeHandle currNode(frag);
currNode.m_loc = tree.m_root;
+ // assume success
+ treePos.m_match = false;
if (currNode.m_loc == NullTupLoc) {
// empty tree
jam();
- treePos.m_match = false;
return;
}
NodeHandle glbNode(frag); // potential g.l.b of final node
@@ -45,7 +46,7 @@ Dbtux::searchToAdd(Signal* signal, Frag& frag, ConstData searchKey, TreeEnt sear
NodeHandle bottomNode(frag);
while (true) {
jam();
- selectNode(signal, currNode, currNode.m_loc, AccPref);
+ selectNode(currNode, currNode.m_loc);
int ret;
// compare prefix
unsigned start = 0;
@@ -93,16 +94,22 @@ Dbtux::searchToAdd(Signal* signal, Frag& frag, ConstData searchKey, TreeEnt sear
jam();
treePos.m_loc = currNode.m_loc;
treePos.m_pos = 0;
+ // failed
treePos.m_match = true;
return;
}
break;
}
- // access rest of current node
- accessNode(signal, currNode, AccFull);
- for (unsigned j = 0, occup = currNode.getOccup(); j < occup; j++) {
+ // anticipate
+ treePos.m_loc = currNode.m_loc;
+ // binary search
+ int lo = -1;
+ unsigned hi = currNode.getOccup();
+ int ret;
+ while (1) {
jam();
- int ret;
+ // hi - lo > 1 implies lo < j < hi
+ int j = (hi + lo) / 2;
// read and compare attributes
unsigned start = 0;
readKeyAttrs(frag, currNode.getEnt(j), start, c_entryKey);
@@ -113,25 +120,38 @@ Dbtux::searchToAdd(Signal* signal, Frag& frag, ConstData searchKey, TreeEnt sear
// keys are equal, compare entry values
ret = searchEnt.cmp(currNode.getEnt(j));
}
- if (ret <= 0) {
- jam();
- treePos.m_loc = currNode.m_loc;
+ if (ret < 0)
+ hi = j;
+ else if (ret > 0)
+ lo = j;
+ else {
treePos.m_pos = j;
- treePos.m_match = (ret == 0);
+ // failed
+ treePos.m_match = true;
return;
}
+ if (hi - lo == 1)
+ break;
}
- if (! bottomNode.isNull()) {
+ if (ret < 0) {
jam();
- // backwards compatible for now
- treePos.m_loc = bottomNode.m_loc;
- treePos.m_pos = 0;
- treePos.m_match = false;
+ treePos.m_pos = hi;
return;
}
- treePos.m_loc = currNode.m_loc;
- treePos.m_pos = currNode.getOccup();
- treePos.m_match = false;
+ if (hi < currNode.getOccup()) {
+ jam();
+ treePos.m_pos = hi;
+ return;
+ }
+ if (bottomNode.isNull()) {
+ jam();
+ treePos.m_pos = hi;
+ return;
+ }
+ jam();
+ // backwards compatible for now
+ treePos.m_loc = bottomNode.m_loc;
+ treePos.m_pos = 0;
}
/*
@@ -139,27 +159,30 @@ Dbtux::searchToAdd(Signal* signal, Frag& frag, ConstData searchKey, TreeEnt sear
*
* Compares search key to each node min. A move to right subtree can
* overshoot target node. The last such node is saved. The final node
- * is a half-leaf or leaf. If search key is less than final node min
+ * is a semi-leaf or leaf. If search key is less than final node min
* then the saved node is the g.l.b of the final node and we move back
* to it.
*/
void
-Dbtux::searchToRemove(Signal* signal, Frag& frag, ConstData searchKey, TreeEnt searchEnt, TreePos& treePos)
+Dbtux::searchToRemove(Frag& frag, ConstData searchKey, TreeEnt searchEnt, TreePos& treePos)
{
const TreeHead& tree = frag.m_tree;
const unsigned numAttrs = frag.m_numAttrs;
NodeHandle currNode(frag);
currNode.m_loc = tree.m_root;
+ // assume success
+ treePos.m_match = true;
if (currNode.m_loc == NullTupLoc) {
// empty tree
jam();
+ // failed
treePos.m_match = false;
return;
}
NodeHandle glbNode(frag); // potential g.l.b of final node
while (true) {
jam();
- selectNode(signal, currNode, currNode.m_loc, AccPref);
+ selectNode(currNode, currNode.m_loc);
int ret;
// compare prefix
unsigned start = 0;
@@ -206,27 +229,24 @@ Dbtux::searchToRemove(Signal* signal, Frag& frag, ConstData searchKey, TreeEnt s
jam();
treePos.m_loc = currNode.m_loc;
treePos.m_pos = 0;
- treePos.m_match = true;
return;
}
break;
}
- // access rest of current node
- accessNode(signal, currNode, AccFull);
+ // anticipate
+ treePos.m_loc = currNode.m_loc;
// pos 0 was handled above
for (unsigned j = 1, occup = currNode.getOccup(); j < occup; j++) {
jam();
// compare only the entry
if (searchEnt.eq(currNode.getEnt(j))) {
jam();
- treePos.m_loc = currNode.m_loc;
treePos.m_pos = j;
- treePos.m_match = true;
return;
}
}
- treePos.m_loc = currNode.m_loc;
treePos.m_pos = currNode.getOccup();
+ // failed
treePos.m_match = false;
}
@@ -236,7 +256,7 @@ Dbtux::searchToRemove(Signal* signal, Frag& frag, ConstData searchKey, TreeEnt s
* Similar to searchToAdd.
*/
void
-Dbtux::searchToScan(Signal* signal, Frag& frag, ConstData boundInfo, unsigned boundCount, TreePos& treePos)
+Dbtux::searchToScan(Frag& frag, ConstData boundInfo, unsigned boundCount, TreePos& treePos)
{
const TreeHead& tree = frag.m_tree;
NodeHandle currNode(frag);
@@ -251,7 +271,7 @@ Dbtux::searchToScan(Signal* signal, Frag& frag, ConstData boundInfo, unsigned bo
NodeHandle bottomNode(frag);
while (true) {
jam();
- selectNode(signal, currNode, currNode.m_loc, AccPref);
+ selectNode(currNode, currNode.m_loc);
int ret;
// compare prefix
ret = cmpScanBound(frag, 0, boundInfo, boundCount, currNode.getPref(), tree.m_prefSize);
@@ -300,8 +320,6 @@ Dbtux::searchToScan(Signal* signal, Frag& frag, ConstData boundInfo, unsigned bo
}
break;
}
- // access rest of current node
- accessNode(signal, currNode, AccFull);
for (unsigned j = 0, occup = currNode.getOccup(); j < occup; j++) {
jam();
int ret;
diff --git a/ndb/src/kernel/blocks/dbtux/DbtuxTree.cpp b/ndb/src/kernel/blocks/dbtux/DbtuxTree.cpp
index 3baa62998db..b9e3b593a00 100644
--- a/ndb/src/kernel/blocks/dbtux/DbtuxTree.cpp
+++ b/ndb/src/kernel/blocks/dbtux/DbtuxTree.cpp
@@ -18,74 +18,105 @@
#include "Dbtux.hpp"
/*
- * Add entry.
+ * Add entry. Handle the case when there is room for one more. This
+ * is the common case given slack in nodes.
*/
void
-Dbtux::treeAdd(Signal* signal, Frag& frag, TreePos treePos, TreeEnt ent)
+Dbtux::treeAdd(Frag& frag, TreePos treePos, TreeEnt ent)
{
TreeHead& tree = frag.m_tree;
- unsigned pos = treePos.m_pos;
NodeHandle node(frag);
- // check for empty tree
- if (treePos.m_loc == NullTupLoc) {
- jam();
- insertNode(signal, node, AccPref);
- nodePushUp(signal, node, 0, ent);
- node.setSide(2);
- tree.m_root = node.m_loc;
- return;
- }
- // access full node
- selectNode(signal, node, treePos.m_loc, AccFull);
- // check if it is bounding node
- if (pos != 0 && pos != node.getOccup()) {
+ if (treePos.m_loc != NullTupLoc) {
+ // non-empty tree
jam();
- // check if room for one more
+ selectNode(node, treePos.m_loc);
+ unsigned pos = treePos.m_pos;
if (node.getOccup() < tree.m_maxOccup) {
+ // node has room
jam();
- nodePushUp(signal, node, pos, ent);
+ nodePushUp(node, pos, ent, RNIL);
return;
}
- // returns min entry
- nodePushDown(signal, node, pos - 1, ent);
- // find position to add the removed min entry
- TupLoc childLoc = node.getLink(0);
- if (childLoc == NullTupLoc) {
+ treeAddFull(frag, node, pos, ent);
+ return;
+ }
+ jam();
+ insertNode(node);
+ nodePushUp(node, 0, ent, RNIL);
+ node.setSide(2);
+ tree.m_root = node.m_loc;
+}
+
+/*
+ * Add entry when node is full. Handle the case when there is g.l.b
+ * node in left subtree with room for one more. It will receive the min
+ * entry of this node. The min entry could be the entry to add.
+ */
+void
+Dbtux::treeAddFull(Frag& frag, NodeHandle lubNode, unsigned pos, TreeEnt ent)
+{
+ TreeHead& tree = frag.m_tree;
+ TupLoc loc = lubNode.getLink(0);
+ if (loc != NullTupLoc) {
+ // find g.l.b node
+ NodeHandle glbNode(frag);
+ do {
jam();
- // left child will be added
- pos = 0;
- } else {
+ selectNode(glbNode, loc);
+ loc = glbNode.getLink(1);
+ } while (loc != NullTupLoc);
+ if (glbNode.getOccup() < tree.m_maxOccup) {
+ // g.l.b node has room
jam();
- // find glb node
- while (childLoc != NullTupLoc) {
+ Uint32 scanList = RNIL;
+ if (pos != 0) {
jam();
- selectNode(signal, node, childLoc, AccHead);
- childLoc = node.getLink(1);
+ // add the new entry and return min entry
+ nodePushDown(lubNode, pos - 1, ent, scanList);
}
- // access full node again
- accessNode(signal, node, AccFull);
- pos = node.getOccup();
+ // g.l.b node receives min entry from l.u.b node
+ nodePushUp(glbNode, glbNode.getOccup(), ent, scanList);
+ return;
}
- // fall thru to next case
- }
- // adding new min or max
- unsigned i = (pos == 0 ? 0 : 1);
- ndbrequire(node.getLink(i) == NullTupLoc);
- // check if the half-leaf/leaf has room for one more
- if (node.getOccup() < tree.m_maxOccup) {
- jam();
- nodePushUp(signal, node, pos, ent);
+ treeAddNode(frag, lubNode, pos, ent, glbNode, 1);
return;
}
- // add a new node
- NodeHandle childNode(frag);
- insertNode(signal, childNode, AccPref);
- nodePushUp(signal, childNode, 0, ent);
+ treeAddNode(frag, lubNode, pos, ent, lubNode, 0);
+}
+
+/*
+ * Add entry when there is no g.l.b node in left subtree or the g.l.b
+ * node is full. We must add a new left or right child node which
+ * becomes the new g.l.b node.
+ */
+void
+Dbtux::treeAddNode(Frag& frag, NodeHandle lubNode, unsigned pos, TreeEnt ent, NodeHandle parentNode, unsigned i)
+{
+ NodeHandle glbNode(frag);
+ insertNode(glbNode);
// connect parent and child
- node.setLink(i, childNode.m_loc);
- childNode.setLink(2, node.m_loc);
- childNode.setSide(i);
- // re-balance tree at each node
+ parentNode.setLink(i, glbNode.m_loc);
+ glbNode.setLink(2, parentNode.m_loc);
+ glbNode.setSide(i);
+ Uint32 scanList = RNIL;
+ if (pos != 0) {
+ jam();
+ // add the new entry and return min entry
+ nodePushDown(lubNode, pos - 1, ent, scanList);
+ }
+ // g.l.b node receives min entry from l.u.b node
+ nodePushUp(glbNode, 0, ent, scanList);
+ // re-balance the tree
+ treeAddRebalance(frag, parentNode, i);
+}
+
+/*
+ * Re-balance tree after adding a node. The process starts with the
+ * parent of the added node.
+ */
+void
+Dbtux::treeAddRebalance(Frag& frag, NodeHandle node, unsigned i)
+{
while (true) {
// height of subtree i has increased by 1
int j = (i == 0 ? -1 : +1);
@@ -105,14 +136,14 @@ Dbtux::treeAdd(Signal* signal, Frag& frag, TreePos treePos, TreeEnt ent)
// height of longer subtree increased
jam();
NodeHandle childNode(frag);
- selectNode(signal, childNode, node.getLink(i), AccHead);
+ selectNode(childNode, node.getLink(i));
int b2 = childNode.getBalance();
if (b2 == b) {
jam();
- treeRotateSingle(signal, frag, node, i);
+ treeRotateSingle(frag, node, i);
} else if (b2 == -b) {
jam();
- treeRotateDouble(signal, frag, node, i);
+ treeRotateDouble(frag, node, i);
} else {
// height of subtree increased so it cannot be perfectly balanced
ndbrequire(false);
@@ -129,118 +160,169 @@ Dbtux::treeAdd(Signal* signal, Frag& frag, TreePos treePos, TreeEnt ent)
break;
}
i = node.getSide();
- selectNode(signal, node, parentLoc, AccHead);
+ selectNode(node, parentLoc);
}
}
/*
- * Remove entry.
+ * Remove entry. Optimize for nodes with slack. Handle the case when
+ * there is no underflow i.e. occupancy remains at least minOccup. For
+ * interior nodes this is a requirement. For others it means that we do
+ * not need to consider merge of semi-leaf and leaf.
*/
void
-Dbtux::treeRemove(Signal* signal, Frag& frag, TreePos treePos)
+Dbtux::treeRemove(Frag& frag, TreePos treePos)
{
TreeHead& tree = frag.m_tree;
unsigned pos = treePos.m_pos;
NodeHandle node(frag);
- // access full node
- selectNode(signal, node, treePos.m_loc, AccFull);
+ selectNode(node, treePos.m_loc);
TreeEnt ent;
- // check interior node first
- if (node.getChilds() == 2) {
+ if (node.getOccup() > tree.m_minOccup) {
+ // no underflow in any node type
jam();
- ndbrequire(node.getOccup() >= tree.m_minOccup);
- // check if no underflow
- if (node.getOccup() > tree.m_minOccup) {
- jam();
- nodePopDown(signal, node, pos, ent);
- return;
- }
- // save current handle
- NodeHandle parentNode = node;
- // find glb node
- TupLoc childLoc = node.getLink(0);
- while (childLoc != NullTupLoc) {
- jam();
- selectNode(signal, node, childLoc, AccHead);
- childLoc = node.getLink(1);
- }
- // access full node again
- accessNode(signal, node, AccFull);
- // use glb max as new parent min
- ent = node.getEnt(node.getOccup() - 1);
- nodePopUp(signal, parentNode, pos, ent);
- // set up to remove glb max
- pos = node.getOccup() - 1;
- // fall thru to next case
+ nodePopDown(node, pos, ent, 0);
+ return;
}
- // remove the element
- nodePopDown(signal, node, pos, ent);
- ndbrequire(node.getChilds() <= 1);
- // handle half-leaf
- unsigned i;
- for (i = 0; i <= 1; i++) {
+ if (node.getChilds() == 2) {
+ // underflow in interior node
jam();
- TupLoc childLoc = node.getLink(i);
- if (childLoc != NullTupLoc) {
- // move to child
- selectNode(signal, node, childLoc, AccFull);
- // balance of half-leaf parent requires child to be leaf
- break;
- }
+ treeRemoveInner(frag, node, pos);
+ return;
}
- ndbrequire(node.getChilds() == 0);
- // get parent if any
- TupLoc parentLoc = node.getLink(2);
- NodeHandle parentNode(frag);
- i = node.getSide();
- // move all that fits into parent
- if (parentLoc != NullTupLoc) {
+ // remove entry in semi/leaf
+ nodePopDown(node, pos, ent, 0);
+ if (node.getLink(0) != NullTupLoc) {
jam();
- selectNode(signal, parentNode, node.getLink(2), AccFull);
- nodeSlide(signal, parentNode, node, i);
- // fall thru to next case
+ treeRemoveSemi(frag, node, 0);
+ return;
}
- // non-empty leaf
- if (node.getOccup() >= 1) {
+ if (node.getLink(1) != NullTupLoc) {
jam();
+ treeRemoveSemi(frag, node, 1);
return;
}
- // remove empty leaf
- deleteNode(signal, node);
- if (parentLoc == NullTupLoc) {
+ treeRemoveLeaf(frag, node);
+}
+
+/*
+ * Remove entry when interior node underflows. There is g.l.b node in
+ * left subtree to borrow an entry from. The max entry of the g.l.b
+ * node becomes the min entry of this node.
+ */
+void
+Dbtux::treeRemoveInner(Frag& frag, NodeHandle lubNode, unsigned pos)
+{
+ TreeHead& tree = frag.m_tree;
+ TreeEnt ent;
+ // find g.l.b node
+ NodeHandle glbNode(frag);
+ TupLoc loc = lubNode.getLink(0);
+ do {
+ jam();
+ selectNode(glbNode, loc);
+ loc = glbNode.getLink(1);
+ } while (loc != NullTupLoc);
+ // borrow max entry from semi/leaf
+ Uint32 scanList = RNIL;
+ nodePopDown(glbNode, glbNode.getOccup() - 1, ent, &scanList);
+ nodePopUp(lubNode, pos, ent, scanList);
+ if (glbNode.getLink(0) != NullTupLoc) {
jam();
- // tree is now empty
- tree.m_root = NullTupLoc;
+ treeRemoveSemi(frag, glbNode, 0);
return;
}
- node = parentNode;
- node.setLink(i, NullTupLoc);
-#ifdef dbtux_min_occup_less_max_occup
- // check if we created a half-leaf
- if (node.getBalance() == 0) {
+ treeRemoveLeaf(frag, glbNode);
+}
+
+/*
+ * Handle semi-leaf after removing an entry. Move entries from leaf to
+ * semi-leaf to bring semi-leaf occupancy above minOccup, if possible.
+ * The leaf may become empty.
+ */
+void
+Dbtux::treeRemoveSemi(Frag& frag, NodeHandle semiNode, unsigned i)
+{
+ TreeHead& tree = frag.m_tree;
+ ndbrequire(semiNode.getChilds() < 2);
+ TupLoc leafLoc = semiNode.getLink(i);
+ NodeHandle leafNode(frag);
+ selectNode(leafNode, leafLoc);
+ if (semiNode.getOccup() < tree.m_minOccup) {
+ jam();
+ unsigned cnt = min(leafNode.getOccup(), tree.m_minOccup - semiNode.getOccup());
+ nodeSlide(semiNode, leafNode, cnt, i);
+ if (leafNode.getOccup() == 0) {
+ // remove empty leaf
+ jam();
+ treeRemoveNode(frag, leafNode);
+ }
+ }
+}
+
+/*
+ * Handle leaf after removing an entry. If parent is semi-leaf, move
+ * entries to it as in the semi-leaf case. If parent is interior node,
+ * do nothing.
+ */
+void
+Dbtux::treeRemoveLeaf(Frag& frag, NodeHandle leafNode)
+{
+ TreeHead& tree = frag.m_tree;
+ TupLoc parentLoc = leafNode.getLink(2);
+ if (parentLoc != NullTupLoc) {
jam();
- // move entries from the other child
- TupLoc childLoc = node.getLink(1 - i);
- NodeHandle childNode(frag);
- selectNode(signal, childNode, childLoc, AccFull);
- nodeSlide(signal, node, childNode, 1 - i);
- if (childNode.getOccup() == 0) {
+ NodeHandle parentNode(frag);
+ selectNode(parentNode, parentLoc);
+ unsigned i = leafNode.getSide();
+ if (parentNode.getLink(1 - i) == NullTupLoc) {
+ // parent is semi-leaf
jam();
- deleteNode(signal, childNode);
- node.setLink(1 - i, NullTupLoc);
- // we are balanced again but our parent balance changes by -1
- parentLoc = node.getLink(2);
- if (parentLoc == NullTupLoc) {
+ if (parentNode.getOccup() < tree.m_minOccup) {
jam();
- return;
+ unsigned cnt = min(leafNode.getOccup(), tree.m_minOccup - parentNode.getOccup());
+ nodeSlide(parentNode, leafNode, cnt, i);
}
- // fix side and become parent
- i = node.getSide();
- selectNode(signal, node, parentLoc, AccHead);
}
}
-#endif
- // re-balance tree at each node
+ if (leafNode.getOccup() == 0) {
+ jam();
+ // remove empty leaf
+ treeRemoveNode(frag, leafNode);
+ }
+}
+
+/*
+ * Remove empty leaf.
+ */
+void
+Dbtux::treeRemoveNode(Frag& frag, NodeHandle leafNode)
+{
+ TreeHead& tree = frag.m_tree;
+ ndbrequire(leafNode.getChilds() == 0);
+ TupLoc parentLoc = leafNode.getLink(2);
+ unsigned i = leafNode.getSide();
+ deleteNode(leafNode);
+ if (parentLoc != NullTupLoc) {
+ jam();
+ NodeHandle parentNode(frag);
+ selectNode(parentNode, parentLoc);
+ parentNode.setLink(i, NullTupLoc);
+ // re-balance the tree
+ treeRemoveRebalance(frag, parentNode, i);
+ return;
+ }
+ // tree is now empty
+ tree.m_root = NullTupLoc;
+}
+
+/*
+ * Re-balance tree after removing a node. The process starts with the
+ * parent of the removed node.
+ */
+void
+Dbtux::treeRemoveRebalance(Frag& frag, NodeHandle node, unsigned i)
+{
while (true) {
// height of subtree i has decreased by 1
int j = (i == 0 ? -1 : +1);
@@ -261,19 +343,19 @@ Dbtux::treeRemove(Signal* signal, Frag& frag, TreePos treePos)
jam();
// child on the other side
NodeHandle childNode(frag);
- selectNode(signal, childNode, node.getLink(1 - i), AccHead);
+ selectNode(childNode, node.getLink(1 - i));
int b2 = childNode.getBalance();
if (b2 == b) {
jam();
- treeRotateSingle(signal, frag, node, 1 - i);
+ treeRotateSingle(frag, node, 1 - i);
// height of tree decreased and propagates up
} else if (b2 == -b) {
jam();
- treeRotateDouble(signal, frag, node, 1 - i);
+ treeRotateDouble(frag, node, 1 - i);
// height of tree decreased and propagates up
} else {
jam();
- treeRotateSingle(signal, frag, node, 1 - i);
+ treeRotateSingle(frag, node, 1 - i);
// height of tree did not change - done
return;
}
@@ -287,7 +369,7 @@ Dbtux::treeRemove(Signal* signal, Frag& frag, TreePos treePos)
return;
}
i = node.getSide();
- selectNode(signal, node, parentLoc, AccHead);
+ selectNode(node, parentLoc);
}
}
@@ -308,10 +390,7 @@ Dbtux::treeRemove(Signal* signal, Frag& frag, TreePos treePos)
* all optional. If 4 are there it changes side.
*/
void
-Dbtux::treeRotateSingle(Signal* signal,
- Frag& frag,
- NodeHandle& node,
- unsigned i)
+Dbtux::treeRotateSingle(Frag& frag, NodeHandle& node, unsigned i)
{
ndbrequire(i <= 1);
/*
@@ -331,7 +410,7 @@ Dbtux::treeRotateSingle(Signal* signal,
*/
TupLoc loc3 = node5.getLink(i);
NodeHandle node3(frag);
- selectNode(signal, node3, loc3, AccHead);
+ selectNode(node3, loc3);
const int bal3 = node3.getBalance();
/*
2 must always be there but is not changed. Thus we mereley check that it
@@ -348,7 +427,7 @@ Dbtux::treeRotateSingle(Signal* signal,
NodeHandle node4(frag);
if (loc4 != NullTupLoc) {
jam();
- selectNode(signal, node4, loc4, AccHead);
+ selectNode(node4, loc4);
ndbrequire(node4.getSide() == (1 - i) &&
node4.getLink(2) == loc3);
node4.setSide(i);
@@ -383,7 +462,7 @@ Dbtux::treeRotateSingle(Signal* signal,
if (loc0 != NullTupLoc) {
jam();
NodeHandle node0(frag);
- selectNode(signal, node0, loc0, AccHead);
+ selectNode(node0, loc0);
node0.setLink(side5, loc3);
} else {
jam();
@@ -520,8 +599,10 @@ Dbtux::treeRotateSingle(Signal* signal,
*
*/
void
-Dbtux::treeRotateDouble(Signal* signal, Frag& frag, NodeHandle& node, unsigned i)
+Dbtux::treeRotateDouble(Frag& frag, NodeHandle& node, unsigned i)
{
+ TreeHead& tree = frag.m_tree;
+
// old top node
NodeHandle node6 = node;
const TupLoc loc6 = node6.m_loc;
@@ -532,13 +613,13 @@ Dbtux::treeRotateDouble(Signal* signal, Frag& frag, NodeHandle& node, unsigned i
// level 1
TupLoc loc2 = node6.getLink(i);
NodeHandle node2(frag);
- selectNode(signal, node2, loc2, AccHead);
+ selectNode(node2, loc2);
const int bal2 = node2.getBalance();
// level 2
TupLoc loc4 = node2.getLink(1 - i);
NodeHandle node4(frag);
- selectNode(signal, node4, loc4, AccHead);
+ selectNode(node4, loc4);
const int bal4 = node4.getBalance();
ndbrequire(i <= 1);
@@ -555,25 +636,26 @@ Dbtux::treeRotateDouble(Signal* signal, Frag& frag, NodeHandle& node, unsigned i
// fill up leaf before it becomes internal
if (loc3 == NullTupLoc && loc5 == NullTupLoc) {
jam();
- TreeHead& tree = frag.m_tree;
- accessNode(signal, node2, AccFull);
- accessNode(signal, node4, AccFull);
- nodeSlide(signal, node4, node2, i);
- // implied by rule of merging half-leaves with leaves
- ndbrequire(node4.getOccup() >= tree.m_minOccup);
- ndbrequire(node2.getOccup() != 0);
+ if (node4.getOccup() < tree.m_minOccup) {
+ jam();
+ unsigned cnt = tree.m_minOccup - node4.getOccup();
+ ndbrequire(cnt < node2.getOccup());
+ nodeSlide(node4, node2, cnt, i);
+ ndbrequire(node4.getOccup() >= tree.m_minOccup);
+ ndbrequire(node2.getOccup() != 0);
+ }
} else {
if (loc3 != NullTupLoc) {
jam();
NodeHandle node3(frag);
- selectNode(signal, node3, loc3, AccHead);
+ selectNode(node3, loc3);
node3.setLink(2, loc2);
node3.setSide(1 - i);
}
if (loc5 != NullTupLoc) {
jam();
NodeHandle node5(frag);
- selectNode(signal, node5, loc5, AccHead);
+ selectNode(node5, loc5);
node5.setLink(2, node6.m_loc);
node5.setSide(i);
}
@@ -596,7 +678,7 @@ Dbtux::treeRotateDouble(Signal* signal, Frag& frag, NodeHandle& node, unsigned i
if (loc0 != NullTupLoc) {
jam();
- selectNode(signal, node0, loc0, AccHead);
+ selectNode(node0, loc0);
node0.setLink(side6, loc4);
} else {
jam();
diff --git a/ndb/src/kernel/blocks/dbtux/Times.txt b/ndb/src/kernel/blocks/dbtux/Times.txt
index 03473353a52..1e6d0a0a329 100644
--- a/ndb/src/kernel/blocks/dbtux/Times.txt
+++ b/ndb/src/kernel/blocks/dbtux/Times.txt
@@ -13,7 +13,7 @@ case c: full scan: index on PK Unsigned
testOIBasic -case v -table 1 -index 1 -fragtype small -threads 10 -rows 100000 -subloop 1 -nologging
case d: scan 1 tuple via EQ: index on PK Unsigned
-testOIBasic -case w -table 1 -index 1 -fragtype small -threads 10 -rows 100000 -samples 10000 -subloop 1 -nologging -v2
+testOIBasic -case w -table 1 -index 1 -fragtype small -threads 10 -rows 100000 -samples 50000 -subloop 1 -nologging -v2
a, b
1 million rows, pk update without index, pk update with index
@@ -29,6 +29,7 @@ shows ms / 1000 rows for each and index time overhead
samples 10% of all PKs (100,000 pk reads, 100,000 scans)
the "pct" values are from more accurate total times (not shown)
+comments [ ... ] are after the case
040616 mc02/a 40 ms 87 ms 114 pct
mc02/b 51 ms 128 ms 148 pct
@@ -76,13 +77,12 @@ optim 13 mc02/a 40 ms 57 ms 42 pct
mc02/c 9 ms 13 ms 50 pct
mc02/d 170 ms 256 ms 50 pct
-after wl-1884 store all-NULL keys (the tests have pctnull=10 per column)
-
optim 13 mc02/a 39 ms 59 ms 50 pct
mc02/b 47 ms 77 ms 61 pct
mc02/c 9 ms 12 ms 44 pct
mc02/d 246 ms 289 ms 17 pct
+[ after wl-1884 store all-NULL keys (the tests have pctnull=10 per column) ]
[ case d: bug in testOIBasic killed PK read performance ]
optim 14 mc02/a 41 ms 60 ms 44 pct
@@ -98,8 +98,7 @@ none mc02/a 35 ms 60 ms 71 pct
mc02/c 5 ms 12 ms 106 pct
mc02/d 165 ms 238 ms 44 pct
-[ johan re-installed mc02 as fedora gcc-3.3.2 ]
-[ case c: table scan has improved... ]
+[ johan re-installed mc02 as fedora gcc-3.3.2, tux uses more C++ stuff than tup]
charsets mc02/a 35 ms 60 ms 71 pct
mc02/b 42 ms 84 ms 97 pct
@@ -108,4 +107,37 @@ charsets mc02/a 35 ms 60 ms 71 pct
[ case b: TUX can no longer use pointers to TUP data ]
+optim 15 mc02/a 34 ms 60 ms 72 pct
+ mc02/b 42 ms 85 ms 100 pct
+ mc02/c 5 ms 12 ms 110 pct
+ mc02/d 178 ms 242 ms 35 pct
+
+[ corrected wasted space in index node ]
+
+optim 16 mc02/a 34 ms 53 ms 53 pct
+ mc02/b 42 ms 75 ms 75 pct
+
+[ binary search of bounding node when adding entry ]
+
+none mc02/a 35 ms 53 ms 51 pct
+ mc02/b 42 ms 75 ms 76 pct
+
+[ rewrote treeAdd / treeRemove ]
+
+optim 17 mc02/a 35 ms 52 ms 49 pct
+ mc02/b 43 ms 75 ms 75 pct
+
+[ allow slack (2) in interior nodes - almost no effect?? ]
+
+wl-1942 mc02/a 35 ms 52 ms 49 pct
+ mc02/b 42 ms 75 ms 76 pct
+
+before mc02/c 5 ms 13 ms 126 pct
+ mc02/d 134 ms 238 ms 78 pct
+
+after mc02/c 5 ms 10 ms 70 pct
+ mc02/d 178 ms 242 ms 69 pct
+
+[ prelim preformance fix for max batch size 16 -> 992 ]
+
vim: set et:
diff --git a/ndb/src/kernel/blocks/dbutil/DbUtil.cpp b/ndb/src/kernel/blocks/dbutil/DbUtil.cpp
index 554fc693fb8..f5379689a5f 100644
--- a/ndb/src/kernel/blocks/dbutil/DbUtil.cpp
+++ b/ndb/src/kernel/blocks/dbutil/DbUtil.cpp
@@ -1059,6 +1059,7 @@ DbUtil::prepareOperation(Signal* signal, PreparePtr prepPtr)
ndbrequire(prepPagesReader.getValueLen() <= MAX_ATTR_NAME_SIZE);
prepPagesReader.getString(attrNameRequested);
+ attrIdRequested= ~0u;
} else {
jam();
attrIdRequested = prepPagesReader.getUint32();
diff --git a/ndb/src/kernel/blocks/ndbcntr/NdbcntrInit.cpp b/ndb/src/kernel/blocks/ndbcntr/NdbcntrInit.cpp
index 1069cf93b06..43044eeebcd 100644
--- a/ndb/src/kernel/blocks/ndbcntr/NdbcntrInit.cpp
+++ b/ndb/src/kernel/blocks/ndbcntr/NdbcntrInit.cpp
@@ -37,10 +37,10 @@ void Ndbcntr::initRecords()
Ndbcntr::Ndbcntr(const class Configuration & conf):
SimulatedBlock(NDBCNTR, conf),
- c_stopRec(* this),
- c_missra(* this),
cnoWaitrep6(0),
- cnoWaitrep7(0)
+ cnoWaitrep7(0),
+ c_stopRec(* this),
+ c_missra(* this)
{
BLOCK_CONSTRUCTOR(Ndbcntr);
diff --git a/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp b/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp
index 568ed6c6566..089cf613b03 100644
--- a/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp
+++ b/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp
@@ -135,42 +135,42 @@ void Ndbcntr::execSYSTEM_ERROR(Signal* signal)
jamEntry();
switch (sysErr->errorCode){
case SystemError::StartInProgressError:
- snprintf(buf, sizeof(buf),
+ BaseString::snprintf(buf, sizeof(buf),
"Node %d killed this node because "
"master start in progress error",
killingNode);
break;
case SystemError::GCPStopDetected:
- snprintf(buf, sizeof(buf),
+ BaseString::snprintf(buf, sizeof(buf),
"Node %d killed this node because "
"GCP stop was detected",
killingNode);
break;
case SystemError::ScanfragTimeout:
- snprintf(buf, sizeof(buf),
+ BaseString::snprintf(buf, sizeof(buf),
"Node %d killed this node because "
"a fragment scan timed out and could not be stopped",
killingNode);
break;
case SystemError::ScanfragStateError:
- snprintf(buf, sizeof(buf),
+ BaseString::snprintf(buf, sizeof(buf),
"Node %d killed this node because "
"the state of a fragment scan was out of sync.",
killingNode);
break;
case SystemError::CopyFragRefError:
- snprintf(buf, sizeof(buf),
+ BaseString::snprintf(buf, sizeof(buf),
"Node %d killed this node because "
"it could not copy a fragment during node restart",
killingNode);
break;
default:
- snprintf(buf, sizeof(buf), "System error %d, "
+ BaseString::snprintf(buf, sizeof(buf), "System error %d, "
" this node was killed by node %d",
sysErr->errorCode, killingNode);
break;
diff --git a/ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp b/ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp
index c61fccad22a..a02bfd459b3 100644
--- a/ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp
+++ b/ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp
@@ -119,7 +119,7 @@ AsyncFile::doStart(Uint32 nodeId,
char buf[16];
numAsyncFiles++;
- snprintf(buf, sizeof(buf), "AsyncFile%d", numAsyncFiles);
+ BaseString::snprintf(buf, sizeof(buf), "AsyncFile%d", numAsyncFiles);
theStartMutexPtr = NdbMutex_Create();
theStartConditionPtr = NdbCondition_Create();
@@ -816,7 +816,7 @@ AsyncFile::rmrfReq(Request * request, char * path, bool removePath){
struct dirent * dp;
while ((dp = readdir(dirp)) != NULL){
if ((strcmp(".", dp->d_name) != 0) && (strcmp("..", dp->d_name) != 0)) {
- snprintf(path_add, (size_t)path_max_copy, "%s%s",
+ BaseString::snprintf(path_add, (size_t)path_max_copy, "%s%s",
DIR_SEPARATOR, dp->d_name);
if(remove((const char*)path) == 0){
path[path_len] = 0;
diff --git a/ndb/src/kernel/blocks/ndbfs/Filename.cpp b/ndb/src/kernel/blocks/ndbfs/Filename.cpp
index 28aa1d23df4..15158ec19ef 100644
--- a/ndb/src/kernel/blocks/ndbfs/Filename.cpp
+++ b/ndb/src/kernel/blocks/ndbfs/Filename.cpp
@@ -56,7 +56,7 @@ Filename::init(Uint32 nodeid,
return;
}
- snprintf(theFileSystemDirectory, sizeof(theFileSystemDirectory),
+ BaseString::snprintf(theFileSystemDirectory, sizeof(theFileSystemDirectory),
"%sndb_%u_fs%s", pFileSystemPath, nodeid, DIR_SEPARATOR);
strncpy(theBackupDirectory, pBackupDirPath, sizeof(theBackupDirectory));
@@ -101,7 +101,7 @@ Filename::set(BlockReference blockReference,
const Uint32 P_val = FsOpenReq::v1_getP(filenumber);
if (diskNo < 0xff){
- snprintf(buf, sizeof(buf), "D%d%s", diskNo, DIR_SEPARATOR);
+ BaseString::snprintf(buf, sizeof(buf), "D%d%s", diskNo, DIR_SEPARATOR);
strcat(theName, buf);
theLevelDepth++;
}
@@ -112,31 +112,31 @@ Filename::set(BlockReference blockReference,
ERROR_SET(ecError, AFS_ERROR_PARAMETER,"","No Block Name");
return;
}
- snprintf(buf, sizeof(buf), "%s%s", blockName, DIR_SEPARATOR);
+ BaseString::snprintf(buf, sizeof(buf), "%s%s", blockName, DIR_SEPARATOR);
strcat(theName, buf);
theLevelDepth++;
}
if (table < 0xffffffff){
- snprintf(buf, sizeof(buf), "T%d%s", table, DIR_SEPARATOR);
+ BaseString::snprintf(buf, sizeof(buf), "T%d%s", table, DIR_SEPARATOR);
strcat(theName, buf);
theLevelDepth++;
}
if (frag < 0xffffffff){
- snprintf(buf, sizeof(buf), "F%d%s", frag, DIR_SEPARATOR);
+ BaseString::snprintf(buf, sizeof(buf), "F%d%s", frag, DIR_SEPARATOR);
strcat(theName, buf);
theLevelDepth++;
}
if (S_val < 0xffffffff){
- snprintf(buf, sizeof(buf), "S%d", S_val);
+ BaseString::snprintf(buf, sizeof(buf), "S%d", S_val);
strcat(theName, buf);
}
if (P_val < 0xff){
- snprintf(buf, sizeof(buf), "P%d", P_val);
+ BaseString::snprintf(buf, sizeof(buf), "P%d", P_val);
strcat(theName, buf);
}
@@ -147,14 +147,14 @@ Filename::set(BlockReference blockReference,
const Uint32 nodeId = FsOpenReq::v2_getNodeId(filenumber);
const Uint32 count = FsOpenReq::v2_getCount(filenumber);
- snprintf(buf, sizeof(buf), "BACKUP%sBACKUP-%d%s",
+ BaseString::snprintf(buf, sizeof(buf), "BACKUP%sBACKUP-%d%s",
DIR_SEPARATOR, seq, DIR_SEPARATOR);
strcat(theName, buf);
if(count == 0xffffffff) {
- snprintf(buf, sizeof(buf), "BACKUP-%d.%d",
+ BaseString::snprintf(buf, sizeof(buf), "BACKUP-%d.%d",
seq, nodeId); strcat(theName, buf);
} else {
- snprintf(buf, sizeof(buf), "BACKUP-%d-%d.%d",
+ BaseString::snprintf(buf, sizeof(buf), "BACKUP-%d-%d.%d",
seq, count, nodeId); strcat(theName, buf);
}
theLevelDepth = 2;
@@ -168,7 +168,7 @@ Filename::set(BlockReference blockReference,
ERROR_SET(ecError, AFS_ERROR_PARAMETER,"","Invalid disk specification");
}
- snprintf(buf, sizeof(buf), "D%d%s", diskNo, DIR_SEPARATOR);
+ BaseString::snprintf(buf, sizeof(buf), "D%d%s", diskNo, DIR_SEPARATOR);
strcat(theName, buf);
theLevelDepth++;
}
diff --git a/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp b/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp
index 6017365a463..41deb3403c8 100644
--- a/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp
+++ b/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp
@@ -592,7 +592,7 @@ void Qmgr::execCM_REGCONF(Signal* signal)
if (!ndbCompatible_ndb_ndb(NDB_VERSION, cmRegConf->presidentVersion)) {
jam();
char buf[128];
- snprintf(buf,sizeof(buf),"incompatible version own=0x%x other=0x%x, shutting down", NDB_VERSION, cmRegConf->presidentVersion);
+ BaseString::snprintf(buf,sizeof(buf),"incompatible version own=0x%x other=0x%x, shutting down", NDB_VERSION, cmRegConf->presidentVersion);
systemErrorLab(signal, buf);
return;
}
@@ -1666,7 +1666,7 @@ void Qmgr::checkStartInterface(Signal* signal)
} else {
if(((nodePtr.p->alarmCount + 1) % 60) == 0){
char buf[100];
- snprintf(buf, sizeof(buf),
+ BaseString::snprintf(buf, sizeof(buf),
"Failure handling of node %d has not completed in %d min."
" - state = %d",
nodePtr.i,
@@ -1760,8 +1760,8 @@ void Qmgr::execAPI_FAILCONF(Signal* signal)
} else {
jam();
#ifdef VM_TRACE
- ndbout << "failedNodePtr.p->failState = " << failedNodePtr.p->failState
- << endl;
+ ndbout << "failedNodePtr.p->failState = "
+ << (Uint32)(failedNodePtr.p->failState) << endl;
#endif
systemErrorLab(signal);
}//if
@@ -1932,10 +1932,6 @@ void Qmgr::execAPI_REGREQ(Signal* signal)
bool compatability_check;
switch(getNodeInfo(apiNodePtr.i).getType()){
- case NodeInfo::DB:
- case NodeInfo::INVALID:
- sendApiRegRef(signal, ref, ApiRegRef::WrongType);
- return;
case NodeInfo::API:
compatability_check = ndbCompatible_ndb_api(NDB_VERSION, version);
break;
@@ -1945,6 +1941,11 @@ void Qmgr::execAPI_REGREQ(Signal* signal)
case NodeInfo::REP:
compatability_check = ndbCompatible_ndb_api(NDB_VERSION, version);
break;
+ case NodeInfo::DB:
+ case NodeInfo::INVALID:
+ default:
+ sendApiRegRef(signal, ref, ApiRegRef::WrongType);
+ return;
}
if (!compatability_check) {
@@ -2672,7 +2673,7 @@ void Qmgr::systemErrorBecauseOtherNodeFailed(Signal* signal,
failReport(signal, getOwnNodeId(), (UintR)ZTRUE, FailRep::ZOWN_FAILURE);
char buf[100];
- snprintf(buf, 100,
+ BaseString::snprintf(buf, 100,
"Node was shutdown during startup because node %d failed",
failedNodeId);
diff --git a/ndb/src/kernel/blocks/suma/Suma.cpp b/ndb/src/kernel/blocks/suma/Suma.cpp
index 052809cb084..d11d5f7176a 100644
--- a/ndb/src/kernel/blocks/suma/Suma.cpp
+++ b/ndb/src/kernel/blocks/suma/Suma.cpp
@@ -98,7 +98,7 @@ Suma::getNodeGroupMembers(Signal* signal) {
}
// ndbout_c("c_noNodesInGroup=%d", c_noNodesInGroup);
- ndbrequire(c_noNodesInGroup >= 0); // at least 1 node in the nodegroup
+ ndbrequire(c_noNodesInGroup > 0); // at least 1 node in the nodegroup
#ifdef NODEFAIL_DEBUG
for (Uint32 i = 0; i < c_noNodesInGroup; i++) {
@@ -1891,7 +1891,7 @@ SumaParticipant::SyncRecord::nextScan(Signal* signal){
ScanFragReq::setHoldLockFlag(req->requestInfo, 0);
ScanFragReq::setKeyinfoFlag(req->requestInfo, 0);
ScanFragReq::setAttrLen(req->requestInfo, attrLen);
- req->fragmentNo = fd.m_fragDesc.m_fragmentNo;
+ req->fragmentNoKeyLen = fd.m_fragDesc.m_fragmentNo;
req->schemaVersion = tabPtr.p->m_schemaVersion;
req->transId1 = 0;
req->transId2 = (SUMA << 20) + (suma.getOwnNodeId() << 8);
@@ -2713,6 +2713,7 @@ Suma::getResponsibleSumaNodeId(Uint32 D)
id = RNIL;
} else {
jam();
+ id = RNIL;
const Uint32 n = c_noNodesInGroup; // Number nodes in node group
const Uint32 C1 = D / n;
const Uint32 C2 = D - C1*n; // = D % n;
diff --git a/ndb/src/kernel/error/ErrorReporter.cpp b/ndb/src/kernel/error/ErrorReporter.cpp
index d43001ef1f5..35c99b30994 100644
--- a/ndb/src/kernel/error/ErrorReporter.cpp
+++ b/ndb/src/kernel/error/ErrorReporter.cpp
@@ -60,7 +60,7 @@ ErrorReporter::formatTimeStampString(){
DateTime.setTimeStamp();
- snprintf(theDateTimeString, 39, "%s %d %s %d - %s:%s:%s",
+ BaseString::snprintf(theDateTimeString, 39, "%s %d %s %d - %s:%s:%s",
DateTime.getDayName(), DateTime.getDayOfMonth(),
DateTime.getMonthName(), DateTime.getYear(), DateTime.getHour(),
DateTime.getMinute(), DateTime.getSecond());
@@ -126,7 +126,7 @@ ErrorReporter::formatMessage(ErrorCategory type,
processId = NdbHost_GetProcessId();
- snprintf(messptr, MESSAGE_LENGTH,
+ BaseString::snprintf(messptr, MESSAGE_LENGTH,
"Date/Time: %s\nType of error: %s\n"
"Message: %s\nFault ID: %d\nProblem data: %s"
"\nObject of reference: %s\nProgramName: %s\n"
@@ -157,13 +157,13 @@ ErrorReporter::handleAssert(const char* message, const char* file, int line)
char refMessage[100];
#ifdef NO_EMULATED_JAM
- snprintf(refMessage, 100, "file: %s lineNo: %d",
+ BaseString::snprintf(refMessage, 100, "file: %s lineNo: %d",
file, line);
#else
const Uint32 blockNumber = theEmulatedJamBlockNumber;
const char *blockName = getBlockName(blockNumber);
- snprintf(refMessage, 100, "%s line: %d (block: %s)",
+ BaseString::snprintf(refMessage, 100, "%s line: %d (block: %s)",
file, line, blockName);
#endif
WriteMessage(assert, ERR_ERROR_PRGERR, message, refMessage,
@@ -178,7 +178,7 @@ ErrorReporter::handleThreadAssert(const char* message,
int line)
{
char refMessage[100];
- snprintf(refMessage, 100, "file: %s lineNo: %d - %s",
+ BaseString::snprintf(refMessage, 100, "file: %s lineNo: %d - %s",
file, line, message);
NdbShutdown(NST_ErrorHandler);
diff --git a/ndb/src/kernel/main.cpp b/ndb/src/kernel/main.cpp
index 9c25da79065..fa44704807d 100644
--- a/ndb/src/kernel/main.cpp
+++ b/ndb/src/kernel/main.cpp
@@ -363,6 +363,6 @@ handler_error(int signum){
g_eventLogger.info("Received signal %d. Running error handler.", signum);
// restart the system
char errorData[40];
- snprintf(errorData, 40, "Signal %d received", signum);
+ BaseString::snprintf(errorData, 40, "Signal %d received", signum);
ERROR_SET_SIGNAL(fatal, 0, errorData, __FILE__);
}
diff --git a/ndb/src/kernel/vm/ClusterConfiguration.cpp b/ndb/src/kernel/vm/ClusterConfiguration.cpp
index 3a6478380d1..d5bd03f69d5 100644
--- a/ndb/src/kernel/vm/ClusterConfiguration.cpp
+++ b/ndb/src/kernel/vm/ClusterConfiguration.cpp
@@ -358,7 +358,7 @@ void ClusterConfiguration::init(const Properties & p, const Properties & db){
for(int i = 0; i<sz; i++){
if(!db.get(tmp[i].attrib, tmp[i].storage)){
char buf[255];
- snprintf(buf, sizeof(buf), "%s not found", tmp[i].attrib);
+ BaseString::snprintf(buf, sizeof(buf), "%s not found", tmp[i].attrib);
ERROR_SET(fatal, ERR_INVALID_CONFIG, msg, buf);
}
}
@@ -406,7 +406,7 @@ void ClusterConfiguration::init(const Properties & p, const Properties & db){
for(unsigned j = 0; j<nodeNo; j++){
if(cd.nodeData[j].nodeId == nodeId){
char buf[255];
- snprintf(buf, sizeof(buf), "Two node can not have the same node id");
+ BaseString::snprintf(buf, sizeof(buf), "Two node can not have the same node id");
ERROR_SET(fatal, ERR_INVALID_CONFIG, msg, buf);
}
}
@@ -429,12 +429,12 @@ void ClusterConfiguration::init(const Properties & p, const Properties & db){
if(nodeId > MAX_NDB_NODES){
char buf[255];
- snprintf(buf, sizeof(buf), "Maximum node id for a ndb node is: %d", MAX_NDB_NODES);
+ BaseString::snprintf(buf, sizeof(buf), "Maximum node id for a ndb node is: %d", MAX_NDB_NODES);
ERROR_SET(fatal, ERR_INVALID_CONFIG, msg, buf);
}
if(cd.SizeAltData.noOfNDBNodes > MAX_NDB_NODES){
char buf[255];
- snprintf(buf, sizeof(buf),
+ BaseString::snprintf(buf, sizeof(buf),
"Maximum %d ndb nodes is allowed in the cluster",
MAX_NDB_NODES);
ERROR_SET(fatal, ERR_INVALID_CONFIG, msg, buf);
diff --git a/ndb/src/kernel/vm/Configuration.cpp b/ndb/src/kernel/vm/Configuration.cpp
index fd5d79b92e7..706f60fd9cf 100644
--- a/ndb/src/kernel/vm/Configuration.cpp
+++ b/ndb/src/kernel/vm/Configuration.cpp
@@ -203,7 +203,7 @@ Configuration::fetch_configuration(LocalConfig &local_config){
/* Set stop on error to true otherwise NDB will
go into an restart loop...
*/
- ERROR_SET(fatal, ERR_INVALID_CONFIG, "Could connect to ndb_mgmd", s);
+ ERROR_SET(fatal, ERR_INVALID_CONFIG, "Could not connect to ndb_mgmd", s);
}
m_mgmd_port= m_config_retriever->get_mgmd_port();
@@ -487,7 +487,7 @@ Configuration::calcSizeAlt(ConfigValues * ownConfig){
if (tmp[i].computable) {
*tmp[i].storage = 0;
} else {
- snprintf(buf, sizeof(buf),"ConfigParam: %d not found", tmp[i].paramId);
+ BaseString::snprintf(buf, sizeof(buf),"ConfigParam: %d not found", tmp[i].paramId);
ERROR_SET(fatal, ERR_INVALID_CONFIG, msg, buf);
}
}
@@ -497,12 +497,12 @@ Configuration::calcSizeAlt(ConfigValues * ownConfig){
ndb_mgm_get_int64_parameter(&db, CFG_DB_DATA_MEM, &dataMem);
ndb_mgm_get_int64_parameter(&db, CFG_DB_INDEX_MEM, &indexMem);
if(dataMem == 0){
- snprintf(buf, sizeof(buf), "ConfigParam: %d not found", CFG_DB_DATA_MEM);
+ BaseString::snprintf(buf, sizeof(buf), "ConfigParam: %d not found", CFG_DB_DATA_MEM);
ERROR_SET(fatal, ERR_INVALID_CONFIG, msg, buf);
}
if(indexMem == 0){
- snprintf(buf, sizeof(buf), "ConfigParam: %d not found", CFG_DB_INDEX_MEM);
+ BaseString::snprintf(buf, sizeof(buf), "ConfigParam: %d not found", CFG_DB_INDEX_MEM);
ERROR_SET(fatal, ERR_INVALID_CONFIG, msg, buf);
}
@@ -535,13 +535,13 @@ Configuration::calcSizeAlt(ConfigValues * ownConfig){
}
if(nodeId > MAX_NODES || nodeId == 0){
- snprintf(buf, sizeof(buf),
+ BaseString::snprintf(buf, sizeof(buf),
"Invalid node id: %d", nodeId);
ERROR_SET(fatal, ERR_INVALID_CONFIG, msg, buf);
}
if(nodes.get(nodeId)){
- snprintf(buf, sizeof(buf), "Two node can not have the same node id: %d",
+ BaseString::snprintf(buf, sizeof(buf), "Two node can not have the same node id: %d",
nodeId);
ERROR_SET(fatal, ERR_INVALID_CONFIG, msg, buf);
}
@@ -568,7 +568,7 @@ Configuration::calcSizeAlt(ConfigValues * ownConfig){
case NODE_TYPE_EXT_REP:
break;
default:
- snprintf(buf, sizeof(buf), "Unknown node type: %d", nodeType);
+ BaseString::snprintf(buf, sizeof(buf), "Unknown node type: %d", nodeType);
ERROR_SET(fatal, ERR_INVALID_CONFIG, msg, buf);
}
}
diff --git a/ndb/src/kernel/vm/SignalCounter.hpp b/ndb/src/kernel/vm/SignalCounter.hpp
index ea770324aa6..62242cb65bd 100644
--- a/ndb/src/kernel/vm/SignalCounter.hpp
+++ b/ndb/src/kernel/vm/SignalCounter.hpp
@@ -151,7 +151,7 @@ const char *
SignalCounter::getText() const {
static char buf[255];
static char nodes[NodeBitmask::TextLength+1];
- snprintf(buf, sizeof(buf), "[SignalCounter: m_count=%d %s]", m_count, m_nodes.getText(nodes));
+ BaseString::snprintf(buf, sizeof(buf), "[SignalCounter: m_count=%d %s]", m_count, m_nodes.getText(nodes));
return buf;
}
diff --git a/ndb/src/kernel/vm/SimulatedBlock.cpp b/ndb/src/kernel/vm/SimulatedBlock.cpp
index 18b7f474ddc..e6b97771d36 100644
--- a/ndb/src/kernel/vm/SimulatedBlock.cpp
+++ b/ndb/src/kernel/vm/SimulatedBlock.cpp
@@ -68,25 +68,25 @@ SimulatedBlock::SimulatedBlock(BlockNumber blockNumber,
char buf[255];
count = 10;
- snprintf(buf, 255, "%s.FragmentSendPool", getBlockName(blockNumber));
+ BaseString::snprintf(buf, 255, "%s.FragmentSendPool", getBlockName(blockNumber));
if(!p->get(buf, &count))
p->get("FragmentSendPool", &count);
c_fragmentSendPool.setSize(count);
count = 10;
- snprintf(buf, 255, "%s.FragmentInfoPool", getBlockName(blockNumber));
+ BaseString::snprintf(buf, 255, "%s.FragmentInfoPool", getBlockName(blockNumber));
if(!p->get(buf, &count))
p->get("FragmentInfoPool", &count);
c_fragmentInfoPool.setSize(count);
count = 10;
- snprintf(buf, 255, "%s.FragmentInfoHash", getBlockName(blockNumber));
+ BaseString::snprintf(buf, 255, "%s.FragmentInfoHash", getBlockName(blockNumber));
if(!p->get(buf, &count))
p->get("FragmentInfoHash", &count);
c_fragmentInfoHash.setSize(count);
count = 5;
- snprintf(buf, 255, "%s.ActiveMutexes", getBlockName(blockNumber));
+ BaseString::snprintf(buf, 255, "%s.ActiveMutexes", getBlockName(blockNumber));
if(!p->get(buf, &count))
p->get("ActiveMutexes", &count);
c_mutexMgr.setSize(count);
@@ -147,7 +147,7 @@ SimulatedBlock::addRecSignalImpl(GlobalSignalNumber gsn,
ExecFunction f, bool force){
if(gsn > MAX_GSN || (!force && theExecArray[gsn] != 0)){
char errorMsg[255];
- snprintf(errorMsg, 255,
+ BaseString::snprintf(errorMsg, 255,
"Illeagal signal (%d %d)", gsn, MAX_GSN);
ERROR_SET(fatal, ERR_ERROR_PRGERR, errorMsg, errorMsg);
}
@@ -159,9 +159,9 @@ SimulatedBlock::signal_error(Uint32 gsn, Uint32 len, Uint32 recBlockNo,
const char* filename, int lineno) const
{
char objRef[255];
- snprintf(objRef, 255, "%s:%d", filename, lineno);
+ BaseString::snprintf(objRef, 255, "%s:%d", filename, lineno);
char probData[255];
- snprintf(probData, 255,
+ BaseString::snprintf(probData, 255,
"Signal (GSN: %d, Length: %d, Rec Block No: %d)",
gsn, len, recBlockNo);
@@ -664,9 +664,9 @@ SimulatedBlock::allocRecord(const char * type, size_t s, size_t n, bool clear)
if (p == NULL){
char buf1[255];
char buf2[255];
- snprintf(buf1, sizeof(buf1), "%s could not allocate memory for %s",
+ BaseString::snprintf(buf1, sizeof(buf1), "%s could not allocate memory for %s",
getBlockName(number()), type);
- snprintf(buf2, sizeof(buf2), "Requested: %ux%u = %u bytes",
+ BaseString::snprintf(buf2, sizeof(buf2), "Requested: %ux%u = %u bytes",
(Uint32)s, (Uint32)n, (Uint32)size);
ERROR_SET(fatal, ERR_MEMALLOC, buf1, buf2);
}
@@ -722,7 +722,7 @@ SimulatedBlock::progError(int line, int err_code, const char* extra) const {
/* Add line number to block name */
char buf[100];
- snprintf(&buf[0], 100, "%s (Line: %d) 0x%.8x",
+ BaseString::snprintf(&buf[0], 100, "%s (Line: %d) 0x%.8x",
aBlockName, line, magicStatus);
ErrorReporter::handleError(ecError, err_code, extra, buf);
@@ -740,7 +740,7 @@ SimulatedBlock::infoEvent(const char * msg, ...) const {
va_list ap;
va_start(ap, msg);
- vsnprintf(buf, 96, msg, ap); // 96 = 100 - 4
+ BaseString::vsnprintf(buf, 96, msg, ap); // 96 = 100 - 4
va_end(ap);
int len = strlen(buf) + 1;
@@ -781,7 +781,7 @@ SimulatedBlock::warningEvent(const char * msg, ...) const {
va_list ap;
va_start(ap, msg);
- vsnprintf(buf, 96, msg, ap); // 96 = 100 - 4
+ BaseString::vsnprintf(buf, 96, msg, ap); // 96 = 100 - 4
va_end(ap);
int len = strlen(buf) + 1;
diff --git a/ndb/src/kernel/vm/SimulatedBlock.hpp b/ndb/src/kernel/vm/SimulatedBlock.hpp
index 6d46e9cc377..7972cb39746 100644
--- a/ndb/src/kernel/vm/SimulatedBlock.hpp
+++ b/ndb/src/kernel/vm/SimulatedBlock.hpp
@@ -472,11 +472,11 @@ SimulatedBlock::executeFunction(GlobalSignalNumber gsn, Signal* signal){
*/
char errorMsg[255];
if (!(gsn <= MAX_GSN)) {
- snprintf(errorMsg, 255, "Illegal signal received (GSN %d too high)", gsn);
+ BaseString::snprintf(errorMsg, 255, "Illegal signal received (GSN %d too high)", gsn);
ERROR_SET(fatal, ERR_ERROR_PRGERR, errorMsg, errorMsg);
}
if (!(theExecArray[gsn] != 0)) {
- snprintf(errorMsg, 255, "Illegal signal received (GSN %d not added)", gsn);
+ BaseString::snprintf(errorMsg, 255, "Illegal signal received (GSN %d not added)", gsn);
ERROR_SET(fatal, ERR_ERROR_PRGERR, errorMsg, errorMsg);
}
ndbrequire(false);
diff --git a/ndb/src/mgmapi/mgmapi.cpp b/ndb/src/mgmapi/mgmapi.cpp
index fccd5c7983b..4b62df968b3 100644
--- a/ndb/src/mgmapi/mgmapi.cpp
+++ b/ndb/src/mgmapi/mgmapi.cpp
@@ -15,6 +15,9 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include <ndb_global.h>
+#include <my_sys.h>
+
+#include <NdbAutoPtr.hpp>
#include <NdbTCP.h>
#include "mgmapi.h"
@@ -107,7 +110,7 @@ setError(NdbMgmHandle h, int error, int error_line, const char * msg, ...){
va_list ap;
va_start(ap, msg);
- vsnprintf(h->last_error_desc, sizeof(h->last_error_desc), msg, ap);
+ BaseString::vsnprintf(h->last_error_desc, sizeof(h->last_error_desc), msg, ap);
va_end(ap);
}
@@ -137,7 +140,8 @@ extern "C"
NdbMgmHandle
ndb_mgm_create_handle()
{
- NdbMgmHandle h = (NdbMgmHandle)malloc(sizeof(ndb_mgm_handle));
+ NdbMgmHandle h =
+ (NdbMgmHandle)my_malloc(sizeof(ndb_mgm_handle),MYF(MY_WME));
h->connected = 0;
h->last_error = 0;
h->last_error_line = 0;
@@ -166,16 +170,14 @@ ndb_mgm_destroy_handle(NdbMgmHandle * handle)
if((* handle)->connected){
ndb_mgm_disconnect(* handle);
}
- if((* handle)->hostname != 0){
- free((* handle)->hostname);
- }
+ my_free((* handle)->hostname,MYF(MY_ALLOW_ZERO_PTR));
#ifdef MGMAPI_LOG
if ((* handle)->logfile != 0){
fclose((* handle)->logfile);
(* handle)->logfile = 0;
}
#endif
- free(* handle);
+ my_free((char*)* handle,MYF(MY_ALLOW_ZERO_PTR));
* handle = 0;
}
@@ -228,7 +230,8 @@ parse_connect_string(const char * connect_string,
return -1;
}
- char * line = strdup(connect_string);
+ char * line = my_strdup(connect_string,MYF(MY_WME));
+ My_auto_ptr<char> ap1(line);
if(line == 0){
SET_ERROR(handle, NDB_MGM_OUT_OF_MEMORY, "");
return -1;
@@ -236,7 +239,6 @@ parse_connect_string(const char * connect_string,
char * tmp = strchr(line, ':');
if(tmp == 0){
- free(line);
SET_ERROR(handle, NDB_MGM_OUT_OF_MEMORY, "");
return -1;
}
@@ -244,17 +246,13 @@ parse_connect_string(const char * connect_string,
int port = 0;
if(sscanf(tmp, "%d", &port) != 1){
- free(line);
SET_ERROR(handle, NDB_MGM_ILLEGAL_PORT_NUMBER, "");
return -1;
}
- if(handle->hostname != 0)
- free(handle->hostname);
-
- handle->hostname = strdup(line);
+ my_free(handle->hostname,MYF(MY_ALLOW_ZERO_PTR));
+ handle->hostname = my_strdup(line,MYF(MY_WME));
handle->port = port;
- free(line);
return 0;
}
@@ -361,7 +359,7 @@ ndb_mgm_connect(NdbMgmHandle handle, const char * mgmsrv)
* Open the log file
*/
char logname[64];
- snprintf(logname, 64, "mgmapi.log");
+ BaseString::snprintf(logname, 64, "mgmapi.log");
handle->logfile = fopen(logname, "w");
#endif
@@ -1153,11 +1151,14 @@ ndb_mgm_dump_state(NdbMgmHandle handle, int nodeId, int* _args,
CHECK_CONNECTED(handle, -1);
char buf[256];
- char buf2[6];
buf[0] = 0;
for (int i = 0; i < _num_args; i++){
- snprintf(buf2, 6, "%d ", _args[i]);
- strncat(buf, buf2, 256);
+ unsigned n = strlen(buf);
+ if (n + 20 > sizeof(buf)) {
+ SET_ERROR(handle, NDB_MGM_USAGE_ERROR, "arguments too long");
+ return -1;
+ }
+ sprintf(buf + n, "%s%d", i ? " " : "", _args[i]);
}
Properties args;
@@ -1653,8 +1654,11 @@ ndb_mgm_alloc_nodeid(NdbMgmHandle handle, unsigned int version, unsigned *pnodei
do {
const char * buf;
if(!prop->get("result", &buf) || strcmp(buf, "Ok") != 0){
+ BaseString err;
+ err.assfmt("Could not alloc node id at %s port %d: %s",
+ handle->hostname, handle->port, buf);
setError(handle, NDB_MGM_COULD_NOT_CONNECT_TO_SOCKET, __LINE__,
- "Could not alloc node id: %s",buf);
+ err.c_str());
break;
}
if(!prop->get("nodeid", pnodeid) != 0){
diff --git a/ndb/src/mgmclient/CommandInterpreter.cpp b/ndb/src/mgmclient/CommandInterpreter.cpp
index 7560a59a1ef..e0935c2104e 100644
--- a/ndb/src/mgmclient/CommandInterpreter.cpp
+++ b/ndb/src/mgmclient/CommandInterpreter.cpp
@@ -828,6 +828,8 @@ CommandInterpreter::executeShow(char* parameters)
case NDB_MGM_NODE_TYPE_UNKNOWN:
ndbout << "Error: Unknown Node Type" << endl;
return;
+ case NDB_MGM_NODE_TYPE_REP:
+ abort();
}
}
@@ -1363,36 +1365,29 @@ CommandInterpreter::executeLog(int processId,
if (! parseBlockSpecification(parameters, blocks)) {
return;
}
- int len=0;
+ int len=1;
Uint32 i;
for(i=0; i<blocks.size(); i++) {
- ndbout_c("blocks %s %d",blocks[i], strlen(blocks[i]));
- len += strlen(blocks[i]);
+ len += strlen(blocks[i]) + 1;
}
- len += blocks.size()*2;
char * blockNames = (char*)my_malloc(len,MYF(MY_WME));
My_auto_ptr<char> ap1(blockNames);
+ blockNames[0] = 0;
for(i=0; i<blocks.size(); i++) {
strcat(blockNames, blocks[i]);
strcat(blockNames, "|");
}
- strcat(blockNames, "\0");
- ndbout_c("blocknames %s", blockNames);
- /*int res =*/ndb_mgm_log_signals(m_mgmsrv,
+ int result = ndb_mgm_log_signals(m_mgmsrv,
processId,
NDB_MGM_SIGNAL_LOG_MODE_INOUT,
blockNames,
&reply);
-
-#if 0
- int result =
- _mgmtSrvr.setSignalLoggingMode(processId, MgmtSrvr::InOut, blocks);
if (result != 0) {
- ndbout << _mgmtSrvr.getErrorText(result) << endl;
+ ndbout_c("Execute LOG on node %d failed.", processId);
+ printError();
}
-#endif
}
//*****************************************************************************
@@ -1401,17 +1396,7 @@ void
CommandInterpreter::executeLogIn(int /* processId */,
const char* parameters, bool /* all */)
{
- Vector<const char*> blocks;
- if (! parseBlockSpecification(parameters, blocks)) {
- return;
- }
-
-#if 0
- int result = _mgmtSrvr.setSignalLoggingMode(processId, MgmtSrvr::In, blocks);
- if (result != 0) {
- ndbout << _mgmtSrvr.getErrorText(result) << endl;
- }
-#endif
+ ndbout << "Command LOGIN not implemented." << endl;
}
//*****************************************************************************
@@ -1420,19 +1405,7 @@ void
CommandInterpreter::executeLogOut(int /*processId*/,
const char* parameters, bool /*all*/)
{
- Vector<const char*> blocks;
- if (! parseBlockSpecification(parameters, blocks)) {
- return;
- }
-
-
-#if 0
- int result = _mgmtSrvr.setSignalLoggingMode(processId, MgmtSrvr::Out,
- blocks);
- if (result != 0) {
- ndbout << _mgmtSrvr.getErrorText(result) << endl;
- }
-#endif
+ ndbout << "Command LOGOUT not implemented." << endl;
}
//*****************************************************************************
@@ -1441,57 +1414,45 @@ void
CommandInterpreter::executeLogOff(int /*processId*/,
const char* parameters, bool /*all*/)
{
- Vector<const char*> blocks;
- if (! parseBlockSpecification(parameters, blocks)) {
- return;
- }
-
-
-#if 0
- int result = _mgmtSrvr.setSignalLoggingMode(processId, MgmtSrvr::Off,
- blocks);
- if (result != 0) {
- ndbout << _mgmtSrvr.getErrorText(result) << endl;
- }
-#endif
+ ndbout << "Command LOGOFF not implemented." << endl;
}
//*****************************************************************************
//*****************************************************************************
void
-CommandInterpreter::executeTestOn(int /*processId*/,
+CommandInterpreter::executeTestOn(int processId,
const char* parameters, bool /*all*/)
{
if (! emptyString(parameters)) {
ndbout << "No parameters expected to this command." << endl;
return;
}
-
-#if 0
- int result = _mgmtSrvr.startSignalTracing(processId);
+ connect();
+ struct ndb_mgm_reply reply;
+ int result = ndb_mgm_start_signallog(m_mgmsrv, processId, &reply);
if (result != 0) {
- ndbout << _mgmtSrvr.getErrorText(result) << endl;
+ ndbout_c("Execute TESTON failed.");
+ printError();
}
-#endif
}
//*****************************************************************************
//*****************************************************************************
void
-CommandInterpreter::executeTestOff(int /*processId*/,
+CommandInterpreter::executeTestOff(int processId,
const char* parameters, bool /*all*/)
{
if (! emptyString(parameters)) {
ndbout << "No parameters expected to this command." << endl;
return;
}
-
-#if 0
- int result = _mgmtSrvr.stopSignalTracing(processId);
+ connect();
+ struct ndb_mgm_reply reply;
+ int result = ndb_mgm_stop_signallog(m_mgmsrv, processId, &reply);
if (result != 0) {
- ndbout << _mgmtSrvr.getErrorText(result) << endl;
+ ndbout_c("Execute TESTOFF failed.");
+ printError();
}
-#endif
}
@@ -1679,7 +1640,7 @@ CommandInterpreter::executeStartBackup(char* /*parameters*/)
if(tmp)
{
ndbout << tmp;
- int id;
+ unsigned int id;
if(sscanf(tmp, "%*[^:]: Backup %d ", &id) == 1 && id == backupId){
count++;
}
@@ -2059,46 +2020,46 @@ CmdBackupCallback(const MgmtSrvr::BackupEvent & event){
switch(event.Event){
case MgmtSrvr::BackupEvent::BackupStarted:
ok = true;
- snprintf(str, sizeof(str),
+ BaseString::snprintf(str, sizeof(str),
"Backup %d started", event.Started.BackupId);
break;
case MgmtSrvr::BackupEvent::BackupFailedToStart:
ok = true;
- snprintf(str, sizeof(str),
+ BaseString::snprintf(str, sizeof(str),
"Backup failed to start (Error %d)",
event.FailedToStart.ErrorCode);
break;
case MgmtSrvr::BackupEvent::BackupCompleted:
ok = true;
- snprintf(str, sizeof(str),
+ BaseString::snprintf(str, sizeof(str),
"Backup %d completed",
event.Completed.BackupId);
ndbout << str << endl;
- snprintf(str, sizeof(str),
+ BaseString::snprintf(str, sizeof(str),
" StartGCP: %d StopGCP: %d",
event.Completed.startGCP, event.Completed.stopGCP);
ndbout << str << endl;
- snprintf(str, sizeof(str),
+ BaseString::snprintf(str, sizeof(str),
" #Records: %d #LogRecords: %d",
event.Completed.NoOfRecords, event.Completed.NoOfLogRecords);
ndbout << str << endl;
- snprintf(str, sizeof(str),
+ BaseString::snprintf(str, sizeof(str),
" Data: %d bytes Log: %d bytes",
event.Completed.NoOfBytes, event.Completed.NoOfLogBytes);
break;
case MgmtSrvr::BackupEvent::BackupAborted:
ok = true;
- snprintf(str, sizeof(str),
+ BaseString::snprintf(str, sizeof(str),
"Backup %d has been aborted reason %d",
event.Aborted.BackupId,
event.Aborted.Reason);
break;
}
if(!ok){
- snprintf(str, sizeof(str),
+ BaseString::snprintf(str, sizeof(str),
"Unknown backup event: %d",
event.Event);
diff --git a/ndb/src/mgmclient/main.cpp b/ndb/src/mgmclient/main.cpp
index 69f968677cd..cc6d4bf600e 100644
--- a/ndb/src/mgmclient/main.cpp
+++ b/ndb/src/mgmclient/main.cpp
@@ -85,7 +85,7 @@ int main(int argc, const char** argv){
}
char buf[MAXHOSTNAMELEN+10];
- snprintf(buf, sizeof(buf), "%s:%d", _host, _port);
+ BaseString::snprintf(buf, sizeof(buf), "%s:%d", _host, _port);
ndbout << "-- NDB Cluster -- Management Client --" << endl;
printf("Connecting to Management Server: %s\n", buf);
diff --git a/ndb/src/mgmsrv/CommandInterpreter.cpp b/ndb/src/mgmsrv/CommandInterpreter.cpp
index 2c2aeda21ed..2a054a01f1e 100644
--- a/ndb/src/mgmsrv/CommandInterpreter.cpp
+++ b/ndb/src/mgmsrv/CommandInterpreter.cpp
@@ -647,6 +647,7 @@ versionCallback(int nodeId, int version, void * anyData, int errCode){
}
break;
case NDB_MGM_NODE_TYPE_UNKNOWN:
+ case NDB_MGM_NODE_TYPE_REP:
abort();
};
diff --git a/ndb/src/mgmsrv/Config.cpp b/ndb/src/mgmsrv/Config.cpp
index b8a494cb759..f9c6a23f909 100644
--- a/ndb/src/mgmsrv/Config.cpp
+++ b/ndb/src/mgmsrv/Config.cpp
@@ -85,6 +85,9 @@ Config::printAllNameValuePairs(NdbOut &out,
MGM_REQUIRE(prop->get(n, &str_value));
out << str_value;
break;
+ case ConfigInfo::SECTION:
+ out << "SECTION";
+ break;
}
out << endl;
}
diff --git a/ndb/src/mgmsrv/ConfigInfo.cpp b/ndb/src/mgmsrv/ConfigInfo.cpp
index bff7f9be0e6..ad346b30ead 100644
--- a/ndb/src/mgmsrv/ConfigInfo.cpp
+++ b/ndb/src/mgmsrv/ConfigInfo.cpp
@@ -2189,7 +2189,7 @@ ConfigInfo::ConfigInfo()
break;
}
case SECTION:
- pinfo.put("SectionType", (Uint32)param._default);
+ pinfo.put("SectionType", (Uint32)UintPtr(param._default));
break;
case STRING:
break;
@@ -2504,7 +2504,7 @@ transformNode(InitConfigFileParser::Context & ctx, const char * data){
}
ctx.m_userProperties.put("AllocatedNodeId_", id, id);
- snprintf(ctx.pname, sizeof(ctx.pname), "Node_%d", id);
+ BaseString::snprintf(ctx.pname, sizeof(ctx.pname), "Node_%d", id);
ctx.m_currentSection->put("Type", ctx.fname);
@@ -2569,7 +2569,7 @@ fixNodeHostname(InitConfigFileParser::Context & ctx, const char * data){
const Properties * computer;
char tmp[255];
- snprintf(tmp, sizeof(tmp), "Computer_%s", compId);
+ BaseString::snprintf(tmp, sizeof(tmp), "Computer_%s", compId);
if(!ctx.m_config->get(tmp, &computer)){
ctx.reportError("Computer \"%s\" not declared"
"- [%s] starting at line: %d",
@@ -2647,7 +2647,7 @@ transformExtNode(InitConfigFileParser::Context & ctx, const char * data){
ctx.m_userProperties.get("ExtNoOfNodes", &nodes);
require(ctx.m_userProperties.put("ExtNoOfNodes",++nodes, true));
- snprintf(ctx.pname, sizeof(ctx.pname), "EXTERNAL SYSTEM_%s:Node_%d",
+ BaseString::snprintf(ctx.pname, sizeof(ctx.pname), "EXTERNAL SYSTEM_%s:Node_%d",
systemName, id);
return true;
@@ -2661,7 +2661,7 @@ transformConnection(InitConfigFileParser::Context & ctx, const char * data){
Uint32 connections = 0;
ctx.m_userProperties.get("NoOfConnections", &connections);
- snprintf(ctx.pname, sizeof(ctx.pname), "Connection_%d", connections);
+ BaseString::snprintf(ctx.pname, sizeof(ctx.pname), "Connection_%d", connections);
ctx.m_userProperties.put("NoOfConnections", ++connections, true);
ctx.m_currentSection->put("Type", ctx.fname);
@@ -2684,7 +2684,7 @@ transformSystem(InitConfigFileParser::Context & ctx, const char * data){
ndbout << "transformSystem " << name << endl;
- snprintf(ctx.pname, sizeof(ctx.pname), "SYSTEM_%s", name);
+ BaseString::snprintf(ctx.pname, sizeof(ctx.pname), "SYSTEM_%s", name);
return true;
}
@@ -2701,7 +2701,7 @@ transformExternalSystem(InitConfigFileParser::Context & ctx, const char * data){
ctx.fname, ctx.m_sectionLineno);
return false;
}
- snprintf(ctx.pname, sizeof(ctx.pname), "EXTERNAL SYSTEM_%s", name);
+ BaseString::snprintf(ctx.pname, sizeof(ctx.pname), "EXTERNAL SYSTEM_%s", name);
return true;
}
@@ -2718,7 +2718,7 @@ transformComputer(InitConfigFileParser::Context & ctx, const char * data){
ctx.fname, ctx.m_sectionLineno);
return false;
}
- snprintf(ctx.pname, sizeof(ctx.pname), "Computer_%s", id);
+ BaseString::snprintf(ctx.pname, sizeof(ctx.pname), "Computer_%s", id);
Uint32 computers = 0;
ctx.m_userProperties.get("NoOfComputers", &computers);
@@ -2894,7 +2894,7 @@ fixExtConnection(InitConfigFileParser::Context & ctx, const char * data){
require(ctx.m_userProperties.put("ExtNoOfConnections",++connections, true));
char tmpLine1[MAX_LINE_LENGTH];
- snprintf(tmpLine1, MAX_LINE_LENGTH, "Connection_%d", connections-1);
+ BaseString::snprintf(tmpLine1, MAX_LINE_LENGTH, "Connection_%d", connections-1);
/**
* Section: EXTERNAL SYSTEM_<Ext System Name>
@@ -3405,9 +3405,9 @@ add_node_connections(Vector<ConfigInfo::ConfigRuleSection>&sections,
s.m_sectionType= BaseString("TCP");
s.m_sectionData= new Properties(true);
char buf[16];
- snprintf(buf, sizeof(buf), "%u", nodeId1);
+ BaseString::snprintf(buf, sizeof(buf), "%u", nodeId1);
s.m_sectionData->put("NodeId1", buf);
- snprintf(buf, sizeof(buf), "%u", nodeId2);
+ BaseString::snprintf(buf, sizeof(buf), "%u", nodeId2);
s.m_sectionData->put("NodeId2", buf);
sections.push_back(s);
}
@@ -3422,9 +3422,9 @@ add_node_connections(Vector<ConfigInfo::ConfigRuleSection>&sections,
s.m_sectionType= BaseString("TCP");
s.m_sectionData= new Properties(true);
char buf[16];
- snprintf(buf, sizeof(buf), "%u", nodeId1);
+ BaseString::snprintf(buf, sizeof(buf), "%u", nodeId1);
s.m_sectionData->put("NodeId1", buf);
- snprintf(buf, sizeof(buf), "%u", nodeId2);
+ BaseString::snprintf(buf, sizeof(buf), "%u", nodeId2);
s.m_sectionData->put("NodeId2", buf);
sections.push_back(s);
}
@@ -3559,7 +3559,7 @@ check_node_vs_replicas(Vector<ConfigInfo::ConfigRuleSection>&sections,
{
unsigned c= 0;
p_db_hosts.get(str.c_str(),&c);
- if (c+1 == (1 << (replicas-1))) // all nodes on same machine
+ 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)
diff --git a/ndb/src/mgmsrv/InitConfigFileParser.cpp b/ndb/src/mgmsrv/InitConfigFileParser.cpp
index 652e0f96190..fdfe7823fc2 100644
--- a/ndb/src/mgmsrv/InitConfigFileParser.cpp
+++ b/ndb/src/mgmsrv/InitConfigFileParser.cpp
@@ -42,7 +42,7 @@ InitConfigFileParser::~InitConfigFileParser() {
// Read Config File
//****************************************************************************
InitConfigFileParser::Context::Context(const ConfigInfo * info)
- : m_configValues(1000, 20), m_userProperties(true) {
+ : m_userProperties(true), m_configValues(1000, 20) {
m_config = new Properties(true);
m_defaults = new Properties(true);
@@ -110,7 +110,7 @@ InitConfigFileParser::parseConfig(FILE * file) {
"of configuration file.");
return 0;
}
- snprintf(ctx.fname, sizeof(ctx.fname), section); free(section);
+ BaseString::snprintf(ctx.fname, sizeof(ctx.fname), section); free(section);
ctx.type = InitConfigFileParser::DefaultSection;
ctx.m_sectionLineno = ctx.m_lineno;
ctx.m_currentSection = new Properties(true);
@@ -130,7 +130,7 @@ InitConfigFileParser::parseConfig(FILE * file) {
"of configuration file.");
return 0;
}
- snprintf(ctx.fname, sizeof(ctx.fname), section);
+ BaseString::snprintf(ctx.fname, sizeof(ctx.fname), section);
free(section);
ctx.type = InitConfigFileParser::Section;
ctx.m_sectionLineno = ctx.m_lineno;
@@ -172,7 +172,7 @@ InitConfigFileParser::parseConfig(FILE * file) {
return 0;
for(size_t j = 0; j<tmp.size(); j++){
- snprintf(ctx.fname, sizeof(ctx.fname), tmp[j].m_sectionType.c_str());
+ BaseString::snprintf(ctx.fname, sizeof(ctx.fname), tmp[j].m_sectionType.c_str());
ctx.type = InitConfigFileParser::Section;
ctx.m_currentSection = tmp[j].m_sectionData;
ctx.m_userDefaults = getSection(ctx.fname, ctx.m_defaults);
@@ -198,7 +198,7 @@ InitConfigFileParser::parseConfig(FILE * file) {
ctx.m_config->put("NoOfNodes", nNodes);
char tmpLine[MAX_LINE_LENGTH];
- snprintf(tmpLine, MAX_LINE_LENGTH, "EXTERNAL SYSTEM_");
+ BaseString::snprintf(tmpLine, MAX_LINE_LENGTH, "EXTERNAL SYSTEM_");
strncat(tmpLine, system, MAX_LINE_LENGTH);
strncat(tmpLine, ":NoOfConnections", MAX_LINE_LENGTH);
ctx.m_config->put(tmpLine, nExtConnections);
@@ -349,6 +349,8 @@ InitConfigFileParser::storeNameValuePair(Context& ctx,
case ConfigInfo::STRING:
MGM_REQUIRE(ctx.m_currentSection->put(pname, value));
break;
+ case ConfigInfo::SECTION:
+ abort();
}
return true;
}
@@ -547,13 +549,13 @@ InitConfigFileParser::storeSection(Context& ctx){
for(int i = strlen(ctx.fname) - 1; i>=0; i--){
ctx.fname[i] = toupper(ctx.fname[i]);
}
- snprintf(ctx.pname, sizeof(ctx.pname), ctx.fname);
+ BaseString::snprintf(ctx.pname, sizeof(ctx.pname), ctx.fname);
char buf[255];
if(ctx.type == InitConfigFileParser::Section)
- snprintf(buf, sizeof(buf), "%s", ctx.fname);
+ BaseString::snprintf(buf, sizeof(buf), "%s", ctx.fname);
if(ctx.type == InitConfigFileParser::DefaultSection)
- snprintf(buf, sizeof(buf), "%s DEFAULT", ctx.fname);
- snprintf(ctx.fname, sizeof(ctx.fname), buf);
+ BaseString::snprintf(buf, sizeof(buf), "%s DEFAULT", ctx.fname);
+ BaseString::snprintf(ctx.fname, sizeof(ctx.fname), buf);
if(ctx.type == InitConfigFileParser::Section){
for(int i = 0; i<m_info->m_NoOfRules; i++){
const ConfigInfo::SectionRule & rule = m_info->m_SectionRules[i];
@@ -579,7 +581,7 @@ InitConfigFileParser::Context::reportError(const char * fmt, ...){
va_start(ap, fmt);
if (fmt != 0)
- vsnprintf(buf, sizeof(buf)-1, fmt, ap);
+ BaseString::vsnprintf(buf, sizeof(buf)-1, fmt, ap);
ndbout << "Error line " << m_lineno << ": " << buf << endl;
va_end(ap);
@@ -593,7 +595,7 @@ InitConfigFileParser::Context::reportWarning(const char * fmt, ...){
va_start(ap, fmt);
if (fmt != 0)
- vsnprintf(buf, sizeof(buf)-1, fmt, ap);
+ BaseString::vsnprintf(buf, sizeof(buf)-1, fmt, ap);
ndbout << "Warning line " << m_lineno << ": " << buf << endl;
va_end(ap);
}
diff --git a/ndb/src/mgmsrv/MgmtSrvr.cpp b/ndb/src/mgmsrv/MgmtSrvr.cpp
index 92a8025295f..fdaa61973d8 100644
--- a/ndb/src/mgmsrv/MgmtSrvr.cpp
+++ b/ndb/src/mgmsrv/MgmtSrvr.cpp
@@ -123,7 +123,7 @@ MgmtSrvr::signalRecvThreadRun()
while(!_isStopThread) {
SigMatch *handler = NULL;
NdbApiSignal *signal = NULL;
- if(m_signalRecvQueue.waitFor(siglist, handler, signal)) {
+ if(m_signalRecvQueue.waitFor(siglist, handler, signal, DEFAULT_TIMEOUT)) {
if(handler->function != 0)
(this->*handler->function)(signal);
}
@@ -1825,7 +1825,7 @@ const char* MgmtSrvr::getErrorText(int errorCode)
}
}
- snprintf(text, 255, "Unknown management server error code %d", errorCode);
+ BaseString::snprintf(text, 255, "Unknown management server error code %d", errorCode);
return text;
}
diff --git a/ndb/src/mgmsrv/Services.cpp b/ndb/src/mgmsrv/Services.cpp
index 5242237a638..201168c1726 100644
--- a/ndb/src/mgmsrv/Services.cpp
+++ b/ndb/src/mgmsrv/Services.cpp
@@ -1008,8 +1008,9 @@ MgmApiSession::stop(Parser<MgmApiSession>::Context &,
}
int stop_self= 0;
+ size_t i;
- for(size_t i=0; i < nodes.size(); i++) {
+ for(i=0; i < nodes.size(); i++) {
if (nodes[i] == m_mgmsrv.getOwnNodeId()) {
stop_self= 1;
if (i != nodes.size()-1) {
@@ -1023,7 +1024,7 @@ MgmApiSession::stop(Parser<MgmApiSession>::Context &,
int stopped = 0, result = 0;
- for(size_t i=0; i < nodes.size(); i++)
+ for(i=0; i < nodes.size(); i++)
if (nodes[i] != m_mgmsrv.getOwnNodeId()) {
if((result = m_mgmsrv.stopNode(nodes[i], abort != 0)) == 0)
stopped++;
@@ -1122,7 +1123,7 @@ MgmApiSession::logSignals(Parser<MgmApiSession>::Context &,
args.get("blocks", blockList);
// fast fix - pekka
char buf[200];
- snprintf(buf, 200, "%s", blockList.c_str());
+ BaseString::snprintf(buf, 200, "%s", blockList.c_str());
Vector<BaseString> blocks;
blockName=strtok(buf,"|");
@@ -1252,8 +1253,9 @@ MgmStatService::log(int eventType, const Uint32* theData, NodeId nodeId){
Uint32 threshold = 0;
LogLevel::EventCategory cat;
-
- for(unsigned i = 0; i<EventLogger::matrixSize; i++){
+ int i;
+
+ for(i = 0; (unsigned)i<EventLogger::matrixSize; i++){
if(EventLogger::matrix[i].eventType == eventType){
cat = EventLogger::matrix[i].eventCategory;
threshold = EventLogger::matrix[i].threshold;
@@ -1266,7 +1268,6 @@ MgmStatService::log(int eventType, const Uint32* theData, NodeId nodeId){
Vector<NDB_SOCKET_TYPE> copy;
m_clients.lock();
- int i;
for(i = m_clients.size() - 1; i >= 0; i--){
if(threshold <= m_clients[i].m_logLevel.getLogLevel(cat)){
if(m_clients[i].m_socket >= 0 &&
@@ -1279,14 +1280,14 @@ MgmStatService::log(int eventType, const Uint32* theData, NodeId nodeId){
}
m_clients.unlock();
- for(i = 0; (unsigned)i<copy.size(); i++){
+ for(i = 0; (unsigned)i < copy.size(); i++){
NDB_CLOSE_SOCKET(copy[i]);
}
if(copy.size()){
LogLevel tmp; tmp.clear();
m_clients.lock();
- for(i = 0; i < m_clients.size(); i++){
+ for(i = 0; (unsigned)i < m_clients.size(); i++){
tmp.set_max(m_clients[i].m_logLevel);
}
m_clients.unlock();
diff --git a/ndb/src/mgmsrv/SignalQueue.cpp b/ndb/src/mgmsrv/SignalQueue.cpp
index 7003f5c0a89..08ad5f363a6 100644
--- a/ndb/src/mgmsrv/SignalQueue.cpp
+++ b/ndb/src/mgmsrv/SignalQueue.cpp
@@ -14,8 +14,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-#include <string.h>
-
+#include <ndb_global.h>
#include "SignalQueue.hpp"
SignalQueue::SignalQueue() {
diff --git a/ndb/src/mgmsrv/main.cpp b/ndb/src/mgmsrv/main.cpp
index 1a2b95391a9..51282416c24 100644
--- a/ndb/src/mgmsrv/main.cpp
+++ b/ndb/src/mgmsrv/main.cpp
@@ -131,6 +131,7 @@ int num_args = sizeof(args) / sizeof(args[0]);
*/
NDB_MAIN(mgmsrv){
ndb_init();
+
/**
* OSE specific. Enable shared ownership of file system resources.
* This is needed in order to use the cluster log since the events
@@ -266,12 +267,12 @@ NDB_MAIN(mgmsrv){
mapi->setMgm(glob.mgmObject);
char msg[256];
- snprintf(msg, sizeof(msg),
+ BaseString::snprintf(msg, sizeof(msg),
"NDB Cluster Management Server. %s", NDB_VERSION_STRING);
ndbout_c(msg);
g_EventLogger.info(msg);
- snprintf(msg, 256, "Id: %d, Command port: %d",
+ BaseString::snprintf(msg, 256, "Id: %d, Command port: %d",
glob.localNodeId, glob.port);
ndbout_c(msg);
g_EventLogger.info(msg);
diff --git a/ndb/src/ndbapi/Ndb.cpp b/ndb/src/ndbapi/Ndb.cpp
index be8ba86c817..be0445bceb3 100644
--- a/ndb/src/ndbapi/Ndb.cpp
+++ b/ndb/src/ndbapi/Ndb.cpp
@@ -330,7 +330,7 @@ Ndb::startTransaction(Uint32 aPriority, const char * keyData, Uint32 keyLen)
{
NdbConnection *trans= startTransactionLocal(aPriority, nodeId);
DBUG_PRINT("exit",("start trans: 0x%x transid: 0x%llx",
- trans, trans->getTransactionId()));
+ trans, trans ? trans->getTransactionId() : 0));
DBUG_RETURN(trans);
}
} else {
@@ -371,6 +371,7 @@ Ndb::hupp(NdbConnection* pBuddyTrans)
// We could not get a connection to the desired node
// release the connection and return NULL
closeTransaction(pCon);
+ theError.code = 4006;
DBUG_RETURN(NULL);
}
pCon->setTransactionId(pBuddyTrans->getTransactionId());
@@ -1157,10 +1158,10 @@ const char * Ndb::getCatalogName() const
void Ndb::setCatalogName(const char * a_catalog_name)
{
if (a_catalog_name) {
- snprintf(theDataBase, sizeof(theDataBase), "%s",
+ BaseString::snprintf(theDataBase, sizeof(theDataBase), "%s",
a_catalog_name ? a_catalog_name : "");
- int len = snprintf(prefixName, sizeof(prefixName), "%s%c%s%c",
+ int len = BaseString::snprintf(prefixName, sizeof(prefixName), "%s%c%s%c",
theDataBase, table_name_separator,
theDataBaseSchema, table_name_separator);
prefixEnd = prefixName + (len < (int) sizeof(prefixName) ? len :
@@ -1176,10 +1177,10 @@ const char * Ndb::getSchemaName() const
void Ndb::setSchemaName(const char * a_schema_name)
{
if (a_schema_name) {
- snprintf(theDataBaseSchema, sizeof(theDataBase), "%s",
+ BaseString::snprintf(theDataBaseSchema, sizeof(theDataBase), "%s",
a_schema_name ? a_schema_name : "");
- int len = snprintf(prefixName, sizeof(prefixName), "%s%c%s%c",
+ int len = BaseString::snprintf(prefixName, sizeof(prefixName), "%s%c%s%c",
theDataBase, table_name_separator,
theDataBaseSchema, table_name_separator);
prefixEnd = prefixName + (len < (int) sizeof(prefixName) ? len :
diff --git a/ndb/src/ndbapi/NdbApiSignal.cpp b/ndb/src/ndbapi/NdbApiSignal.cpp
index d7b2b74b2bf..a1d34896968 100644
--- a/ndb/src/ndbapi/NdbApiSignal.cpp
+++ b/ndb/src/ndbapi/NdbApiSignal.cpp
@@ -168,7 +168,7 @@ NdbApiSignal::setSignal(int aNdbSignalType)
theTrace = TestOrd::TraceAPI;
theReceiversBlockNumber = DBTC;
theVerId_signalNumber = GSN_TC_COMMITREQ;
- theLength = 5;
+ theLength = 3;
}
break;
diff --git a/ndb/src/ndbapi/NdbBlob.cpp b/ndb/src/ndbapi/NdbBlob.cpp
index 7939f54d846..feab95d8ca5 100644
--- a/ndb/src/ndbapi/NdbBlob.cpp
+++ b/ndb/src/ndbapi/NdbBlob.cpp
@@ -867,7 +867,7 @@ NdbBlob::readParts(char* buf, Uint32 part, Uint32 count)
while (n < count) {
NdbOperation* tOp = theNdbCon->getNdbOperation(theBlobTable);
if (tOp == NULL ||
- tOp->readTuple() == -1 ||
+ tOp->committedRead() == -1 ||
setPartKeyValue(tOp, part + n) == -1 ||
tOp->getValue((Uint32)3, buf) == NULL) {
setErrorCode(tOp);
@@ -1440,11 +1440,11 @@ NdbOut&
operator<<(NdbOut& out, const NdbBlob& blob)
{
ndbout << dec << "o=" << blob.getOperationType();
- ndbout << dec << " s=" << blob.theState;
+ ndbout << dec << " s=" << (Uint32) blob.theState;
ndbout << dec << " n=" << blob.theNullFlag;;
ndbout << dec << " l=" << blob.theLength;
ndbout << dec << " p=" << blob.thePos;
- ndbout << dec << " u=" << blob.theHeadInlineUpdateFlag;
+ ndbout << dec << " u=" << (Uint32) blob.theHeadInlineUpdateFlag;
return out;
}
#endif
diff --git a/ndb/src/ndbapi/NdbConnection.cpp b/ndb/src/ndbapi/NdbConnection.cpp
index 8ab0d13c67f..1457792cf28 100644
--- a/ndb/src/ndbapi/NdbConnection.cpp
+++ b/ndb/src/ndbapi/NdbConnection.cpp
@@ -83,6 +83,11 @@ NdbConnection::NdbConnection( Ndb* aNdb ) :
theListState = NotInList;
theError.code = 0;
theId = theNdb->theNdbObjectIdMap->map(this);
+
+#define CHECK_SZ(mask, sz) assert((sizeof(mask)/sizeof(mask[0])) == sz)
+
+ CHECK_SZ(m_db_nodes, NdbNodeBitmask::Size);
+ CHECK_SZ(m_failed_db_nodes, NdbNodeBitmask::Size);
}//NdbConnection::NdbConnection()
/*****************************************************************************
@@ -308,8 +313,8 @@ NdbConnection::execute(ExecType aTypeOfExec,
tPrepOp = tPrepOp->next();
}
// save rest of prepared ops if batch
- NdbOperation* tRestOp;
- NdbOperation* tLastOp;
+ NdbOperation* tRestOp= 0;
+ NdbOperation* tLastOp= 0;
if (tPrepOp != NULL) {
tRestOp = tPrepOp->next();
tPrepOp->next(NULL);
@@ -490,11 +495,6 @@ NdbConnection::executeAsynchPrepare( ExecType aTypeOfExec,
theListState = InPreparedList;
tNdb->theNoOfPreparedTransactions = tnoOfPreparedTransactions + 1;
- if(tCommitStatus == Committed){
- tCommitStatus = Started;
- tTransactionIsStarted = false;
- }
-
if ((tCommitStatus != Started) ||
(aTypeOfExec == Rollback)) {
/*****************************************************************************
@@ -503,7 +503,7 @@ NdbConnection::executeAsynchPrepare( ExecType aTypeOfExec,
* same action.
****************************************************************************/
if (aTypeOfExec == Rollback) {
- if (theTransactionIsStarted == false) {
+ if (theTransactionIsStarted == false || theSimpleState) {
theCommitStatus = Aborted;
theSendStatus = sendCompleted;
} else {
@@ -528,7 +528,7 @@ NdbConnection::executeAsynchPrepare( ExecType aTypeOfExec,
tLastOp->theCommitIndicator = 1;
}//if
} else {
- if (aTypeOfExec == Commit) {
+ if (aTypeOfExec == Commit && !theSimpleState) {
/**********************************************************************
* A Transaction have been started and no more operations exist.
* We will use the commit method.
@@ -610,6 +610,8 @@ NdbConnection::executeAsynchPrepare( ExecType aTypeOfExec,
theNoOfOpSent = 0;
theNoOfOpCompleted = 0;
theSendStatus = sendOperations;
+ NdbNodeBitmask::clear(m_db_nodes);
+ NdbNodeBitmask::clear(m_failed_db_nodes);
DBUG_VOID_RETURN;
}//NdbConnection::executeAsynchPrepare()
@@ -728,7 +730,8 @@ NdbConnection::doSend()
theNdb->insert_completed_list(this);
DBUG_RETURN(0);
default:
- ndbout << "Inconsistent theSendStatus = " << theSendStatus << endl;
+ ndbout << "Inconsistent theSendStatus = "
+ << (Uint32) theSendStatus << endl;
abort();
break;
}//switch
@@ -1115,15 +1118,8 @@ NdbConnection::getNdbScanOperation(const NdbTableImpl * tab)
if (tOp == NULL)
goto getNdbOp_error1;
- // Link scan operation into list of cursor operations
- if (m_theLastScanOperation == NULL)
- m_theFirstScanOperation = m_theLastScanOperation = tOp;
- else {
- m_theLastScanOperation->next(tOp);
- m_theLastScanOperation = tOp;
- }
- tOp->next(NULL);
if (tOp->init(tab, this) != -1) {
+ define_scan_op(tOp);
return tOp;
} else {
theNdb->releaseScanOperation(tOp);
@@ -1135,6 +1131,31 @@ getNdbOp_error1:
return NULL;
}//NdbConnection::getNdbScanOperation()
+void
+NdbConnection::remove_list(NdbOperation*& list, NdbOperation* op){
+ NdbOperation* tmp= list;
+ if(tmp == op)
+ list = op->next();
+ else {
+ while(tmp && tmp->next() != op) tmp = tmp->next();
+ if(tmp)
+ tmp->next(op->next());
+ }
+ op->next(NULL);
+}
+
+void
+NdbConnection::define_scan_op(NdbIndexScanOperation * tOp){
+ // Link scan operation into list of cursor operations
+ if (m_theLastScanOperation == NULL)
+ m_theFirstScanOperation = m_theLastScanOperation = tOp;
+ else {
+ m_theLastScanOperation->next(tOp);
+ m_theLastScanOperation = tOp;
+ }
+ tOp->next(NULL);
+}
+
NdbScanOperation*
NdbConnection::getNdbScanOperation(const NdbDictionary::Table * table)
{
@@ -1517,12 +1538,21 @@ from other transactions.
const Uint32* tPtr = (Uint32 *)&keyConf->operations[0];
Uint32 tNoComp = theNoOfOpCompleted;
for (Uint32 i = 0; i < tNoOfOperations ; i++) {
- tOp = theNdb->void2rec(theNdb->int2void(*tPtr));
- tPtr++;
- const Uint32 tAttrInfoLen = *tPtr;
- tPtr++;
+ tOp = theNdb->void2rec(theNdb->int2void(*tPtr++));
+ const Uint32 tAttrInfoLen = *tPtr++;
if (tOp && tOp->checkMagicNumber()) {
- tNoComp += tOp->execTCOPCONF(tAttrInfoLen);
+ Uint32 done = tOp->execTCOPCONF(tAttrInfoLen);
+ if(tAttrInfoLen > TcKeyConf::SimpleReadBit){
+ Uint32 node = tAttrInfoLen & (~TcKeyConf::SimpleReadBit);
+ NdbNodeBitmask::set(m_db_nodes, node);
+ if(NdbNodeBitmask::get(m_failed_db_nodes, node) && !done)
+ {
+ done = 1;
+ tOp->setErrorCode(4119);
+ theCompletionStatus = CompletedFailure;
+ }
+ }
+ tNoComp += done;
} else {
return -1;
}//if
@@ -1614,6 +1644,10 @@ NdbConnection::receiveTCKEY_FAILCONF(const TcKeyFailConf * failConf)
setOperationErrorCodeAbort(4115);
tOp = NULL;
break;
+ case NdbOperation::NotDefined:
+ case NdbOperation::NotDefined2:
+ assert(false);
+ break;
}//if
}//while
theReleaseOnClose = true;
@@ -1772,7 +1806,7 @@ Parameters: aErrorCode: The error code.
Remark: An operation was completed with failure.
*******************************************************************************/
int
-NdbConnection::OpCompleteFailure()
+NdbConnection::OpCompleteFailure(Uint8 abortOption)
{
Uint32 tNoComp = theNoOfOpCompleted;
Uint32 tNoSent = theNoOfOpSent;
@@ -1786,10 +1820,7 @@ NdbConnection::OpCompleteFailure()
//decide the success of the whole transaction since a simple
//operation is not really part of that transaction.
//------------------------------------------------------------------------
- if (theSimpleState == 1) {
- theCommitStatus = NdbConnection::Aborted;
- }//if
- if (m_abortOption == IgnoreError){
+ if (abortOption == IgnoreError){
/**
* There's always a TCKEYCONF when using IgnoreError
*/
@@ -1824,9 +1855,6 @@ NdbConnection::OpCompleteSuccess()
tNoComp++;
theNoOfOpCompleted = tNoComp;
if (tNoComp == tNoSent) { // Last operation completed
- if (theSimpleState == 1) {
- theCommitStatus = NdbConnection::Committed;
- }//if
return 0;
} else if (tNoComp < tNoSent) {
return -1; // Continue waiting for more signals
@@ -1901,14 +1929,14 @@ NdbConnection::printState()
CASE(Connected);
CASE(DisConnecting);
CASE(ConnectFailure);
- default: ndbout << theStatus;
+ default: ndbout << (Uint32) theStatus;
}
switch (theListState) {
CASE(NotInList);
CASE(InPreparedList);
CASE(InSendList);
CASE(InCompletedList);
- default: ndbout << theListState;
+ default: ndbout << (Uint32) theListState;
}
switch (theSendStatus) {
CASE(NotInit);
@@ -1921,7 +1949,7 @@ NdbConnection::printState()
CASE(sendTC_ROLLBACK);
CASE(sendTC_COMMIT);
CASE(sendTC_OP);
- default: ndbout << theSendStatus;
+ default: ndbout << (Uint32) theSendStatus;
}
switch (theCommitStatus) {
CASE(NotStarted);
@@ -1929,16 +1957,56 @@ NdbConnection::printState()
CASE(Committed);
CASE(Aborted);
CASE(NeedAbort);
- default: ndbout << theCommitStatus;
+ default: ndbout << (Uint32) theCommitStatus;
}
switch (theCompletionStatus) {
CASE(NotCompleted);
CASE(CompletedSuccess);
CASE(CompletedFailure);
CASE(DefinitionFailure);
- default: ndbout << theCompletionStatus;
+ default: ndbout << (Uint32) theCompletionStatus;
}
ndbout << endl;
}
#undef CASE
#endif
+
+int
+NdbConnection::report_node_failure(Uint32 id){
+ NdbNodeBitmask::set(m_failed_db_nodes, id);
+ if(!NdbNodeBitmask::get(m_db_nodes, id))
+ {
+ return 0;
+ }
+
+ /**
+ * Arrived
+ * TCKEYCONF TRANSIDAI
+ * 1) - -
+ * 2) - X
+ * 3) X -
+ * 4) X X
+ */
+ NdbOperation* tmp = theFirstExecOpInList;
+ const Uint32 len = TcKeyConf::SimpleReadBit | id;
+ Uint32 tNoComp = theNoOfOpCompleted;
+ Uint32 tNoSent = theNoOfOpSent;
+ while(tmp != 0)
+ {
+ if(tmp->theReceiver.m_expected_result_length == len &&
+ tmp->theReceiver.m_received_result_length == 0)
+ {
+ tNoComp++;
+ tmp->theError.code = 4119;
+ }
+ tmp = tmp->next();
+ }
+ theNoOfOpCompleted = tNoComp;
+ if(tNoComp == tNoSent)
+ {
+ theError.code = 4119;
+ theCompletionStatus = NdbConnection::CompletedFailure;
+ return 1;
+ }
+ return 0;
+}
diff --git a/ndb/src/ndbapi/NdbDictionaryImpl.cpp b/ndb/src/ndbapi/NdbDictionaryImpl.cpp
index 5e640cdebd5..cf51a30fe0b 100644
--- a/ndb/src/ndbapi/NdbDictionaryImpl.cpp
+++ b/ndb/src/ndbapi/NdbDictionaryImpl.cpp
@@ -148,6 +148,9 @@ NdbColumnImpl::init(Type t)
m_length = 4;
m_cs = default_cs;
break;
+ case Undefined:
+ assert(false);
+ break;
}
m_pk = false;
m_nullable = false;
@@ -1466,7 +1469,7 @@ NdbDictInterface::createOrAlterTable(Ndb & ndb,
impl.m_internalName.assign(internalName);
UtilBufferWriter w(m_buffer);
DictTabInfo::Table tmpTab; tmpTab.init();
- snprintf(tmpTab.TableName,
+ BaseString::snprintf(tmpTab.TableName,
sizeof(tmpTab.TableName),
internalName);
@@ -1522,7 +1525,7 @@ NdbDictInterface::createOrAlterTable(Ndb & ndb,
continue;
DictTabInfo::Attribute tmpAttr; tmpAttr.init();
- snprintf(tmpAttr.AttributeName, sizeof(tmpAttr.AttributeName),
+ BaseString::snprintf(tmpAttr.AttributeName, sizeof(tmpAttr.AttributeName),
col->m_name.c_str());
tmpAttr.AttributeId = i;
tmpAttr.AttributeKeyFlag = col->m_pk || col->m_tupleKey;
@@ -1557,7 +1560,7 @@ NdbDictInterface::createOrAlterTable(Ndb & ndb,
(void)tmpAttr.translateExtType();
tmpAttr.AttributeAutoIncrement = col->m_autoIncrement;
- snprintf(tmpAttr.AttributeDefaultValue,
+ BaseString::snprintf(tmpAttr.AttributeDefaultValue,
sizeof(tmpAttr.AttributeDefaultValue),
col->m_defaultValue.c_str());
s = SimpleProperties::pack(w,
diff --git a/ndb/src/ndbapi/NdbIndexOperation.cpp b/ndb/src/ndbapi/NdbIndexOperation.cpp
index c62f6962e25..83de6d9ef87 100644
--- a/ndb/src/ndbapi/NdbIndexOperation.cpp
+++ b/ndb/src/ndbapi/NdbIndexOperation.cpp
@@ -87,7 +87,19 @@ NdbIndexOperation::indxInit(const NdbIndexImpl * anIndex,
int NdbIndexOperation::readTuple(NdbOperation::LockMode lm)
{
- return NdbOperation::readTuple(lm);
+ switch(lm) {
+ case LM_Read:
+ return readTuple();
+ break;
+ case LM_Exclusive:
+ return readTupleExclusive();
+ break;
+ case LM_CommittedRead:
+ return readTuple();
+ break;
+ default:
+ return -1;
+ };
}
int NdbIndexOperation::readTuple()
@@ -108,21 +120,21 @@ int NdbIndexOperation::simpleRead()
{
// First check that index is unique
- return NdbOperation::simpleRead();
+ return NdbOperation::readTuple();
}
int NdbIndexOperation::dirtyRead()
{
// First check that index is unique
- return NdbOperation::dirtyRead();
+ return NdbOperation::readTuple();
}
int NdbIndexOperation::committedRead()
{
// First check that index is unique
- return NdbOperation::committedRead();
+ return NdbOperation::readTuple();
}
int NdbIndexOperation::updateTuple()
@@ -536,7 +548,7 @@ NdbIndexOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64 aTransactionId)
//-------------------------------------------------------------
Uint8 tReadInd = (theOperationType == ReadRequest);
Uint8 tSimpleState = tReadInd & tSimpleAlt;
- theNdbCon->theSimpleState = tSimpleState;
+ //theNdbCon->theSimpleState = tSimpleState;
tcIndxReq->transId1 = tTransId1;
tcIndxReq->transId2 = tTransId2;
@@ -723,23 +735,10 @@ NdbIndexOperation::receiveTCINDXREF( NdbApiSignal* aSignal)
theStatus = Finished;
theNdbCon->theReturnStatus = NdbConnection::ReturnFailure;
- //--------------------------------------------------------------------------//
- // If the transaction this operation belongs to consists only of simple reads
- // we set the error code on the transaction object.
- // If the transaction consists of other types of operations we set
- // the error code only on the operation since the simple read is not really
- // part of this transaction and we can not decide the status of the whole
- // transaction based on this operation.
- //--------------------------------------------------------------------------//
Uint32 errorCode = tcIndxRef->errorCode;
- if (theNdbCon->theSimpleState == 0) {
- theError.code = errorCode;
- theNdbCon->setOperationErrorCodeAbort(errorCode);
- return theNdbCon->OpCompleteFailure();
- } else {
- theError.code = errorCode;
- return theNdbCon->OpCompleteSuccess();
- }
+ theError.code = errorCode;
+ theNdbCon->setOperationErrorCodeAbort(errorCode);
+ return theNdbCon->OpCompleteFailure(theNdbCon->m_abortOption);
}//NdbIndexOperation::receiveTCINDXREF()
diff --git a/ndb/src/ndbapi/NdbOperation.cpp b/ndb/src/ndbapi/NdbOperation.cpp
index 53a94d98a5a..b0b95d0ff43 100644
--- a/ndb/src/ndbapi/NdbOperation.cpp
+++ b/ndb/src/ndbapi/NdbOperation.cpp
@@ -78,7 +78,6 @@ NdbOperation::NdbOperation(Ndb* aNdb) :
m_tcReqGSN(GSN_TCKEYREQ),
m_keyInfoGSN(GSN_KEYINFO),
m_attrInfoGSN(GSN_ATTRINFO),
- theBoundATTRINFO(NULL),
theBlobList(NULL)
{
theReceiver.init(NdbReceiver::NDB_OPERATION, this);
@@ -167,7 +166,6 @@ NdbOperation::init(const NdbTableImpl* tab, NdbConnection* myConnection){
theScanInfo = 0;
theTotalNrOfKeyWordInSignal = 8;
theMagicNumber = 0xABCDEF01;
- theBoundATTRINFO = NULL;
theBlobList = NULL;
tSignal = theNdb->getSignal();
@@ -263,14 +261,6 @@ NdbOperation::release()
tSubroutine = tSubroutine->theNext;
theNdb->releaseNdbSubroutine(tSaveSubroutine);
}
- tSignal = theBoundATTRINFO;
- while (tSignal != NULL)
- {
- tSaveSignal = tSignal;
- tSignal = tSignal->next();
- theNdb->releaseSignal(tSaveSignal);
- }
- theBoundATTRINFO = NULL;
}
tBlob = theBlobList;
while (tBlob != NULL)
diff --git a/ndb/src/ndbapi/NdbOperationDefine.cpp b/ndb/src/ndbapi/NdbOperationDefine.cpp
index 1cbfedd21b1..35abb15b00d 100644
--- a/ndb/src/ndbapi/NdbOperationDefine.cpp
+++ b/ndb/src/ndbapi/NdbOperationDefine.cpp
@@ -55,6 +55,7 @@ NdbOperation::insertTuple()
theOperationType = InsertRequest;
tNdbCon->theSimpleState = 0;
theErrorLine = tErrorLine++;
+ theLockMode = LM_Exclusive;
return 0;
} else {
setErrorCode(4200);
@@ -74,6 +75,7 @@ NdbOperation::updateTuple()
tNdbCon->theSimpleState = 0;
theOperationType = UpdateRequest;
theErrorLine = tErrorLine++;
+ theLockMode = LM_Exclusive;
return 0;
} else {
setErrorCode(4200);
@@ -93,6 +95,7 @@ NdbOperation::writeTuple()
tNdbCon->theSimpleState = 0;
theOperationType = WriteRequest;
theErrorLine = tErrorLine++;
+ theLockMode = LM_Exclusive;
return 0;
} else {
setErrorCode(4200);
@@ -113,8 +116,10 @@ NdbOperation::readTuple(NdbOperation::LockMode lm)
return readTupleExclusive();
break;
case LM_CommittedRead:
- return readTuple();
+ return committedRead();
break;
+ default:
+ return -1;
};
}
/******************************************************************************
@@ -130,6 +135,7 @@ NdbOperation::readTuple()
tNdbCon->theSimpleState = 0;
theOperationType = ReadRequest;
theErrorLine = tErrorLine++;
+ theLockMode = LM_Read;
return 0;
} else {
setErrorCode(4200);
@@ -150,6 +156,7 @@ NdbOperation::deleteTuple()
tNdbCon->theSimpleState = 0;
theOperationType = DeleteRequest;
theErrorLine = tErrorLine++;
+ theLockMode = LM_Exclusive;
return 0;
} else {
setErrorCode(4200);
@@ -170,6 +177,7 @@ NdbOperation::readTupleExclusive()
tNdbCon->theSimpleState = 0;
theOperationType = ReadExclusive;
theErrorLine = tErrorLine++;
+ theLockMode = LM_Exclusive;
return 0;
} else {
setErrorCode(4200);
@@ -183,17 +191,24 @@ NdbOperation::readTupleExclusive()
int
NdbOperation::simpleRead()
{
+ /**
+ * Currently/still disabled
+ */
+ return readTuple();
+#if 0
int tErrorLine = theErrorLine;
if (theStatus == Init) {
theStatus = OperationDefined;
theOperationType = ReadRequest;
theSimpleIndicator = 1;
theErrorLine = tErrorLine++;
+ theLockMode = LM_Read;
return 0;
} else {
setErrorCode(4200);
return -1;
}//if
+#endif
}//NdbOperation::simpleRead()
/*****************************************************************************
@@ -218,6 +233,7 @@ NdbOperation::committedRead()
theSimpleIndicator = 1;
theDirtyIndicator = 1;
theErrorLine = tErrorLine++;
+ theLockMode = LM_CommittedRead;
return 0;
} else {
setErrorCode(4200);
@@ -240,6 +256,7 @@ NdbOperation::dirtyUpdate()
theSimpleIndicator = 1;
theDirtyIndicator = 1;
theErrorLine = tErrorLine++;
+ theLockMode = LM_CommittedRead;
return 0;
} else {
setErrorCode(4200);
@@ -262,6 +279,7 @@ NdbOperation::dirtyWrite()
theSimpleIndicator = 1;
theDirtyIndicator = 1;
theErrorLine = tErrorLine++;
+ theLockMode = LM_CommittedRead;
return 0;
} else {
setErrorCode(4200);
@@ -282,7 +300,7 @@ NdbOperation::interpretedUpdateTuple()
tNdbCon->theSimpleState = 0;
theOperationType = UpdateRequest;
theAI_LenInCurrAI = 25;
-
+ theLockMode = LM_Exclusive;
theErrorLine = tErrorLine++;
initInterpreter();
return 0;
@@ -307,7 +325,7 @@ NdbOperation::interpretedDeleteTuple()
theErrorLine = tErrorLine++;
theAI_LenInCurrAI = 25;
-
+ theLockMode = LM_Exclusive;
initInterpreter();
return 0;
} else {
@@ -334,10 +352,6 @@ NdbOperation::getValue_impl(const NdbColumnImpl* tAttrInfo, char* aValue)
if ((tAttrInfo != NULL) &&
(!tAttrInfo->m_indexOnly) &&
(theStatus != Init)){
- if (theStatus == SetBound) {
- ((NdbIndexScanOperation*)this)->saveBoundATTRINFO();
- theStatus = GetValue;
- }
if (theStatus != GetValue) {
if (theInterpretIndicator == 1) {
if (theStatus == FinalGetValue) {
diff --git a/ndb/src/ndbapi/NdbOperationExec.cpp b/ndb/src/ndbapi/NdbOperationExec.cpp
index cd89f953213..f1338ae01e4 100644
--- a/ndb/src/ndbapi/NdbOperationExec.cpp
+++ b/ndb/src/ndbapi/NdbOperationExec.cpp
@@ -161,28 +161,17 @@ NdbOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64 aTransId)
tTransId1 = (Uint32) aTransId;
tTransId2 = (Uint32) (aTransId >> 32);
-//-------------------------------------------------------------
-// Simple is simple if simple or both start and commit is set.
-//-------------------------------------------------------------
-// Temporarily disable simple stuff
- Uint8 tSimpleIndicator = 0;
-// Uint8 tSimpleIndicator = theSimpleIndicator;
+ 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;
+ Uint8 tInterpretIndicator = theInterpretIndicator;
//-------------------------------------------------------------
// 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;
+ Uint8 tSimpleState = tReadInd & tSimpleIndicator;
tcKeyReq->transId1 = tTransId1;
tcKeyReq->transId2 = tTransId2;
@@ -197,7 +186,6 @@ NdbOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64 aTransId)
tcKeyReq->setSimpleFlag(tReqInfo, tSimpleIndicator);
tcKeyReq->setCommitFlag(tReqInfo, tCommitIndicator);
tcKeyReq->setStartFlag(tReqInfo, tStartIndicator);
- const Uint8 tInterpretIndicator = theInterpretIndicator;
tcKeyReq->setInterpretedFlag(tReqInfo, tInterpretIndicator);
Uint8 tDirtyIndicator = theDirtyIndicator;
@@ -208,6 +196,9 @@ NdbOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64 aTransId)
tcKeyReq->setDirtyFlag(tReqInfo, tDirtyIndicator);
tcKeyReq->setOperationType(tReqInfo, tOperationType);
tcKeyReq->setKeyLength(tReqInfo, tTupKeyLen);
+
+ // A simple read is always ignore error
+ abortOption = tSimpleIndicator ? IgnoreError : abortOption;
tcKeyReq->setAbortOption(tReqInfo, abortOption);
Uint8 tDistrKeyIndicator = theDistrKeyIndicator;
@@ -550,27 +541,29 @@ NdbOperation::receiveTCKEYREF( NdbApiSignal* aSignal)
return -1;
}//if
+ AbortOption ao = (AbortOption)theNdbCon->m_abortOption;
+ theReceiver.m_received_result_length = ~0;
+
theStatus = Finished;
-
theNdbCon->theReturnStatus = NdbConnection::ReturnFailure;
- //-------------------------------------------------------------------------//
- // If the transaction this operation belongs to consists only of simple reads
- // we set the error code on the transaction object.
- // If the transaction consists of other types of operations we set
- // the error code only on the operation since the simple read is not really
- // part of this transaction and we can not decide the status of the whole
- // transaction based on this operation.
- //-------------------------------------------------------------------------//
- if (theNdbCon->theSimpleState == 0) {
- theError.code = aSignal->readData(4);
- theNdbCon->setOperationErrorCodeAbort(aSignal->readData(4));
- return theNdbCon->OpCompleteFailure();
- } else {
- theError.code = aSignal->readData(4);
- return theNdbCon->OpCompleteSuccess();
+
+ theError.code = aSignal->readData(4);
+ theNdbCon->setOperationErrorCodeAbort(aSignal->readData(4));
+
+ if(theOperationType != ReadRequest || !theSimpleIndicator) // not simple read
+ return theNdbCon->OpCompleteFailure(ao);
+
+ /**
+ * If TCKEYCONF has arrived
+ * op has completed (maybe trans has completed)
+ */
+ if(theReceiver.m_expected_result_length)
+ {
+ return theNdbCon->OpCompleteFailure(AbortOnError);
}
-}//NdbOperation::receiveTCKEYREF()
+ return -1;
+}
void
diff --git a/ndb/src/ndbapi/NdbOperationInt.cpp b/ndb/src/ndbapi/NdbOperationInt.cpp
index f5d334fd79a..ee7b8132cd1 100644
--- a/ndb/src/ndbapi/NdbOperationInt.cpp
+++ b/ndb/src/ndbapi/NdbOperationInt.cpp
@@ -216,10 +216,6 @@ int
NdbOperation::initial_interpreterCheck()
{
if ((theInterpretIndicator == 1)) {
- if (theStatus == SetBound) {
- ((NdbIndexScanOperation*)this)->saveBoundATTRINFO();
- theStatus = GetValue;
- }
if (theStatus == ExecInterpretedValue) {
return 0; // Simply continue with interpretation
} else if (theStatus == GetValue) {
diff --git a/ndb/src/ndbapi/NdbOperationSearch.cpp b/ndb/src/ndbapi/NdbOperationSearch.cpp
index e5166fc4a82..0d3130fffd0 100644
--- a/ndb/src/ndbapi/NdbOperationSearch.cpp
+++ b/ndb/src/ndbapi/NdbOperationSearch.cpp
@@ -543,7 +543,8 @@ NdbOperation::getKeyFromTCREQ(Uint32* data, unsigned size)
assert(m_accessTable->m_sizeOfKeysInWords == size);
unsigned pos = 0;
while (pos < 8 && pos < size) {
- data[pos++] = theKEYINFOptr[pos];
+ data[pos] = theKEYINFOptr[pos];
+ pos++;
}
NdbApiSignal* tSignal = theFirstKEYINFO;
unsigned n = 0;
diff --git a/ndb/src/ndbapi/NdbReceiver.cpp b/ndb/src/ndbapi/NdbReceiver.cpp
index caeeac80093..14f8d4b8440 100644
--- a/ndb/src/ndbapi/NdbReceiver.cpp
+++ b/ndb/src/ndbapi/NdbReceiver.cpp
@@ -22,6 +22,7 @@
#include <AttributeHeader.hpp>
#include <NdbConnection.hpp>
#include <TransporterFacade.hpp>
+#include <signaldata/TcKeyConf.hpp>
NdbReceiver::NdbReceiver(Ndb *aNdb) :
theMagicNumber(0),
@@ -91,7 +92,7 @@ NdbReceiver::getValue(const NdbColumnImpl* tAttrInfo, char * user_dst_ptr){
return 0;
}
-#define KEY_ATTR_ID (~0)
+#define KEY_ATTR_ID (~(Uint32)0)
void
NdbReceiver::calculate_batch_size(Uint32 key_size,
@@ -249,10 +250,11 @@ NdbReceiver::execTRANSID_AI(const Uint32* aDataPtr, Uint32 aLength)
/**
* Update m_received_result_length
*/
+ Uint32 exp = m_expected_result_length;
Uint32 tmp = m_received_result_length + aLength;
m_received_result_length = tmp;
- return (tmp == m_expected_result_length ? 1 : 0);
+ return (tmp == exp || (exp > TcKeyConf::SimpleReadBit) ? 1 : 0);
}
int
@@ -272,3 +274,11 @@ NdbReceiver::execKEYINFO20(Uint32 info, const Uint32* aDataPtr, Uint32 aLength)
return (tmp == m_expected_result_length ? 1 : 0);
}
+
+void
+NdbReceiver::setErrorCode(int code)
+{
+ theMagicNumber = 0;
+ NdbOperation* op = (NdbOperation*)getOwner();
+ op->setErrorCode(code);
+}
diff --git a/ndb/src/ndbapi/NdbScanOperation.cpp b/ndb/src/ndbapi/NdbScanOperation.cpp
index 3ff2a32d418..fd63ce96f25 100644
--- a/ndb/src/ndbapi/NdbScanOperation.cpp
+++ b/ndb/src/ndbapi/NdbScanOperation.cpp
@@ -32,6 +32,7 @@
#include <signaldata/ScanTab.hpp>
#include <signaldata/KeyInfo.hpp>
+#include <signaldata/AttrInfo.hpp>
#include <signaldata/TcKeyReq.hpp>
NdbScanOperation::NdbScanOperation(Ndb* aNdb) :
@@ -116,10 +117,8 @@ NdbScanOperation::init(const NdbTableImpl* tab, NdbConnection* myConnection)
theStatus = GetValue;
theOperationType = OpenScanRequest;
-
- theTotalBoundAI_Len = 0;
- theBoundATTRINFO = NULL;
-
+ theNdbCon->theMagicNumber = 0xFE11DF;
+
return 0;
}
@@ -145,6 +144,7 @@ NdbResultSet* NdbScanOperation::readTuples(NdbScanOperation::LockMode lm,
}
theNdbCon->theScanningOp = this;
+ theLockMode = lm;
bool lockExcl, lockHoldMode, readCommitted;
switch(lm){
@@ -168,7 +168,7 @@ NdbResultSet* NdbScanOperation::readTuples(NdbScanOperation::LockMode lm,
return 0;
}
- m_keyInfo = lockExcl;
+ m_keyInfo = lockExcl ? 1 : 0;
bool range = false;
if (m_accessTable->m_indexType == NdbDictionary::Index::OrderedIndex ||
@@ -181,7 +181,7 @@ NdbResultSet* NdbScanOperation::readTuples(NdbScanOperation::LockMode lm,
}
assert (m_currentTable != m_accessTable);
// Modify operation state
- theStatus = SetBound;
+ theStatus = GetValue;
theOperationType = OpenRangeScanRequest;
range = true;
}
@@ -219,8 +219,17 @@ NdbResultSet* NdbScanOperation::readTuples(NdbScanOperation::LockMode lm,
req->transId1 = (Uint32) transId;
req->transId2 = (Uint32) (transId >> 32);
- getFirstATTRINFOScan();
+ NdbApiSignal* tSignal =
+ theFirstKEYINFO;
+ theFirstKEYINFO = (tSignal ? tSignal : tSignal = theNdb->getSignal());
+ theLastKEYINFO = tSignal;
+
+ tSignal->setSignal(GSN_KEYINFO);
+ theKEYINFOptr = ((KeyInfo*)tSignal->getDataPtrSend())->keyData;
+ theTotalNrOfKeyWordInSignal= 0;
+
+ getFirstATTRINFOScan();
return getResultSet();
}
@@ -256,18 +265,7 @@ NdbScanOperation::fix_receivers(Uint32 parallel){
m_allocated_receivers = parallel;
}
- for(Uint32 i = 0; i<parallel; i++){
- m_receivers[i]->m_list_index = i;
- m_prepared_receivers[i] = m_receivers[i]->getId();
- m_sent_receivers[i] = m_receivers[i];
- m_conf_receivers[i] = 0;
- m_api_receivers[i] = 0;
- }
-
- m_api_receivers_count = 0;
- m_current_api_receiver = 0;
- m_sent_receivers_count = parallel;
- m_conf_receivers_count = 0;
+ reset_receivers(parallel, 0);
return 0;
}
@@ -355,6 +353,7 @@ NdbScanOperation::getFirstATTRINFOScan()
* After setBound() are done, move the accumulated ATTRINFO signals to
* a separate list. Then continue with normal scan.
*/
+#if 0
int
NdbIndexScanOperation::saveBoundATTRINFO()
{
@@ -401,6 +400,7 @@ NdbIndexScanOperation::saveBoundATTRINFO()
}
return res;
}
+#endif
#define WAITFOR_SCAN_TIMEOUT 120000
@@ -409,14 +409,22 @@ NdbScanOperation::executeCursor(int nodeId){
NdbConnection * tCon = theNdbCon;
TransporterFacade* tp = TransporterFacade::instance();
Guard guard(tp->theMutexPtr);
+
+ Uint32 magic = tCon->theMagicNumber;
Uint32 seq = tCon->theNodeSequence;
+
if (tp->get_node_alive(nodeId) &&
(tp->getNodeSequence(nodeId) == seq)) {
-
- if(prepareSendScan(tCon->theTCConPtr, tCon->theTransactionId) == -1)
- return -1;
+ /**
+ * Only call prepareSendScan first time (incase of restarts)
+ * - check with theMagicNumber
+ */
tCon->theMagicNumber = 0x37412619;
+ if(magic != 0x37412619 &&
+ prepareSendScan(tCon->theTCConPtr, tCon->theTransactionId) == -1)
+ return -1;
+
if (doSendScan(nodeId) == -1)
return -1;
@@ -428,7 +436,6 @@ NdbScanOperation::executeCursor(int nodeId){
TRACE_DEBUG("The node is hard dead when attempting to start a scan");
setErrorCode(4029);
tCon->theReleaseOnClose = true;
- abort();
} else {
TRACE_DEBUG("The node is stopping when attempting to start a scan");
setErrorCode(4030);
@@ -559,6 +566,8 @@ int NdbScanOperation::nextResult(bool fetchAllowed)
setErrorCode(4028); // Node fail
break;
case -3: // send_next_scan -> return fail (set error-code self)
+ if(theError.code == 0)
+ setErrorCode(4028); // seq changed = Node fail
break;
}
@@ -635,7 +644,7 @@ NdbScanOperation::doSend(int ProcessorId)
void NdbScanOperation::closeScan()
{
- if(m_transConnection) do {
+ if(m_transConnection){
if(DEBUG_NEXT_RESULT)
ndbout_c("closeScan() theError.code = %d "
"m_api_receivers_count = %d "
@@ -648,55 +657,8 @@ void NdbScanOperation::closeScan()
TransporterFacade* tp = TransporterFacade::instance();
Guard guard(tp->theMutexPtr);
-
- Uint32 seq = theNdbCon->theNodeSequence;
- Uint32 nodeId = theNdbCon->theDBnode;
-
- if(seq != tp->getNodeSequence(nodeId)){
- theNdbCon->theReleaseOnClose = true;
- break;
- }
-
- while(theError.code == 0 && m_sent_receivers_count){
- theNdb->theWaiter.m_node = nodeId;
- theNdb->theWaiter.m_state = WAIT_SCAN;
- int return_code = theNdb->receiveResponse(WAITFOR_SCAN_TIMEOUT);
- switch(return_code){
- case 0:
- break;
- case -1:
- setErrorCode(4008);
- case -2:
- m_api_receivers_count = 0;
- m_conf_receivers_count = 0;
- m_sent_receivers_count = 0;
- theNdbCon->theReleaseOnClose = true;
- }
- }
-
- if(m_api_receivers_count+m_conf_receivers_count){
- // Send close scan
- send_next_scan(0, true); // Close scan
- }
+ close_impl(tp);
- /**
- * wait for close scan conf
- */
- while(m_sent_receivers_count+m_api_receivers_count+m_conf_receivers_count){
- theNdb->theWaiter.m_node = nodeId;
- theNdb->theWaiter.m_state = WAIT_SCAN;
- int return_code = theNdb->receiveResponse(WAITFOR_SCAN_TIMEOUT);
- switch(return_code){
- case 0:
- break;
- case -1:
- setErrorCode(4008);
- case -2:
- m_api_receivers_count = 0;
- m_conf_receivers_count = 0;
- m_sent_receivers_count = 0;
- }
- }
} while(0);
theNdbCon->theScanningOp = 0;
@@ -750,11 +712,6 @@ int NdbScanOperation::prepareSendScan(Uint32 aTC_ConnectPtr,
return -1;
}
- if (theStatus == SetBound) {
- ((NdbIndexScanOperation*)this)->saveBoundATTRINFO();
- theStatus = GetValue;
- }
-
theErrorLine = 0;
// In preapareSendInterpreted we set the sizes (word 4-8) in the
@@ -766,26 +723,7 @@ int NdbScanOperation::prepareSendScan(Uint32 aTC_ConnectPtr,
((NdbIndexScanOperation*)this)->fix_get_values();
}
- const Uint32 transId1 = (Uint32) (aTransactionId & 0xFFFFFFFF);
- const Uint32 transId2 = (Uint32) (aTransactionId >> 32);
-
- if (theOperationType == OpenRangeScanRequest) {
- NdbApiSignal* tSignal = theBoundATTRINFO;
- do{
- tSignal->setData(aTC_ConnectPtr, 1);
- tSignal->setData(transId1, 2);
- tSignal->setData(transId2, 3);
- tSignal = tSignal->next();
- } while (tSignal != NULL);
- }
theCurrentATTRINFO->setLength(theAI_LenInCurrAI);
- NdbApiSignal* tSignal = theFirstATTRINFO;
- do{
- tSignal->setData(aTC_ConnectPtr, 1);
- tSignal->setData(transId1, 2);
- tSignal->setData(transId2, 3);
- tSignal = tSignal->next();
- } while (tSignal != NULL);
/**
* Prepare all receivers
@@ -808,20 +746,28 @@ int NdbScanOperation::prepareSendScan(Uint32 aTC_ConnectPtr,
req->batch_byte_size= batch_byte_size;
req->first_batch_size= first_batch_size;
+ /**
+ * Set keyinfo flag
+ * (Always keyinfo when using blobs)
+ */
+ Uint32 reqInfo = req->requestInfo;
+ ScanTabReq::setKeyinfoFlag(reqInfo, keyInfo);
+ req->requestInfo = reqInfo;
+
for(Uint32 i = 0; i<theParallelism; i++){
m_receivers[i]->do_get_value(&theReceiver, batch_size, key_size);
}
return 0;
}
-/******************************************************************************
+/*****************************************************************************
int doSend()
Return Value: Return >0 : send was succesful, returns number of signals sent
Return -1: In all other case.
Parameters: aProcessorId: Receiving processor node
Remark: Sends the ATTRINFO signal(s)
-******************************************************************************/
+*****************************************************************************/
int
NdbScanOperation::doSendScan(int aProcessorId)
{
@@ -841,13 +787,18 @@ NdbScanOperation::doSendScan(int aProcessorId)
setErrorCode(4001);
return -1;
}
+
+ Uint32 tupKeyLen = theTupKeyLen;
+ Uint32 len = theTotalNrOfKeyWordInSignal;
+ Uint32 aTC_ConnectPtr = theNdbCon->theTCConPtr;
+ Uint64 transId = theNdbCon->theTransactionId;
+
// Update the "attribute info length in words" in SCAN_TABREQ before
// sending it. This could not be done in openScan because
// we created the ATTRINFO signals after the SCAN_TABREQ signal.
ScanTabReq * const req = CAST_PTR(ScanTabReq, tSignal->getDataPtrSend());
- req->attrLen = theTotalCurrAI_Len;
- if (theOperationType == OpenRangeScanRequest)
- req->attrLen += theTotalBoundAI_Len;
+ req->attrLenKeyLen = (tupKeyLen << 16) | theTotalCurrAI_Len;
+
TransporterFacade *tp = TransporterFacade::instance();
LinearSectionPtr ptr[3];
ptr[0].p = m_prepared_receivers;
@@ -856,22 +807,41 @@ NdbScanOperation::doSendScan(int aProcessorId)
setErrorCode(4002);
return -1;
}
- if (theOperationType == OpenRangeScanRequest) {
+
+ if (tupKeyLen > 0){
// must have at least one signal since it contains attrLen for bounds
- assert(theBoundATTRINFO != NULL);
- tSignal = theBoundATTRINFO;
- while (tSignal != NULL) {
+ assert(theLastKEYINFO != NULL);
+ tSignal = theLastKEYINFO;
+ tSignal->setLength(KeyInfo::HeaderLength + theTotalNrOfKeyWordInSignal);
+
+ assert(theFirstKEYINFO != NULL);
+ tSignal = theFirstKEYINFO;
+
+ NdbApiSignal* last;
+ do {
+ KeyInfo * keyInfo = CAST_PTR(KeyInfo, tSignal->getDataPtrSend());
+ keyInfo->connectPtr = aTC_ConnectPtr;
+ keyInfo->transId[0] = Uint32(transId);
+ keyInfo->transId[1] = Uint32(transId >> 32);
+
if (tp->sendSignal(tSignal,aProcessorId) == -1){
- setErrorCode(4002);
- return -1;
+ setErrorCode(4002);
+ return -1;
}
+
tSignalCount++;
+ last = tSignal;
tSignal = tSignal->next();
- }
+ } while(last != theLastKEYINFO);
}
tSignal = theFirstATTRINFO;
while (tSignal != NULL) {
+ AttrInfo * attrInfo = CAST_PTR(AttrInfo, tSignal->getDataPtrSend());
+ attrInfo->connectPtr = aTC_ConnectPtr;
+ attrInfo->transId[0] = Uint32(transId);
+ attrInfo->transId[1] = Uint32(transId >> 32);
+
if (tp->sendSignal(tSignal,aProcessorId) == -1){
setErrorCode(4002);
return -1;
@@ -883,7 +853,7 @@ NdbScanOperation::doSendScan(int aProcessorId)
return tSignalCount;
}//NdbOperation::doSendScan()
-/******************************************************************************
+/*****************************************************************************
* NdbOperation* takeOverScanOp(NdbConnection* updateTrans);
*
* Parameters: The update transactions NdbConnection pointer.
@@ -902,7 +872,7 @@ NdbScanOperation::doSendScan(int aProcessorId)
* This means that the updating transactions can be placed
* in separate threads and thus increasing the parallelism during
* the scan process.
- *****************************************************************************/
+ ****************************************************************************/
int
NdbScanOperation::getKeyFromKEYINFO20(Uint32* data, unsigned size)
{
@@ -940,6 +910,7 @@ NdbScanOperation::takeOverScanOp(OperationType opType, NdbConnection* pTrans){
if (newOp == NULL){
return NULL;
}
+ pTrans->theSimpleState = 0;
const Uint32 len = (tRecAttr->attrSize() * tRecAttr->arraySize() + 3)/4-1;
@@ -1011,6 +982,7 @@ NdbScanOperation::takeOverScanOp(OperationType opType, NdbConnection* pTrans){
NdbBlob*
NdbScanOperation::getBlobHandle(const char* anAttrName)
{
+ m_keyInfo = 1;
return NdbOperation::getBlobHandle(m_transConnection,
m_currentTable->getColumn(anAttrName));
}
@@ -1018,6 +990,7 @@ NdbScanOperation::getBlobHandle(const char* anAttrName)
NdbBlob*
NdbScanOperation::getBlobHandle(Uint32 anAttrId)
{
+ m_keyInfo = 1;
return NdbOperation::getBlobHandle(m_transConnection,
m_currentTable->getColumn(anAttrId));
}
@@ -1031,13 +1004,15 @@ NdbIndexScanOperation::~NdbIndexScanOperation(){
}
int
-NdbIndexScanOperation::setBound(const char* anAttrName, int type, const void* aValue, Uint32 len)
+NdbIndexScanOperation::setBound(const char* anAttrName, int type,
+ const void* aValue, Uint32 len)
{
return setBound(m_accessTable->getColumn(anAttrName), type, aValue, len);
}
int
-NdbIndexScanOperation::setBound(Uint32 anAttrId, int type, const void* aValue, Uint32 len)
+NdbIndexScanOperation::setBound(Uint32 anAttrId, int type,
+ const void* aValue, Uint32 len)
{
return setBound(m_accessTable->getColumn(anAttrId), type, aValue, len);
}
@@ -1056,11 +1031,6 @@ NdbIndexScanOperation::getValue_impl(const NdbColumnImpl* attrInfo,
return NdbScanOperation::getValue_impl(attrInfo, aValue);
}
- if (theStatus == SetBound) {
- saveBoundATTRINFO();
- theStatus = GetValue;
- }
-
int id = attrInfo->m_attrId; // In "real" table
assert(m_accessTable->m_index);
int sz = (int)m_accessTable->m_index->m_key_ids.size();
@@ -1101,12 +1071,13 @@ NdbIndexScanOperation::setBound(const NdbColumnImpl* tAttrInfo,
int type, const void* aValue, Uint32 len)
{
if (theOperationType == OpenRangeScanRequest &&
- theStatus == SetBound &&
(0 <= type && type <= 4) &&
len <= 8000) {
// insert bound type
- insertATTRINFO(type);
+ Uint32 currLen = theTotalNrOfKeyWordInSignal;
+ Uint32 remaining = KeyInfo::DataLength - currLen;
Uint32 sizeInBytes = tAttrInfo->m_attrSize * tAttrInfo->m_arraySize;
+
// normalize char bound
CHARSET_INFO* cs = tAttrInfo->m_cs;
Uint32 xfrmData[2000];
@@ -1130,19 +1101,34 @@ NdbIndexScanOperation::setBound(const NdbColumnImpl* tAttrInfo,
Uint32 tIndexAttrId = tAttrInfo->m_attrId;
Uint32 sizeInWords = (len + 3) / 4;
AttributeHeader ah(tIndexAttrId, sizeInWords);
- insertATTRINFO(ah.m_value);
- if (len != 0) {
- // insert attribute data
- if ((UintPtr(aValue) & 0x3) == 0 && (len & 0x3) == 0)
- insertATTRINFOloop((const Uint32*)aValue, sizeInWords);
- else {
- Uint32 tempData[2000];
- memcpy(tempData, aValue, len);
+ const Uint32 ahValue = ah.m_value;
+
+ const bool aligned = (UintPtr(aValue) & 3) == 0;
+ const bool nobytes = (len & 0x3) == 0;
+ const Uint32 totalLen = 2 + sizeInWords;
+ Uint32 tupKeyLen = theTupKeyLen;
+ if(remaining > totalLen && aligned && nobytes){
+ Uint32 * dst = theKEYINFOptr + currLen;
+ * dst ++ = type;
+ * dst ++ = ahValue;
+ memcpy(dst, aValue, 4 * sizeInWords);
+ theTotalNrOfKeyWordInSignal = currLen + totalLen;
+ } else {
+ if(!aligned || !nobytes){
+ Uint32 tempData[2002];
+ tempData[0] = type;
+ tempData[1] = ahValue;
+ memcpy(tempData+2, aValue, len);
while ((len & 0x3) != 0)
- ((char*)tempData)[len++] = 0;
- insertATTRINFOloop(tempData, sizeInWords);
+ ((char*)&tempData[2])[len++] = 0;
+ insertBOUNDS(tempData, 2+sizeInWords);
+ } else {
+ Uint32 buf[2] = { type, ahValue };
+ insertBOUNDS(buf, 2);
+ insertBOUNDS((Uint32*)aValue, sizeInWords);
}
}
+ theTupKeyLen = tupKeyLen + totalLen;
/**
* Do sorted stuff
@@ -1165,6 +1151,46 @@ NdbIndexScanOperation::setBound(const NdbColumnImpl* tAttrInfo,
}
}
+int
+NdbIndexScanOperation::insertBOUNDS(Uint32 * data, Uint32 sz){
+ Uint32 len;
+ Uint32 remaining = KeyInfo::DataLength - theTotalNrOfKeyWordInSignal;
+ Uint32 * dst = theKEYINFOptr + theTotalNrOfKeyWordInSignal;
+ do {
+ len = (sz < remaining ? sz : remaining);
+ memcpy(dst, data, 4 * len);
+
+ if(sz >= remaining){
+ NdbApiSignal* tCurr = theLastKEYINFO;
+ tCurr->setLength(KeyInfo::MaxSignalLength);
+ NdbApiSignal* tSignal = tCurr->next();
+ if(tSignal)
+ ;
+ else if((tSignal = theNdb->getSignal()) != 0)
+ {
+ tCurr->next(tSignal);
+ tSignal->setSignal(GSN_KEYINFO);
+ } else {
+ goto error;
+ }
+ theLastKEYINFO = tSignal;
+ theKEYINFOptr = dst = ((KeyInfo*)tSignal->getDataPtrSend())->keyData;
+ remaining = KeyInfo::DataLength;
+ sz -= len;
+ data += len;
+ } else {
+ len = (KeyInfo::DataLength - remaining) + len;
+ break;
+ }
+ } while(true);
+ theTotalNrOfKeyWordInSignal = len;
+ return 0;
+
+error:
+ setErrorCodeAbort(4228); // XXX wrong code
+ return -1;
+}
+
NdbResultSet*
NdbIndexScanOperation::readTuples(LockMode lm,
Uint32 batch,
@@ -1173,9 +1199,23 @@ NdbIndexScanOperation::readTuples(LockMode lm,
NdbResultSet * rs = NdbScanOperation::readTuples(lm, batch, 0);
if(rs && order_by){
m_ordered = 1;
- m_sort_columns = m_accessTable->getNoOfColumns() - 1; // -1 for NDB$NODE
+ Uint32 cnt = m_accessTable->getNoOfColumns() - 1;
+ m_sort_columns = cnt; // -1 for NDB$NODE
m_current_api_receiver = m_sent_receivers_count;
m_api_receivers_count = m_sent_receivers_count;
+
+ m_sort_columns = cnt;
+ for(Uint32 i = 0; i<cnt; i++){
+ const NdbColumnImpl* key = m_accessTable->m_index->m_columns[i];
+ const NdbColumnImpl* col = m_currentTable->getColumn(key->m_keyInfoPos);
+ NdbRecAttr* tmp = NdbScanOperation::getValue_impl(col, (char*)-1);
+ UintPtr newVal = UintPtr(tmp);
+ theTupleKeyDefined[i][0] = FAKE_PTR;
+ theTupleKeyDefined[i][1] = (newVal & 0xFFFFFFFF);
+#if (SIZEOF_CHARP == 8)
+ theTupleKeyDefined[i][2] = (newVal >> 32);
+#endif
+ }
}
return rs;
}
@@ -1396,10 +1436,7 @@ NdbIndexScanOperation::send_next_scan_ordered(Uint32 idx){
}
int
-NdbScanOperation::restart(){
- TransporterFacade* tp = TransporterFacade::instance();
- Guard guard(tp->theMutexPtr);
-
+NdbScanOperation::close_impl(TransporterFacade* tp){
Uint32 seq = theNdbCon->theNodeSequence;
Uint32 nodeId = theNdbCon->theDBnode;
@@ -1407,8 +1444,8 @@ NdbScanOperation::restart(){
theNdbCon->theReleaseOnClose = true;
return -1;
}
-
- while(m_sent_receivers_count){
+
+ while(theError.code == 0 && m_sent_receivers_count){
theNdb->theWaiter.m_node = nodeId;
theNdb->theWaiter.m_state = WAIT_SCAN;
int return_code = theNdb->receiveResponse(WAITFOR_SCAN_TIMEOUT);
@@ -1421,14 +1458,17 @@ NdbScanOperation::restart(){
m_api_receivers_count = 0;
m_conf_receivers_count = 0;
m_sent_receivers_count = 0;
+ theNdbCon->theReleaseOnClose = true;
return -1;
}
}
if(m_api_receivers_count+m_conf_receivers_count){
// Send close scan
- if(send_next_scan(0, true) == -1) // Close scan
+ if(send_next_scan(0, true) == -1){ // Close scan
+ theNdbCon->theReleaseOnClose = true;
return -1;
+ }
}
/**
@@ -1447,15 +1487,15 @@ NdbScanOperation::restart(){
m_api_receivers_count = 0;
m_conf_receivers_count = 0;
m_sent_receivers_count = 0;
+ theNdbCon->theReleaseOnClose = true;
return -1;
}
}
+ return 0;
+}
- /**
- * Reset receivers
- */
- const Uint32 parallell = theParallelism;
-
+void
+NdbScanOperation::reset_receivers(Uint32 parallell, Uint32 ordered){
for(Uint32 i = 0; i<parallell; i++){
m_receivers[i]->m_list_index = i;
m_prepared_receivers[i] = m_receivers[i]->getId();
@@ -1470,13 +1510,64 @@ NdbScanOperation::restart(){
m_sent_receivers_count = parallell;
m_conf_receivers_count = 0;
- if(m_ordered){
+ if(ordered){
m_current_api_receiver = parallell;
m_api_receivers_count = parallell;
}
+}
+
+int
+NdbScanOperation::restart()
+{
+
+ TransporterFacade* tp = TransporterFacade::instance();
+ Guard guard(tp->theMutexPtr);
+ Uint32 nodeId = theNdbCon->theDBnode;
+
+ {
+ int res;
+ if((res= close_impl(tp)))
+ {
+ return res;
+ }
+ }
+
+ /**
+ * Reset receivers
+ */
+ reset_receivers(theParallelism, m_ordered);
+ theError.code = 0;
if (doSendScan(nodeId) == -1)
return -1;
return 0;
}
+
+int
+NdbIndexScanOperation::reset_bounds(){
+ int res;
+
+ {
+ TransporterFacade* tp = TransporterFacade::instance();
+ Guard guard(tp->theMutexPtr);
+ res= close_impl(tp);
+ }
+
+ if(!res)
+ {
+ theError.code = 0;
+ reset_receivers(theParallelism, m_ordered);
+
+ theLastKEYINFO = theFirstKEYINFO;
+ theKEYINFOptr = ((KeyInfo*)theFirstKEYINFO->getDataPtrSend())->keyData;
+ theTupKeyLen = 0;
+ theTotalNrOfKeyWordInSignal = 0;
+ m_transConnection
+ ->remove_list((NdbOperation*&)m_transConnection->m_firstExecutedScanOp,
+ this);
+ m_transConnection->define_scan_op(this);
+ return 0;
+ }
+ return res;
+}
diff --git a/ndb/src/ndbapi/Ndbif.cpp b/ndb/src/ndbapi/Ndbif.cpp
index 5c91467f2e5..c011c1a6a26 100644
--- a/ndb/src/ndbapi/Ndbif.cpp
+++ b/ndb/src/ndbapi/Ndbif.cpp
@@ -249,6 +249,7 @@ Ndb::report_node_failure(Uint32 node_id)
*/
the_release_ind[node_id] = 1;
theWaiter.nodeFail(node_id);
+ return;
}//Ndb::report_node_failure()
@@ -271,9 +272,10 @@ Ndb::abortTransactionsAfterNodeFailure(Uint16 aNodeId)
Uint32 tNoSentTransactions = theNoOfSentTransactions;
for (int i = tNoSentTransactions - 1; i >= 0; i--) {
NdbConnection* localCon = theSentTransactionsArray[i];
- if (localCon->getConnectedNodeId() == aNodeId ) {
+ if (localCon->getConnectedNodeId() == aNodeId) {
const NdbConnection::SendStatusType sendStatus = localCon->theSendStatus;
- if (sendStatus == NdbConnection::sendTC_OP || sendStatus == NdbConnection::sendTC_COMMIT) {
+ if (sendStatus == NdbConnection::sendTC_OP ||
+ sendStatus == NdbConnection::sendTC_COMMIT) {
/*
A transaction was interrupted in the prepare phase by a node
failure. Since the transaction was not found in the phase
@@ -293,7 +295,7 @@ Ndb::abortTransactionsAfterNodeFailure(Uint16 aNodeId)
printState("abortTransactionsAfterNodeFailure %x", this);
abort();
#endif
- }//
+ }
/*
All transactions arriving here have no connection to the kernel
intact since the node was failing and they were aborted. Thus we
@@ -302,7 +304,11 @@ Ndb::abortTransactionsAfterNodeFailure(Uint16 aNodeId)
localCon->theCommitStatus = NdbConnection::Aborted;
localCon->theReleaseOnClose = true;
completedTransaction(localCon);
- }//if
+ }
+ else if(localCon->report_node_failure(aNodeId))
+ {
+ completedTransaction(localCon);
+ }
}//for
return;
}//Ndb::abortTransactionsAfterNodeFailure()
diff --git a/ndb/src/ndbapi/Ndbinit.cpp b/ndb/src/ndbapi/Ndbinit.cpp
index 8589158ae6a..b8927f2abba 100644
--- a/ndb/src/ndbapi/Ndbinit.cpp
+++ b/ndb/src/ndbapi/Ndbinit.cpp
@@ -107,8 +107,6 @@ void Ndb::setup(Ndb_cluster_connection *ndb_cluster_connection,
theOpIdleList= NULL;
theScanOpIdleList= NULL;
theIndexOpIdleList= NULL;
-// theSchemaConIdleList= NULL;
-// theSchemaConToNdbList= NULL;
theTransactionList= NULL;
theConnectionArray= NULL;
theRecAttrIdleList= NULL;
@@ -134,10 +132,13 @@ void Ndb::setup(Ndb_cluster_connection *ndb_cluster_connection,
fullyQualifiedNames = true;
+#ifdef POORMANSPURIFY
cgetSignals =0;
cfreeSignals = 0;
cnewSignals = 0;
creleaseSignals = 0;
+#endif
+
theError.code = 0;
theNdbObjectIdMap = new NdbObjectIdMap(1024,1024);
@@ -159,12 +160,12 @@ void Ndb::setup(Ndb_cluster_connection *ndb_cluster_connection,
theLastTupleId[i] = 0;
}//for
- snprintf(theDataBase, sizeof(theDataBase), "%s",
+ BaseString::snprintf(theDataBase, sizeof(theDataBase), "%s",
aDataBase ? aDataBase : "");
- snprintf(theDataBaseSchema, sizeof(theDataBaseSchema), "%s",
+ BaseString::snprintf(theDataBaseSchema, sizeof(theDataBaseSchema), "%s",
aSchema ? aSchema : "");
- int len = snprintf(prefixName, sizeof(prefixName), "%s%c%s%c",
+ int len = BaseString::snprintf(prefixName, sizeof(prefixName), "%s%c%s%c",
theDataBase, table_name_separator,
theDataBaseSchema, table_name_separator);
prefixEnd = prefixName + (len < (int) sizeof(prefixName) ? len :
diff --git a/ndb/src/ndbapi/Ndblist.cpp b/ndb/src/ndbapi/Ndblist.cpp
index af98aa09280..a5f2a4801d5 100644
--- a/ndb/src/ndbapi/Ndblist.cpp
+++ b/ndb/src/ndbapi/Ndblist.cpp
@@ -33,7 +33,7 @@ Ndb::checkFailedNode()
DBUG_PRINT("enter", ("theNoOfDBnodes: %d", theNoOfDBnodes));
DBUG_ASSERT(theNoOfDBnodes < MAX_NDB_NODES);
- for (int i = 0; i < theNoOfDBnodes; i++){
+ for (Uint32 i = 0; i < theNoOfDBnodes; i++){
const NodeId node_id = theDBnodes[i];
DBUG_PRINT("info", ("i: %d, node_id: %d", i, node_id));
@@ -432,11 +432,15 @@ Ndb::getSignal()
theSignalIdleList = tSignalNext;
} else {
tSignal = new NdbApiSignal(theMyRef);
+#ifdef POORMANSPURIFY
cnewSignals++;
+#endif
if (tSignal != NULL)
tSignal->next(NULL);
}
+#ifdef POORMANSPURIFY
cgetSignals++;
+#endif
return tSignal;
}
@@ -605,7 +609,9 @@ Ndb::releaseSignal(NdbApiSignal* aSignal)
}
#endif
#endif
+#ifdef POORMANSPURIFY
creleaseSignals++;
+#endif
aSignal->next(theSignalIdleList);
theSignalIdleList = aSignal;
}
@@ -649,8 +655,8 @@ Remark: Always release the first item in the free list
void
Ndb::freeScanOperation()
{
- NdbScanOperation* tOp = theScanOpIdleList;
- theScanOpIdleList = (NdbIndexScanOperation *) theScanOpIdleList->next();
+ NdbIndexScanOperation* tOp = theScanOpIdleList;
+ theScanOpIdleList = (NdbIndexScanOperation *)tOp->next();
delete tOp;
}
@@ -769,7 +775,9 @@ Ndb::freeSignal()
NdbApiSignal* tSignal = theSignalIdleList;
theSignalIdleList = tSignal->next();
delete tSignal;
+#ifdef POORMANSPURIFY
cfreeSignals++;
+#endif
}
void
diff --git a/ndb/src/ndbapi/ndberror.c b/ndb/src/ndbapi/ndberror.c
index fdfd8a15fb0..20661b89517 100644
--- a/ndb/src/ndbapi/ndberror.c
+++ b/ndb/src/ndbapi/ndberror.c
@@ -16,7 +16,6 @@
#include <ndb_global.h>
-
#include <ndberror.h>
typedef struct ErrorBundle {
@@ -92,9 +91,10 @@ ErrorBundle ErrorCodes[] = {
{ 4031, NR, "Node failure caused abort of transaction" },
{ 4033, NR, "Send to NDB failed" },
{ 4115, NR,
- "Transaction was committed but all read information was not "
- "received due to node crash" },
-
+ "Transaction was committed but all read information was not "
+ "received due to node crash" },
+ { 4119, NR, "Simple/dirty read failed due to node failure" },
+
/**
* Node shutdown
*/
@@ -171,7 +171,7 @@ ErrorBundle ErrorCodes[] = {
{ 677, OL, "Index UNDO buffers overloaded" },
{ 891, OL, "Data UNDO buffers overloaded" },
{ 1221, OL, "REDO log buffers overloaded" },
- { 4006, AE, "Connect failure - out of connection objects" },
+ { 4006, OL, "Connect failure - out of connection objects" },
@@ -491,6 +491,7 @@ static
const
int NbClassification = sizeof(StatusClassificationMapping)/sizeof(ErrorStatusClassification);
+#ifdef NOT_USED
/**
* Complete all fields of an NdbError given the error code
* and details
@@ -506,7 +507,7 @@ set(ndberror_struct * error, int code, const char * details, ...){
va_end(ap);
}
}
-
+#endif
void
ndberror_update(ndberror_struct * error){
@@ -592,8 +593,10 @@ int ndb_error_string(int err_no, char *str, unsigned int size)
error.code = err_no;
ndberror_update(&error);
- len = snprintf(str, size-1, "%s: %s: %s", error.message,
- ndberror_status_message(error.status), ndberror_classification_message(error.classification));
+ len =
+ snprintf(str, size-1, "%s: %s: %s", error.message,
+ ndberror_status_message(error.status),
+ ndberror_classification_message(error.classification));
str[size-1]= '\0';
return len;
diff --git a/ndb/test/include/HugoOperations.hpp b/ndb/test/include/HugoOperations.hpp
index 6bd8f7204b2..fe22e4b5649 100644
--- a/ndb/test/include/HugoOperations.hpp
+++ b/ndb/test/include/HugoOperations.hpp
@@ -38,16 +38,8 @@ public:
int pkReadRecord(Ndb*,
int recordNo,
- bool exclusive = false,
- int numRecords = 1);
-
- int pkSimpleReadRecord(Ndb*,
- int recordNo,
- int numRecords = 1);
-
- int pkDirtyReadRecord(Ndb*,
- int recordNo,
- int numRecords = 1);
+ int numRecords = 1,
+ NdbOperation::LockMode lm = NdbOperation::LM_Read);
int pkUpdateRecord(Ndb*,
int recordNo,
diff --git a/ndb/test/include/HugoTransactions.hpp b/ndb/test/include/HugoTransactions.hpp
index 280d9490f15..19e4cb43336 100644
--- a/ndb/test/include/HugoTransactions.hpp
+++ b/ndb/test/include/HugoTransactions.hpp
@@ -48,8 +48,8 @@ public:
int pkReadRecords(Ndb*,
int records,
int batchsize = 1,
- bool dirty = false);
-
+ NdbOperation::LockMode = NdbOperation::LM_Read);
+
int scanUpdateRecords(Ndb*,
int records,
int abort = 0,
diff --git a/ndb/test/include/NDBT_ResultRow.hpp b/ndb/test/include/NDBT_ResultRow.hpp
index aa54e892da3..6072d0ea510 100644
--- a/ndb/test/include/NDBT_ResultRow.hpp
+++ b/ndb/test/include/NDBT_ResultRow.hpp
@@ -24,8 +24,9 @@ public:
NDBT_ResultRow(const NdbDictionary::Table &tab, char attrib_delimiter='\t');
~NDBT_ResultRow();
NdbRecAttr * & attributeStore(int i);
- const NdbRecAttr * attributeStore(const char* name);
-
+ const NdbRecAttr * attributeStore(int i) const ;
+ const NdbRecAttr * attributeStore(const char* name) const ;
+
BaseString c_str();
NdbOut & header (NdbOut &) const;
diff --git a/ndb/test/include/NDBT_Test.hpp b/ndb/test/include/NDBT_Test.hpp
index 6a968c491ae..b0b5fe15960 100644
--- a/ndb/test/include/NDBT_Test.hpp
+++ b/ndb/test/include/NDBT_Test.hpp
@@ -82,6 +82,12 @@ public:
*/
int getNoOfRunningSteps() const ;
int getNoOfCompletedSteps() const ;
+
+ /**
+ * Thread sync
+ */
+ void sync_down(const char * key);
+ void sync_up_and_wait(const char * key, Uint32 count = 0);
private:
friend class NDBT_Step;
friend class NDBT_TestSuite;
@@ -245,7 +251,7 @@ public:
// Convert to Uint32 in order to be able to print it to screen
Uint32 lapTime = (Uint32)m_ticks;
Uint32 secTime = lapTime/1000;
- snprintf(buf, 255, "%d secs (%d ms)", secTime, lapTime);
+ BaseString::snprintf(buf, 255, "%d secs (%d ms)", secTime, lapTime);
return buf;
}
private:
diff --git a/ndb/test/include/UtilTransactions.hpp b/ndb/test/include/UtilTransactions.hpp
index 1298028d591..37cd99550a5 100644
--- a/ndb/test/include/UtilTransactions.hpp
+++ b/ndb/test/include/UtilTransactions.hpp
@@ -87,19 +87,30 @@ private:
int verifyUniqueIndex(Ndb*,
- const char* indexName,
+ const NdbDictionary::Index *,
int parallelism = 0,
bool transactional = false);
-
+
int scanAndCompareUniqueIndex(Ndb* pNdb,
- const char * indexName,
+ const NdbDictionary::Index *,
int parallelism,
bool transactional);
int readRowFromTableAndIndex(Ndb* pNdb,
NdbConnection* pTrans,
- const char * indexName,
+ const NdbDictionary::Index *,
NDBT_ResultRow& row );
+
+ int verifyOrderedIndex(Ndb*,
+ const NdbDictionary::Index *,
+ int parallelism = 0,
+ bool transactional = false);
+
+
+ int get_values(NdbOperation* op, NDBT_ResultRow& dst);
+ int equal(const NdbDictionary::Table*, NdbOperation*, const NDBT_ResultRow&);
+ int equal(const NdbDictionary::Index*, NdbOperation*, const NDBT_ResultRow&);
+
protected:
int m_defaultClearMethod;
const NdbDictionary::Table& tab;
diff --git a/ndb/test/ndbapi/asyncGenerator.cpp b/ndb/test/ndbapi/asyncGenerator.cpp
index 84a93414712..d91e38dff1a 100644
--- a/ndb/test/ndbapi/asyncGenerator.cpp
+++ b/ndb/test/ndbapi/asyncGenerator.cpp
@@ -248,7 +248,7 @@ doTransaction_T1(Ndb * pNDB, ThreadData * td, int async)
/*----------------*/
getRandomSubscriberNumber(td->transactionData.number);
getRandomChangedBy(td->transactionData.changed_by);
- snprintf(td->transactionData.changed_time,
+ BaseString::snprintf(td->transactionData.changed_time,
sizeof(td->transactionData.changed_time),
"%ld - %d", td->changedTime++, myRandom48(65536*1024));
//getRandomChangedTime(td->transactionData.changed_time);
diff --git a/ndb/test/ndbapi/bulk_copy.cpp b/ndb/test/ndbapi/bulk_copy.cpp
index 8821a92fb27..b53654ce0fb 100644
--- a/ndb/test/ndbapi/bulk_copy.cpp
+++ b/ndb/test/ndbapi/bulk_copy.cpp
@@ -263,7 +263,7 @@ int main(int argc, const char** argv){
}
char buf[255];
- snprintf(buf, sizeof(buf), "%s.data", (const char*)_tabname);
+ BaseString::snprintf(buf, sizeof(buf), "%s.data", (const char*)_tabname);
if (insertFile(&MyNdb, pTab, buf) != 0){
return NDBT_ProgramExit(NDBT_FAILED);
}
diff --git a/ndb/test/ndbapi/cdrserver.cpp b/ndb/test/ndbapi/cdrserver.cpp
index 8d15061e94b..976319034bf 100644
--- a/ndb/test/ndbapi/cdrserver.cpp
+++ b/ndb/test/ndbapi/cdrserver.cpp
@@ -501,11 +501,11 @@ server(long int servernum)
/* that this program could easily be ported to a host */
/* that does require it. */
- snprintf(msg,sizeof(msg),"Startup from %s port %u",hostname,ntohs(peeraddr_in.sin_port));
+ BaseString::snprintf(msg,sizeof(msg),"Startup from %s port %u",hostname,ntohs(peeraddr_in.sin_port));
if ((checkchangelog(fi,temp))==0)
c2log(fi,msg);
n2log(log,msg);
- snprintf(msg,sizeof(msg),"For further information, see log(%s)",lognamn);
+ BaseString::snprintf(msg,sizeof(msg),"For further information, see log(%s)",lognamn);
if ((checkchangelog(fi,temp))==0)
c2log(fi,msg);
@@ -516,7 +516,7 @@ server(long int servernum)
linger.l_onoff =1;
linger.l_linger =0;
if (setsockopt(s, SOL_SOCKET, SO_LINGER,(const char*)&linger,sizeof(linger)) == -1) {
- snprintf(msg,sizeof(msg),"Setting SO_LINGER, l_onoff=%d, l_linger=%d",linger.l_onoff,linger.l_linger);
+ BaseString::snprintf(msg,sizeof(msg),"Setting SO_LINGER, l_onoff=%d, l_linger=%d",linger.l_onoff,linger.l_linger);
if ((checkchangelog(log,lognamn))==0)
n2log(log,msg);
goto errout;
@@ -529,7 +529,7 @@ server(long int servernum)
rcvbuf_size=64*1024;
if (setsockopt(s, SOL_SOCKET, SO_RCVBUF,(const char*) &rcvbuf_size,sizeof(rcvbuf_size)) == -1) {
- snprintf(msg,sizeof(msg),"Setting SO_RCVBUF = %d",rcvbuf_size);
+ BaseString::snprintf(msg,sizeof(msg),"Setting SO_RCVBUF = %d",rcvbuf_size);
if ((checkchangelog(log,lognamn))==0)
n2log(log,msg);
goto errout;
@@ -913,7 +913,7 @@ server(long int servernum)
tmpcdrptr->USED_FIELDS |= B_ReroutingIndicator;
break;
default :
- snprintf(msg,sizeof(msg),"ERROR: Redirection information has wrong length %d\n",parmlen);
+ BaseString::snprintf(msg,sizeof(msg),"ERROR: Redirection information has wrong length %d\n",parmlen);
if ((checkchangelog(log,lognamn))==0)
n2log(log,msg);
break;
@@ -1060,7 +1060,7 @@ server(long int servernum)
tmpcdrptr->USED_FIELDS |= B_RINParameter;
break;
default :
- snprintf(msg,sizeof(msg),"ERROR: Rin parameter has wrong length %d\n",parmlen);
+ BaseString::snprintf(msg,sizeof(msg),"ERROR: Rin parameter has wrong length %d\n",parmlen);
if ((checkchangelog(log,lognamn))==0)
n2log(log,msg);
break;
@@ -1088,7 +1088,7 @@ server(long int servernum)
tmpcdrptr->USED_FIELDS |= B_OriginatingPointCode;
break;
default :
- snprintf(msg,sizeof(msg),"ERROR: OriginatingPointCode parameter has wrong length %d\n",parmlen);
+ BaseString::snprintf(msg,sizeof(msg),"ERROR: OriginatingPointCode parameter has wrong length %d\n",parmlen);
if ((checkchangelog(log,lognamn))==0)
n2log(log,msg);
break;
@@ -1119,7 +1119,7 @@ server(long int servernum)
tmpcdrptr->USED_FIELDS |= B_DestinationPointCode;
break;
default :
- snprintf(msg,sizeof(msg),"ERROR: DestinationPointCode parameter has wrong length %d\n",parmlen);
+ BaseString::snprintf(msg,sizeof(msg),"ERROR: DestinationPointCode parameter has wrong length %d\n",parmlen);
if ((checkchangelog(log,lognamn))==0)
n2log(log,msg);
break;
@@ -1146,7 +1146,7 @@ server(long int servernum)
break;
default:
printf("ERROR: Undefined parmtype %d , previous %d, length %d\n",parmtype,parmtype_prev,parmlen);
- snprintf(msg,sizeof(msg),"ERROR: Undefined parmtype %d , previous %d, length %d\n",parmtype,parmtype_prev,parmlen);
+ BaseString::snprintf(msg,sizeof(msg),"ERROR: Undefined parmtype %d , previous %d, length %d\n",parmtype,parmtype_prev,parmlen);
if ((checkchangelog(log,lognamn))==0)
n2log(log,msg);
if (parmlen == 0) {
@@ -1289,17 +1289,17 @@ server(long int servernum)
/* that this program could easily be ported to a host */
/* that does require it. */
- snprintf(msg,sizeof(msg),"Completed %s port %u, %d requests",hostname,ntohs(peeraddr_in.sin_port), reqcnt);
+ BaseString::snprintf(msg,sizeof(msg),"Completed %s port %u, %d requests",hostname,ntohs(peeraddr_in.sin_port), reqcnt);
if ((checkchangelog(fi,temp))==0)
c2log(fi,msg);
error_from_client = 1;
- snprintf(msg,sizeof(msg),"Communicate with threads");
+ BaseString::snprintf(msg,sizeof(msg),"Communicate with threads");
if ((checkchangelog(log,lognamn))==0)
n2log(log,msg);
- snprintf(msg,sizeof(msg),"Waiting for threads to return from work");
+ BaseString::snprintf(msg,sizeof(msg),"Waiting for threads to return from work");
if ((checkchangelog(log,lognamn))==0)
n2log(log,msg);
- snprintf(msg,sizeof(msg),"Closing down");
+ BaseString::snprintf(msg,sizeof(msg),"Closing down");
if ((checkchangelog(log,lognamn))==0)
n2log(log,msg);
close(s);
@@ -1307,19 +1307,19 @@ server(long int servernum)
return EXIT_SUCCESS;
errout:
- snprintf(msg,sizeof(msg),"Connection with %s aborted on error\n", hostname);
+ BaseString::snprintf(msg,sizeof(msg),"Connection with %s aborted on error\n", hostname);
if ((checkchangelog(log,lognamn))==0)
n2log(log,msg);
if ((checkchangelog(fi,temp))==0)
c2log(fi,msg);
error_from_client = 1;
- snprintf(msg,sizeof(msg),"Communicate with threads");
+ BaseString::snprintf(msg,sizeof(msg),"Communicate with threads");
if ((checkchangelog(log,lognamn))==0)
n2log(log,msg);
- snprintf(msg,sizeof(msg),"Waiting for threads to return from work");
+ BaseString::snprintf(msg,sizeof(msg),"Waiting for threads to return from work");
if ((checkchangelog(log,lognamn))==0)
n2log(log,msg);
- snprintf(msg,sizeof(msg),"Closing down");
+ BaseString::snprintf(msg,sizeof(msg),"Closing down");
if ((checkchangelog(log,lognamn))==0)
n2log(log,msg);
close(s);
diff --git a/ndb/test/ndbapi/flexAsynch.cpp b/ndb/test/ndbapi/flexAsynch.cpp
index 8c0ba46130c..1953444d640 100644
--- a/ndb/test/ndbapi/flexAsynch.cpp
+++ b/ndb/test/ndbapi/flexAsynch.cpp
@@ -710,7 +710,7 @@ static void setAttrNames()
int i;
for (i = 0; i < MAXATTR ; i++){
- snprintf(attrName[i], MAXSTRLEN, "COL%d", i);
+ BaseString::snprintf(attrName[i], MAXSTRLEN, "COL%d", i);
}
}
@@ -722,10 +722,10 @@ static void setTableNames()
int i;
for (i = 0; i < MAXTABLES ; i++){
if (theStdTableNameFlag==0){
- snprintf(tableName[i], MAXSTRLEN, "TAB%d_%d", i,
+ BaseString::snprintf(tableName[i], MAXSTRLEN, "TAB%d_%d", i,
(int)(NdbTick_CurrentMillisecond()/1000));
} else {
- snprintf(tableName[i], MAXSTRLEN, "TAB%d", i);
+ BaseString::snprintf(tableName[i], MAXSTRLEN, "TAB%d", i);
}
}
}
diff --git a/ndb/test/ndbapi/flexBench.cpp b/ndb/test/ndbapi/flexBench.cpp
index b19944498f4..2a2388109a1 100644
--- a/ndb/test/ndbapi/flexBench.cpp
+++ b/ndb/test/ndbapi/flexBench.cpp
@@ -1032,7 +1032,7 @@ static int readArguments(int argc, const char** argv)
const char *q = strrchr(p, ':');
if (q == 0)
return -1;
- snprintf(statHost, sizeof(statHost), "%.*s", q-p, p);
+ BaseString::snprintf(statHost, sizeof(statHost), "%.*s", q-p, p);
statPort = atoi(q+1);
statEnable = true;
argc -= 1;
@@ -1068,17 +1068,17 @@ static int
createTables(Ndb* pMyNdb){
int i;
for (i = 0; i < tNoOfAttributes; i++){
- snprintf(attrName[i], MAXSTRLEN, "COL%d", i);
+ BaseString::snprintf(attrName[i], MAXSTRLEN, "COL%d", i);
}
// Note! Uses only uppercase letters in table name's
// so that we can look at the tables with SQL
for (i = 0; i < tNoOfTables; i++){
if (theStdTableNameFlag == 0){
- snprintf(tableName[i], MAXSTRLEN, "TAB%d_%d", i,
+ BaseString::snprintf(tableName[i], MAXSTRLEN, "TAB%d_%d", i,
(int)(NdbTick_CurrentMillisecond() / 1000));
} else {
- snprintf(tableName[i], MAXSTRLEN, "TAB%d", i);
+ BaseString::snprintf(tableName[i], MAXSTRLEN, "TAB%d", i);
}
}
diff --git a/ndb/test/ndbapi/flexHammer.cpp b/ndb/test/ndbapi/flexHammer.cpp
index 80cc7c5a53f..688e70d501a 100644
--- a/ndb/test/ndbapi/flexHammer.cpp
+++ b/ndb/test/ndbapi/flexHammer.cpp
@@ -840,7 +840,7 @@ static int setAttrNames()
int retVal = 0;
for (i = 0; i < MAXATTR ; i++) {
- retVal = snprintf(attrName[i], MAXSTRLEN, "COL%d", i);
+ retVal = BaseString::snprintf(attrName[i], MAXSTRLEN, "COL%d", i);
if (retVal < 0) {
// Error in conversion
return(-1);
@@ -859,11 +859,11 @@ static int setTableNames()
for (i = 0; i < MAXTABLES ; i++) {
if (theStandardTableNameFlag == 0) {
- retVal = snprintf(tableName[i], MAXSTRLEN, "TAB%d_%d", i,
+ retVal = BaseString::snprintf(tableName[i], MAXSTRLEN, "TAB%d_%d", i,
NdbTick_CurrentMillisecond()/1000);
} // if
else {
- retVal = snprintf(tableName[i], MAXSTRLEN, "TAB%d", i);
+ retVal = BaseString::snprintf(tableName[i], MAXSTRLEN, "TAB%d", i);
} // else
if (retVal < 0) {
// Error in conversion
diff --git a/ndb/test/ndbapi/flexScan.cpp b/ndb/test/ndbapi/flexScan.cpp
index b09d71fb010..c7f4041a525 100644
--- a/ndb/test/ndbapi/flexScan.cpp
+++ b/ndb/test/ndbapi/flexScan.cpp
@@ -713,7 +713,7 @@ static int setAttrNames()
int retVal = 0;
for (i = 0; i < MAXATTR ; i++) {
- retVal = snprintf(attrName[i], MAXSTRLEN, "COL%d", i);
+ retVal = BaseString::snprintf(attrName[i], MAXSTRLEN, "COL%d", i);
if (retVal < 0) {
return(-1);
} // if
@@ -733,11 +733,11 @@ static int setTableNames()
for (i = 0; i < MAXTABLES ; i++) {
if (theStdTableNameFlag == 0) {
- retVal = snprintf(tableName[i], MAXSTRLEN, "TAB%d_%d", i,
+ retVal = BaseString::snprintf(tableName[i], MAXSTRLEN, "TAB%d_%d", i,
(int)(NdbTick_CurrentMillisecond() / 1000));
} // if
else {
- retVal = snprintf(tableName[i], MAXSTRLEN, "TAB%d", i);
+ retVal = BaseString::snprintf(tableName[i], MAXSTRLEN, "TAB%d", i);
} // if else
if (retVal < 0) {
diff --git a/ndb/test/ndbapi/flexTT.cpp b/ndb/test/ndbapi/flexTT.cpp
index 162fc080218..3b976f9f87e 100644
--- a/ndb/test/ndbapi/flexTT.cpp
+++ b/ndb/test/ndbapi/flexTT.cpp
@@ -641,17 +641,17 @@ defineOperation(NdbConnection* localNdbConnection, TransNdb* transNdbRef,
static void setAttrNames()
{
- snprintf(attrName[0], MAXSTRLEN, "VPN_ID");
- snprintf(attrName[1], MAXSTRLEN, "VPN_NB");
- snprintf(attrName[2], MAXSTRLEN, "DIRECTORY_NB");
- snprintf(attrName[3], MAXSTRLEN, "LAST_CALL_PARTY");
- snprintf(attrName[4], MAXSTRLEN, "DESCR");
+ BaseString::snprintf(attrName[0], MAXSTRLEN, "VPN_ID");
+ BaseString::snprintf(attrName[1], MAXSTRLEN, "VPN_NB");
+ BaseString::snprintf(attrName[2], MAXSTRLEN, "DIRECTORY_NB");
+ BaseString::snprintf(attrName[3], MAXSTRLEN, "LAST_CALL_PARTY");
+ BaseString::snprintf(attrName[4], MAXSTRLEN, "DESCR");
}
static void setTableNames()
{
- snprintf(tableName[0], MAXSTRLEN, "VPN_USERS");
+ BaseString::snprintf(tableName[0], MAXSTRLEN, "VPN_USERS");
}
static
diff --git a/ndb/test/ndbapi/flex_bench_mysql.cpp b/ndb/test/ndbapi/flex_bench_mysql.cpp
index 8e1fbcd9058..c8d4d85bedf 100644
--- a/ndb/test/ndbapi/flex_bench_mysql.cpp
+++ b/ndb/test/ndbapi/flex_bench_mysql.cpp
@@ -1552,7 +1552,7 @@ static int readArguments(int argc, const char** argv)
const char *q = strrchr(p, ':');
if (q == 0)
return -1;
- snprintf(statHost, sizeof(statHost), "%.*s", q-p, p);
+ BaseString::snprintf(statHost, sizeof(statHost), "%.*s", q-p, p);
statPort = atoi(q+1);
statEnable = true;
argc -= 1;
@@ -1618,17 +1618,17 @@ static int
createTables(MYSQL* mysqlp){
for (Uint32 i = 0; i < tNoOfAttributes; i++){
- snprintf(attrName[i], MAXSTRLEN, "COL%d", i);
+ BaseString::snprintf(attrName[i], MAXSTRLEN, "COL%d", i);
}
// Note! Uses only uppercase letters in table name's
// so that we can look at the tables with SQL
for (Uint32 i = 0; i < tNoOfTables; i++){
if (theStdTableNameFlag == 0){
- snprintf(tableName[i], MAXSTRLEN, "TAB%d_%d", i,
+ BaseString::snprintf(tableName[i], MAXSTRLEN, "TAB%d_%d", i,
(int)(NdbTick_CurrentMillisecond() / 1000));
} else {
- snprintf(tableName[i], MAXSTRLEN, "TAB%d", i);
+ BaseString::snprintf(tableName[i], MAXSTRLEN, "TAB%d", i);
}
}
@@ -1663,17 +1663,17 @@ static int
createTables(Ndb* pMyNdb){
for (Uint32 i = 0; i < tNoOfAttributes; i++){
- snprintf(attrName[i], MAXSTRLEN, "COL%d", i);
+ BaseString::snprintf(attrName[i], MAXSTRLEN, "COL%d", i);
}
// Note! Uses only uppercase letters in table name's
// so that we can look at the tables with SQL
for (Uint32 i = 0; i < tNoOfTables; i++){
if (theStdTableNameFlag == 0){
- snprintf(tableName[i], MAXSTRLEN, "TAB%d_%d", i,
+ BaseString::snprintf(tableName[i], MAXSTRLEN, "TAB%d_%d", i,
(int)(NdbTick_CurrentMillisecond() / 1000));
} else {
- snprintf(tableName[i], MAXSTRLEN, "TAB%d", i);
+ BaseString::snprintf(tableName[i], MAXSTRLEN, "TAB%d", i);
}
}
diff --git a/ndb/test/ndbapi/interpreterInTup.cpp b/ndb/test/ndbapi/interpreterInTup.cpp
index 20d84e6e96d..a07d5898213 100644
--- a/ndb/test/ndbapi/interpreterInTup.cpp
+++ b/ndb/test/ndbapi/interpreterInTup.cpp
@@ -1507,12 +1507,12 @@ void delete_rows(Ndb* pMyNdb, int tupleTest, int opType) {
inline void setAttrNames(){
for (int i = 0; i < MAXATTR; i++){
- snprintf(attrName[i], MAXSTRLEN, "COL%d", i);
+ BaseString::snprintf(attrName[i], MAXSTRLEN, "COL%d", i);
}
}
inline void setTableNames(){
- snprintf(tableName, MAXSTRLEN, "TAB1");
+ BaseString::snprintf(tableName, MAXSTRLEN, "TAB1");
}
diff --git a/ndb/test/ndbapi/testBasic.cpp b/ndb/test/ndbapi/testBasic.cpp
index 7d03016b87a..4d64b15ecfa 100644
--- a/ndb/test/ndbapi/testBasic.cpp
+++ b/ndb/test/ndbapi/testBasic.cpp
@@ -160,8 +160,8 @@ int runPkDirtyRead(NDBT_Context* ctx, NDBT_Step* step){
HugoTransactions hugoTrans(*ctx->getTab());
while (i<loops) {
g_info << i << ": ";
- if (hugoTrans.pkReadRecords(GETNDB(step), records,
- batchSize, dirty) != NDBT_OK){
+ if (hugoTrans.pkReadRecords(GETNDB(step), records, batchSize,
+ NdbOperation::LM_CommittedRead) != NDBT_OK){
g_info << endl;
return NDBT_FAILED;
}
@@ -398,14 +398,14 @@ int runNoCommitSleep(NDBT_Context* ctx, NDBT_Step* step){
for (int i = 2; i < 8; i++){
CHECK(hugoOps.startTransaction(pNdb) == 0);
- CHECK(hugoOps.pkReadRecord(pNdb, 1, true) == 0);
+ CHECK(hugoOps.pkReadRecord(pNdb, 1, 1, NdbOperation::LM_Exclusive) == 0);
CHECK(hugoOps.execute_NoCommit(pNdb) == 0);
ndbout << i <<": Sleeping for " << sleepTime << " ms" << endl;
NdbSleep_MilliSleep(sleepTime);
// Dont care about result of these ops
- hugoOps.pkReadRecord(pNdb, 1, true);
+ hugoOps.pkReadRecord(pNdb, 1, 1, NdbOperation::LM_Exclusive);
hugoOps.closeTransaction(pNdb);
sleepTime = sleepTime *i;
@@ -424,16 +424,16 @@ int runCommit626(NDBT_Context* ctx, NDBT_Step* step){
do{
// Commit transaction
CHECK(hugoOps.startTransaction(pNdb) == 0);
- CHECK(hugoOps.pkReadRecord(pNdb, 1, true) == 0);
+ CHECK(hugoOps.pkReadRecord(pNdb, 1, 1, NdbOperation::LM_Exclusive) == 0);
CHECK(hugoOps.execute_Commit(pNdb) == 626);
CHECK(hugoOps.closeTransaction(pNdb) == 0);
// Commit transaction
// Multiple operations
CHECK(hugoOps.startTransaction(pNdb) == 0);
- CHECK(hugoOps.pkReadRecord(pNdb, 1, true) == 0);
- CHECK(hugoOps.pkReadRecord(pNdb, 2, true) == 0);
- CHECK(hugoOps.pkReadRecord(pNdb, 3, true) == 0);
+ CHECK(hugoOps.pkReadRecord(pNdb, 1, 1, NdbOperation::LM_Exclusive) == 0);
+ CHECK(hugoOps.pkReadRecord(pNdb, 2, 1, NdbOperation::LM_Exclusive) == 0);
+ CHECK(hugoOps.pkReadRecord(pNdb, 3, 1, NdbOperation::LM_Exclusive) == 0);
CHECK(hugoOps.execute_Commit(pNdb) == 626);
}while(false);
@@ -467,7 +467,7 @@ int runCommit_TryCommit626(NDBT_Context* ctx, NDBT_Step* step){
do{
// Commit transaction, TryCommit
CHECK(hugoOps.startTransaction(pNdb) == 0);
- CHECK(hugoOps.pkReadRecord(pNdb, 1, true) == 0);
+ CHECK(hugoOps.pkReadRecord(pNdb, 1, 1, NdbOperation::LM_Exclusive) == 0);
CHECK(hugoOps.execute_Commit(pNdb, TryCommit) == 626);
CHECK(hugoOps.closeTransaction(pNdb) == 0);
@@ -475,11 +475,11 @@ int runCommit_TryCommit626(NDBT_Context* ctx, NDBT_Step* step){
// Several operations in one transaction
// The insert is OK
CHECK(hugoOps.startTransaction(pNdb) == 0);
- CHECK(hugoOps.pkReadRecord(pNdb, 1, true) == 0);
- CHECK(hugoOps.pkReadRecord(pNdb, 2, true) == 0);
- CHECK(hugoOps.pkReadRecord(pNdb, 3, true) == 0);
+ CHECK(hugoOps.pkReadRecord(pNdb, 1, 1, NdbOperation::LM_Exclusive) == 0);
+ CHECK(hugoOps.pkReadRecord(pNdb, 2, 1, NdbOperation::LM_Exclusive) == 0);
+ CHECK(hugoOps.pkReadRecord(pNdb, 3, 1, NdbOperation::LM_Exclusive) == 0);
CHECK(hugoOps.pkInsertRecord(pNdb, 1) == 0);
- CHECK(hugoOps.pkReadRecord(pNdb, 4, true) == 0);
+ CHECK(hugoOps.pkReadRecord(pNdb, 4, 1, NdbOperation::LM_Exclusive) == 0);
CHECK(hugoOps.execute_Commit(pNdb, TryCommit) == 626);
}while(false);
@@ -513,20 +513,23 @@ int runCommit_CommitAsMuchAsPossible626(NDBT_Context* ctx, NDBT_Step* step){
do{
// Commit transaction, CommitAsMuchAsPossible
CHECK(hugoOps.startTransaction(pNdb) == 0);
- CHECK(hugoOps.pkReadRecord(pNdb, 1, true) == 0);
+ CHECK(hugoOps.pkReadRecord(pNdb, 1, 1, NdbOperation::LM_Exclusive) == 0);
CHECK(hugoOps.execute_Commit(pNdb, CommitAsMuchAsPossible) == 626);
CHECK(hugoOps.closeTransaction(pNdb) == 0);
// Commit transaction, CommitAsMuchAsPossible
CHECK(hugoOps.startTransaction(pNdb) == 0);
- CHECK(hugoOps.pkReadRecord(pNdb, 1, true) == 0);
- CHECK(hugoOps.pkReadRecord(pNdb, 2, true) == 0);
- CHECK(hugoOps.pkReadRecord(pNdb, 3, true) == 0);
+ CHECK(hugoOps.pkReadRecord(pNdb, 2, 1, NdbOperation::LM_Exclusive) == 0);
+ CHECK(hugoOps.pkReadRecord(pNdb, 3, 1, NdbOperation::LM_Exclusive) == 0);
CHECK(hugoOps.pkInsertRecord(pNdb, 1) == 0);
- CHECK(hugoOps.pkReadRecord(pNdb, 4, true) == 0);
CHECK(hugoOps.execute_Commit(pNdb, CommitAsMuchAsPossible) == 626);
CHECK(hugoOps.closeTransaction(pNdb) == 0);
- }while(false);
+
+ CHECK(hugoOps.startTransaction(pNdb) == 0);
+ CHECK(hugoOps.pkReadRecord(pNdb, 1) == 0);
+ CHECK(hugoOps.execute_Commit(pNdb) == 0);
+ CHECK(hugoOps.closeTransaction(pNdb) == 0);
+ } while(false);
hugoOps.closeTransaction(pNdb);
@@ -542,8 +545,14 @@ int runCommit_CommitAsMuchAsPossible630(NDBT_Context* ctx, NDBT_Step* step){
// Commit transaction, CommitAsMuchAsPossible
CHECK(hugoOps.startTransaction(pNdb) == 0);
CHECK(hugoOps.pkInsertRecord(pNdb, 1) == 0);
+ CHECK(hugoOps.pkDeleteRecord(pNdb, 2) == 0);
CHECK(hugoOps.execute_Commit(pNdb, CommitAsMuchAsPossible) == 630);
- }while(false);
+ CHECK(hugoOps.closeTransaction(pNdb) == 0);
+
+ CHECK(hugoOps.startTransaction(pNdb) == 0);
+ CHECK(hugoOps.pkReadRecord(pNdb, 2) == 0);
+ CHECK(hugoOps.execute_Commit(pNdb) == 0);
+ } while(false);
hugoOps.closeTransaction(pNdb);
@@ -558,13 +567,13 @@ int runNoCommit626(NDBT_Context* ctx, NDBT_Step* step){
do{
// No commit transaction, readTuple
CHECK(hugoOps.startTransaction(pNdb) == 0);
- CHECK(hugoOps.pkReadRecord(pNdb, 1, false) == 0);
+ CHECK(hugoOps.pkReadRecord(pNdb, 1, 1, NdbOperation::LM_Read) == 0);
CHECK(hugoOps.execute_NoCommit(pNdb) == 626);
CHECK(hugoOps.closeTransaction(pNdb) == 0);
// No commit transaction, readTupleExcluive
CHECK(hugoOps.startTransaction(pNdb) == 0);
- CHECK(hugoOps.pkReadRecord(pNdb, 1, true) == 0);
+ CHECK(hugoOps.pkReadRecord(pNdb, 1, 1, NdbOperation::LM_Exclusive) == 0);
CHECK(hugoOps.execute_NoCommit(pNdb) == 626);
}while(false);
@@ -598,7 +607,7 @@ int runNoCommitRollback626(NDBT_Context* ctx, NDBT_Step* step){
do{
// No commit transaction, rollback
CHECK(hugoOps.startTransaction(pNdb) == 0);
- CHECK(hugoOps.pkReadRecord(pNdb, 1, true) == 0);
+ CHECK(hugoOps.pkReadRecord(pNdb, 1, 1, NdbOperation::LM_Exclusive) == 0);
CHECK(hugoOps.execute_NoCommit(pNdb) == 626);
CHECK(hugoOps.execute_Rollback(pNdb) == 0);
CHECK(hugoOps.closeTransaction(pNdb) == 0);
@@ -606,10 +615,10 @@ int runNoCommitRollback626(NDBT_Context* ctx, NDBT_Step* step){
// No commit transaction, rollback
// Multiple operations
CHECK(hugoOps.startTransaction(pNdb) == 0);
- CHECK(hugoOps.pkReadRecord(pNdb, 1, true) == 0);
- CHECK(hugoOps.pkReadRecord(pNdb, 2, true) == 0);
- CHECK(hugoOps.pkReadRecord(pNdb, 3, true) == 0);
- CHECK(hugoOps.pkReadRecord(pNdb, 4, true) == 0);
+ CHECK(hugoOps.pkReadRecord(pNdb, 1, 1, NdbOperation::LM_Exclusive) == 0);
+ CHECK(hugoOps.pkReadRecord(pNdb, 2, 1, NdbOperation::LM_Exclusive) == 0);
+ CHECK(hugoOps.pkReadRecord(pNdb, 3, 1, NdbOperation::LM_Exclusive) == 0);
+ CHECK(hugoOps.pkReadRecord(pNdb, 4, 1, NdbOperation::LM_Exclusive) == 0);
CHECK(hugoOps.execute_NoCommit(pNdb) == 626);
CHECK(hugoOps.execute_Rollback(pNdb) == 0);
}while(false);
@@ -647,7 +656,7 @@ int runNoCommitAndClose(NDBT_Context* ctx, NDBT_Step* step){
// Read
CHECK(hugoOps.startTransaction(pNdb) == 0);
for (i = 0; i < 10; i++)
- CHECK(hugoOps.pkReadRecord(pNdb, i, true) == 0);
+ CHECK(hugoOps.pkReadRecord(pNdb, i, 1, NdbOperation::LM_Exclusive) == 0);
CHECK(hugoOps.execute_NoCommit(pNdb) == 0);
CHECK(hugoOps.closeTransaction(pNdb) == 0);
@@ -701,7 +710,7 @@ int runCheckRollbackDelete(NDBT_Context* ctx, NDBT_Step* step){
CHECK(hugoOps.execute_NoCommit(pNdb) == 0);
// Check record is deleted
- CHECK(hugoOps.pkReadRecord(pNdb, 5, true) == 0);
+ CHECK(hugoOps.pkReadRecord(pNdb, 5, 1, NdbOperation::LM_Exclusive) == 0);
CHECK(hugoOps.execute_NoCommit(pNdb) == 626);
CHECK(hugoOps.execute_Rollback(pNdb) == 0);
@@ -709,13 +718,13 @@ int runCheckRollbackDelete(NDBT_Context* ctx, NDBT_Step* step){
// Check record is not deleted
CHECK(hugoOps.startTransaction(pNdb) == 0);
- CHECK(hugoOps.pkReadRecord(pNdb, 5, true) == 0);
+ CHECK(hugoOps.pkReadRecord(pNdb, 5, 1, NdbOperation::LM_Exclusive) == 0);
CHECK(hugoOps.execute_Commit(pNdb) == 0);
CHECK(hugoOps.closeTransaction(pNdb) == 0);
// Check record is back to original value
CHECK(hugoOps.startTransaction(pNdb) == 0);
- CHECK(hugoOps.pkReadRecord(pNdb, 5, true) == 0);
+ CHECK(hugoOps.pkReadRecord(pNdb, 5, 1, NdbOperation::LM_Exclusive) == 0);
CHECK(hugoOps.execute_Commit(pNdb) == 0);
CHECK(hugoOps.compareRecordToCopy() == NDBT_OK);
@@ -736,7 +745,7 @@ int runCheckRollbackUpdate(NDBT_Context* ctx, NDBT_Step* step){
// Read value and save it for later
CHECK(hugoOps.startTransaction(pNdb) == 0);
- CHECK(hugoOps.pkReadRecord(pNdb, 1, false, numRecords) == 0);
+ CHECK(hugoOps.pkReadRecord(pNdb, 1, numRecords) == 0);
CHECK(hugoOps.execute_Commit(pNdb) == 0);
CHECK(hugoOps.verifyUpdatesValue(0) == NDBT_OK); // Update value 0
CHECK(hugoOps.closeTransaction(pNdb) == 0);
@@ -747,7 +756,7 @@ int runCheckRollbackUpdate(NDBT_Context* ctx, NDBT_Step* step){
CHECK(hugoOps.execute_NoCommit(pNdb) == 0);
// Check record is updated
- CHECK(hugoOps.pkReadRecord(pNdb, 1, true, numRecords) == 0);
+ CHECK(hugoOps.pkReadRecord(pNdb, 1, numRecords, NdbOperation::LM_Exclusive) == 0);
CHECK(hugoOps.execute_NoCommit(pNdb) == 0);
CHECK(hugoOps.verifyUpdatesValue(5) == NDBT_OK); // Updates value 5
CHECK(hugoOps.execute_Rollback(pNdb) == 0);
@@ -756,7 +765,7 @@ int runCheckRollbackUpdate(NDBT_Context* ctx, NDBT_Step* step){
// Check record is back to original value
CHECK(hugoOps.startTransaction(pNdb) == 0);
- CHECK(hugoOps.pkReadRecord(pNdb, 1, true, numRecords) == 0);
+ CHECK(hugoOps.pkReadRecord(pNdb, 1, numRecords, NdbOperation::LM_Exclusive) == 0);
CHECK(hugoOps.execute_Commit(pNdb) == 0);
CHECK(hugoOps.verifyUpdatesValue(0) == NDBT_OK); // Updates value 0
@@ -775,7 +784,7 @@ int runCheckRollbackDeleteMultiple(NDBT_Context* ctx, NDBT_Step* step){
do{
// Read value and save it for later
CHECK(hugoOps.startTransaction(pNdb) == 0);
- CHECK(hugoOps.pkReadRecord(pNdb, 5, false, 10) == 0);
+ CHECK(hugoOps.pkReadRecord(pNdb, 5, 10) == 0);
CHECK(hugoOps.execute_Commit(pNdb) == 0);
CHECK(hugoOps.verifyUpdatesValue(0) == NDBT_OK);
CHECK(hugoOps.closeTransaction(pNdb) == 0);
@@ -785,7 +794,7 @@ int runCheckRollbackDeleteMultiple(NDBT_Context* ctx, NDBT_Step* step){
for(Uint32 i = 0; i<1; i++){
// Read record 5 - 10
CHECK(hugoOps.startTransaction(pNdb) == 0);
- CHECK(hugoOps.pkReadRecord(pNdb, 5, true, 10) == 0);
+ CHECK(hugoOps.pkReadRecord(pNdb, 5, 10, NdbOperation::LM_Exclusive) == 0);
CHECK(hugoOps.execute_NoCommit(pNdb) == 0);
for(j = 0; j<10; j++){
@@ -794,7 +803,7 @@ int runCheckRollbackDeleteMultiple(NDBT_Context* ctx, NDBT_Step* step){
CHECK(hugoOps.pkUpdateRecord(pNdb, 5, 10, updatesValue) == 0);
CHECK(hugoOps.execute_NoCommit(pNdb) == 0);
- CHECK(hugoOps.pkReadRecord(pNdb, 5, true, 10) == 0);
+ CHECK(hugoOps.pkReadRecord(pNdb, 5, 10, NdbOperation::LM_Exclusive) == 0);
CHECK(hugoOps.execute_NoCommit(pNdb) == 0);
CHECK(hugoOps.verifyUpdatesValue(updatesValue) == 0);
}
@@ -806,7 +815,7 @@ int runCheckRollbackDeleteMultiple(NDBT_Context* ctx, NDBT_Step* step){
#if 0
// Check records are deleted
- CHECK(hugoOps.pkReadRecord(pNdb, 5, true, 10) == 0);
+ CHECK(hugoOps.pkReadRecord(pNdb, 5, 10, NdbOperation::LM_Exclusive) == 0);
CHECK(hugoOps.execute_NoCommit(pNdb) == 626);
#endif
@@ -814,7 +823,7 @@ int runCheckRollbackDeleteMultiple(NDBT_Context* ctx, NDBT_Step* step){
CHECK(hugoOps.pkInsertRecord(pNdb, 5, 10, updatesValue) == 0);
CHECK(hugoOps.execute_NoCommit(pNdb) == 0);
- CHECK(hugoOps.pkReadRecord(pNdb, 5, true, 10) == 0);
+ CHECK(hugoOps.pkReadRecord(pNdb, 5, 10, NdbOperation::LM_Exclusive) == 0);
CHECK(hugoOps.execute_NoCommit(pNdb) == 0);
CHECK(hugoOps.verifyUpdatesValue(updatesValue) == 0);
}
@@ -823,7 +832,7 @@ int runCheckRollbackDeleteMultiple(NDBT_Context* ctx, NDBT_Step* step){
CHECK(hugoOps.execute_NoCommit(pNdb) == 0);
// Check records are deleted
- CHECK(hugoOps.pkReadRecord(pNdb, 5, true, 10) == 0);
+ CHECK(hugoOps.pkReadRecord(pNdb, 5, 10, NdbOperation::LM_Exclusive) == 0);
CHECK(hugoOps.execute_NoCommit(pNdb) == 626);
CHECK(hugoOps.execute_Rollback(pNdb) == 0);
@@ -833,7 +842,7 @@ int runCheckRollbackDeleteMultiple(NDBT_Context* ctx, NDBT_Step* step){
// Check records are not deleted
// after rollback
CHECK(hugoOps.startTransaction(pNdb) == 0);
- CHECK(hugoOps.pkReadRecord(pNdb, 5, true, 10) == 0);
+ CHECK(hugoOps.pkReadRecord(pNdb, 5, 10, NdbOperation::LM_Exclusive) == 0);
CHECK(hugoOps.execute_Commit(pNdb) == 0);
CHECK(hugoOps.verifyUpdatesValue(0) == NDBT_OK);
@@ -853,7 +862,7 @@ int runCheckImplicitRollbackDelete(NDBT_Context* ctx, NDBT_Step* step){
do{
// Read record 5
CHECK(hugoOps.startTransaction(pNdb) == 0);
- CHECK(hugoOps.pkReadRecord(pNdb, 5, true) == 0);
+ CHECK(hugoOps.pkReadRecord(pNdb, 5, 1, NdbOperation::LM_Exclusive) == 0);
CHECK(hugoOps.execute_NoCommit(pNdb) == 0);
CHECK(hugoOps.closeTransaction(pNdb) == 0);
@@ -872,7 +881,7 @@ int runCheckImplicitRollbackDelete(NDBT_Context* ctx, NDBT_Step* step){
// Check record is not deleted
// Close transaction should have rollbacked
CHECK(hugoOps.startTransaction(pNdb) == 0);
- CHECK(hugoOps.pkReadRecord(pNdb, 5, true) == 0);
+ CHECK(hugoOps.pkReadRecord(pNdb, 5, 1, NdbOperation::LM_Exclusive) == 0);
CHECK(hugoOps.execute_Commit(pNdb) == 0);
}while(false);
@@ -889,7 +898,7 @@ int runCheckCommitDelete(NDBT_Context* ctx, NDBT_Step* step){
do{
// Read 10 records
CHECK(hugoOps.startTransaction(pNdb) == 0);
- CHECK(hugoOps.pkReadRecord(pNdb, 5, true, 10) == 0);
+ CHECK(hugoOps.pkReadRecord(pNdb, 5, 10, NdbOperation::LM_Exclusive) == 0);
CHECK(hugoOps.execute_NoCommit(pNdb) == 0);
// Update 10 records
@@ -905,7 +914,7 @@ int runCheckCommitDelete(NDBT_Context* ctx, NDBT_Step* step){
// Check record's are deleted
CHECK(hugoOps.startTransaction(pNdb) == 0);
- CHECK(hugoOps.pkReadRecord(pNdb, 5, true, 10) == 0);
+ CHECK(hugoOps.pkReadRecord(pNdb, 5, 10, NdbOperation::LM_Exclusive) == 0);
CHECK(hugoOps.execute_Commit(pNdb) == 626);
}while(false);
@@ -930,7 +939,7 @@ int runRollbackNothing(NDBT_Context* ctx, NDBT_Step* step){
// Check records are not deleted
CHECK(hugoOps.startTransaction(pNdb) == 0);
- CHECK(hugoOps.pkReadRecord(pNdb, 5, true, 10) == 0);
+ CHECK(hugoOps.pkReadRecord(pNdb, 5, 10, NdbOperation::LM_Exclusive) == 0);
CHECK(hugoOps.execute_Commit(pNdb) == 0);
CHECK(hugoOps.closeTransaction(pNdb) == 0);
@@ -964,8 +973,8 @@ int runMassiveRollback(NDBT_Context* ctx, NDBT_Step* step){
for(int row = 0; row < records; row++){
int res;
CHECK(hugoOps.startTransaction(pNdb) == 0);
- for(int i = 0; i<OPS_TOTAL; i += OPS_PER_TRANS){
- for(int j = 0; j<OPS_PER_TRANS; j++){
+ for(Uint32 i = 0; i<OPS_TOTAL; i += OPS_PER_TRANS){
+ for(Uint32 j = 0; j<OPS_PER_TRANS; j++){
CHECK(hugoOps.pkUpdateRecord(pNdb, row, 1, i) == 0);
}
g_info << "Performed " << (i+OPS_PER_TRANS) << " updates on row: " << row
@@ -1007,9 +1016,9 @@ runMassiveRollback2(NDBT_Context* ctx, NDBT_Step* step){
const Uint32 OPS_TOTAL = 4096;
const Uint32 LOOPS = 10;
- for(int loop = 0; loop<LOOPS; loop++){
+ for(Uint32 loop = 0; loop<LOOPS; loop++){
CHECK(hugoOps.startTransaction(pNdb) == 0);
- for(int i = 0; i<OPS_TOTAL-1; i ++){
+ for(Uint32 i = 0; i<OPS_TOTAL-1; i ++){
if((i & 1) == 0){
CHECK(hugoOps.pkUpdateRecord(pNdb, 0, 1, loop) == 0);
} else {
@@ -1110,13 +1119,6 @@ TESTCASE("ReadWithLocksAndInserts",
STEP(runInsertUntilStopped);
FINALIZER(runClearTable);
}
-TESTCASE("ReadConsistency",
- "Check that a read within a transaction returns the " \
- "same result no matter"){
- STEP(runInsertOne);
- STEP(runReadOne);
- FINALIZER(runClearTable2);
-}
TESTCASE("PkInsertTwice",
"Verify that we can't insert an already inserted record."
"Error should be returned" ){
@@ -1124,12 +1126,6 @@ TESTCASE("PkInsertTwice",
STEP(runInsertTwice);
FINALIZER(runClearTable);
}
-TESTCASE("Fill",
- "Verify what happens when we fill the db" ){
- INITIALIZER(runFillTable);
- INITIALIZER(runPkRead);
- FINALIZER(runClearTable2);
-}
TESTCASE("NoCommitSleep",
"Verify what happens when a NoCommit transaction is aborted by "
"NDB because the application is sleeping" ){
@@ -1275,8 +1271,24 @@ TESTCASE("MassiveTransaction",
INITIALIZER(runLoadTable2);
FINALIZER(runClearTable2);
}
+TESTCASE("Fill",
+ "Verify what happens when we fill the db" ){
+ INITIALIZER(runFillTable);
+ INITIALIZER(runPkRead);
+ FINALIZER(runClearTable2);
+}
NDBT_TESTSUITE_END(testBasic);
+#if 0
+TESTCASE("ReadConsistency",
+ "Check that a read within a transaction returns the " \
+ "same result no matter"){
+ STEP(runInsertOne);
+ STEP(runReadOne);
+ FINALIZER(runClearTable2);
+}
+#endif
+
int main(int argc, const char** argv){
ndb_init();
return testBasic.execute(argc, argv);
diff --git a/ndb/test/ndbapi/testBlobs.cpp b/ndb/test/ndbapi/testBlobs.cpp
index e18f4a8bd1a..41bb82f3e06 100644
--- a/ndb/test/ndbapi/testBlobs.cpp
+++ b/ndb/test/ndbapi/testBlobs.cpp
@@ -1030,7 +1030,7 @@ readScan(int style, bool idx)
} else {
CHK((g_ops = g_con->getNdbIndexScanOperation(g_opt.m_x2name, g_opt.m_tname)) != 0);
}
- CHK((rs = g_ops->readTuples(NdbScanOperation::LM_Exclusive)) != 0);
+ CHK((rs = g_ops->readTuples(NdbScanOperation::LM_Read)) != 0);
CHK(g_ops->getValue("PK1", (char*)&tup.m_pk1) != 0);
if (g_opt.m_pk2len != 0)
CHK(g_ops->getValue("PK2", tup.m_pk2) != 0);
diff --git a/ndb/test/ndbapi/testDataBuffers.cpp b/ndb/test/ndbapi/testDataBuffers.cpp
index 94658d5c6b9..04602f51d5f 100644
--- a/ndb/test/ndbapi/testDataBuffers.cpp
+++ b/ndb/test/ndbapi/testDataBuffers.cpp
@@ -93,7 +93,7 @@ ndberror(char const* fmt, ...)
va_list ap;
char buf[200];
va_start(ap, fmt);
- vsnprintf(buf, sizeof(buf), fmt, ap);
+ BaseString::vsnprintf(buf, sizeof(buf), fmt, ap);
va_end(ap);
ndbout << buf << " --" << endl;
if (ndb)
@@ -115,7 +115,7 @@ chkerror(char const* fmt, ...)
va_list ap;
char buf[200];
va_start(ap, fmt);
- vsnprintf(buf, sizeof(buf), fmt, ap);
+ BaseString::vsnprintf(buf, sizeof(buf), fmt, ap);
va_end(ap);
ndbout << "*** check failed: " << buf << " ***" << endl;
return -1;
diff --git a/ndb/test/ndbapi/testDict.cpp b/ndb/test/ndbapi/testDict.cpp
index 7cba5ce4cc8..89232de2535 100644
--- a/ndb/test/ndbapi/testDict.cpp
+++ b/ndb/test/ndbapi/testDict.cpp
@@ -55,7 +55,7 @@ int runCreateInvalidTables(NDBT_Context* ctx, NDBT_Step* step){
char failTabName[256];
for (int i = 0; i < 10; i++){
- snprintf(failTabName, 256, "F%d", i);
+ BaseString::snprintf(failTabName, 256, "F%d", i);
const NdbDictionary::Table* pFailTab = NDBT_Tables::getTable(failTabName);
if (pFailTab != NULL){
@@ -425,7 +425,7 @@ int runCreateMaxTables(NDBT_Context* ctx, NDBT_Step* step){
Ndb* pNdb = GETNDB(step);
for (int i = 0; i < numTables && failures < 5; i++){
- snprintf(tabName, 256, "MAXTAB%d", i);
+ BaseString::snprintf(tabName, 256, "MAXTAB%d", i);
if (pNdb->waitUntilReady(30) != 0){
// Db is not ready, return with failure
@@ -491,7 +491,7 @@ int runDropMaxTables(NDBT_Context* ctx, NDBT_Step* step){
Ndb* pNdb = GETNDB(step);
for (int i = 0; i < numTables; i++){
- snprintf(tabName, 256, "MAXTAB%d", i);
+ BaseString::snprintf(tabName, 256, "MAXTAB%d", i);
if (pNdb->waitUntilReady(30) != 0){
// Db is not ready, return with failure
@@ -707,7 +707,7 @@ int runPkSizes(NDBT_Context* ctx, NDBT_Step* step){
int numRecords = ctx->getNumRecords();
for (int i = minPkSize; i < maxPkSize; i++){
- snprintf(tabName, 256, "TPK_%d", i);
+ BaseString::snprintf(tabName, 256, "TPK_%d", i);
int records = numRecords;
int max = ~0;
diff --git a/ndb/test/ndbapi/testIndex.cpp b/ndb/test/ndbapi/testIndex.cpp
index bef3b310c96..ed9e114fd92 100644
--- a/ndb/test/ndbapi/testIndex.cpp
+++ b/ndb/test/ndbapi/testIndex.cpp
@@ -150,7 +150,7 @@ int create_index(NDBT_Context* ctx, int indxNum,
}
// Create index
- snprintf(idxName, 255, "IDC%d", indxNum);
+ BaseString::snprintf(idxName, 255, "IDC%d", indxNum);
if (orderedIndex)
ndbout << "Creating " << ((logged)?"logged ": "temporary ") << "ordered index "<<idxName << " (";
else
@@ -194,7 +194,7 @@ int drop_index(int indxNum, Ndb* pNdb,
if (attr->indexCreated == false)
return NDBT_OK;
- snprintf(idxName, 255, "IDC%d", indxNum);
+ BaseString::snprintf(idxName, 255, "IDC%d", indxNum);
// Drop index
ndbout << "Dropping index "<<idxName<<"(" << pTab->getName() << ") ";
@@ -284,7 +284,7 @@ int createRandomIndex_Drop(NDBT_Context* ctx, NDBT_Step* step){
Uint32 i = ctx->getProperty("createRandomIndex");
- snprintf(idxName, 255, "IDC%d", i);
+ BaseString::snprintf(idxName, 255, "IDC%d", i);
// Drop index
ndbout << "Dropping index " << idxName << " ";
@@ -309,7 +309,7 @@ int createPkIndex(NDBT_Context* ctx, NDBT_Step* step){
bool logged = ctx->getProperty("LoggedIndexes", 1);
// Create index
- snprintf(pkIdxName, 255, "IDC_PK_%s", pTab->getName());
+ BaseString::snprintf(pkIdxName, 255, "IDC_PK_%s", pTab->getName());
if (orderedIndex)
ndbout << "Creating " << ((logged)?"logged ": "temporary ") << "ordered index "
<< pkIdxName << " (";
@@ -381,27 +381,6 @@ runVerifyIndex(NDBT_Context* ctx, NDBT_Step* step){
}
int
-sync_down(NDBT_Context* ctx){
- Uint32 threads = ctx->getProperty("PauseThreads", (unsigned)0);
- if(threads){
- ctx->decProperty("PauseThreads");
- }
- return 0;
-}
-
-int
-sync_up_and_wait(NDBT_Context* ctx){
- Uint32 threads = ctx->getProperty("Threads", (unsigned)0);
- ndbout_c("Setting PauseThreads to %d", threads);
- ctx->setProperty("PauseThreads", threads);
- ctx->getPropertyWait("PauseThreads", (unsigned)0);
- if(threads){
- ndbout_c("wait completed");
- }
- return 0;
-}
-
-int
runTransactions1(NDBT_Context* ctx, NDBT_Step* step){
// Verify that data in index match
// table data
@@ -416,7 +395,7 @@ runTransactions1(NDBT_Context* ctx, NDBT_Step* step){
return NDBT_FAILED;
}
- sync_down(ctx);
+ ctx->sync_down("PauseThreads");
if(ctx->isTestStopped())
break;
@@ -425,7 +404,7 @@ runTransactions1(NDBT_Context* ctx, NDBT_Step* step){
return NDBT_FAILED;
}
- sync_down(ctx);
+ ctx->sync_down("PauseThreads");
}
return NDBT_OK;
}
@@ -446,7 +425,7 @@ runTransactions2(NDBT_Context* ctx, NDBT_Step* step){
return NDBT_FAILED;
}
#endif
- sync_down(ctx);
+ ctx->sync_down("PauseThreads");
if(ctx->isTestStopped())
break;
#if 1
@@ -455,7 +434,7 @@ runTransactions2(NDBT_Context* ctx, NDBT_Step* step){
return NDBT_FAILED;
}
#endif
- sync_down(ctx);
+ ctx->sync_down("PauseThreads");
}
return NDBT_OK;
}
@@ -476,7 +455,7 @@ runTransactions3(NDBT_Context* ctx, NDBT_Step* step){
g_err << "Load table failed" << endl;
return NDBT_FAILED;
}
- sync_down(ctx);
+ ctx->sync_down("PauseThreads");
if(ctx->isTestStopped())
break;
@@ -485,7 +464,7 @@ runTransactions3(NDBT_Context* ctx, NDBT_Step* step){
return NDBT_FAILED;
}
- sync_down(ctx);
+ ctx->sync_down("PauseThreads");
if(ctx->isTestStopped())
break;
@@ -494,7 +473,7 @@ runTransactions3(NDBT_Context* ctx, NDBT_Step* step){
return NDBT_FAILED;
}
- sync_down(ctx);
+ ctx->sync_down("PauseThreads");
if(ctx->isTestStopped())
break;
@@ -503,7 +482,7 @@ runTransactions3(NDBT_Context* ctx, NDBT_Step* step){
return NDBT_FAILED;
}
- sync_down(ctx);
+ ctx->sync_down("PauseThreads");
if(ctx->isTestStopped())
break;
@@ -512,7 +491,7 @@ runTransactions3(NDBT_Context* ctx, NDBT_Step* step){
return NDBT_FAILED;
}
- sync_down(ctx);
+ ctx->sync_down("PauseThreads");
if(ctx->isTestStopped())
break;
@@ -521,14 +500,14 @@ runTransactions3(NDBT_Context* ctx, NDBT_Step* step){
return NDBT_FAILED;
}
- sync_down(ctx);
+ ctx->sync_down("PauseThreads");
if(ctx->isTestStopped())
break;
int count = -1;
if(utilTrans.selectCount(pNdb, 64, &count) != 0 || count != 0)
return NDBT_FAILED;
- sync_down(ctx);
+ ctx->sync_down("PauseThreads");
}
return NDBT_OK;
}
@@ -540,6 +519,7 @@ int runRestarts(NDBT_Context* ctx, NDBT_Step* step){
NdbRestarts restarts;
int i = 0;
int timeout = 240;
+ int sync_threads = ctx->getProperty("Threads", (unsigned)0);
while(i<loops && result != NDBT_FAILED && !ctx->isTestStopped()){
if(restarts.executeRestart("RestartRandomNodeAbort", timeout) != 0){
@@ -547,7 +527,7 @@ int runRestarts(NDBT_Context* ctx, NDBT_Step* step){
result = NDBT_FAILED;
break;
}
- sync_up_and_wait(ctx);
+ ctx->sync_up_and_wait("PauseThreads", sync_threads);
i++;
}
ctx->stopTest();
@@ -1088,7 +1068,7 @@ runUniqueNullTransactions(NDBT_Context* ctx, NDBT_Step* step){
const NdbDictionary::Table* pTab = ctx->getTab();
// Create index
char nullIndex[255];
- snprintf(nullIndex, 255, "IDC_PK_%s_NULL", pTab->getName());
+ BaseString::snprintf(nullIndex, 255, "IDC_PK_%s_NULL", pTab->getName());
if (orderedIndex)
ndbout << "Creating " << ((logged)?"logged ": "temporary ") << "ordered index "
<< pkIdxName << " (";
diff --git a/ndb/test/ndbapi/testNdbApi.cpp b/ndb/test/ndbapi/testNdbApi.cpp
index 47987629fe3..74cb1f8bcd0 100644
--- a/ndb/test/ndbapi/testNdbApi.cpp
+++ b/ndb/test/ndbapi/testNdbApi.cpp
@@ -229,7 +229,7 @@ int runTestMaxOperations(NDBT_Context* ctx, NDBT_Step* step){
int i = 0;
while (errors < maxErrors){
- if(hugoOps.pkReadRecord(pNdb,1, false, 1) != NDBT_OK){
+ if(hugoOps.pkReadRecord(pNdb,1, 1) != NDBT_OK){
errors++;
continue;
}
diff --git a/ndb/test/ndbapi/testNodeRestart.cpp b/ndb/test/ndbapi/testNodeRestart.cpp
index 6bfe59f8d3f..e844f227034 100644
--- a/ndb/test/ndbapi/testNodeRestart.cpp
+++ b/ndb/test/ndbapi/testNodeRestart.cpp
@@ -100,11 +100,16 @@ int runScanReadUntilStopped(NDBT_Context* ctx, NDBT_Step* step){
int runPkReadUntilStopped(NDBT_Context* ctx, NDBT_Step* step){
int result = NDBT_OK;
int records = ctx->getNumRecords();
+ NdbOperation::LockMode lm =
+ (NdbOperation::LockMode)ctx->getProperty("ReadLockMode",
+ (Uint32)NdbOperation::LM_Read);
int i = 0;
HugoTransactions hugoTrans(*ctx->getTab());
while (ctx->isTestStopped() == false) {
g_info << i << ": ";
- if (hugoTrans.pkReadRecords(GETNDB(step), records, 128) != 0){
+ int rows = (rand()%records)+1;
+ int batch = (rand()%rows)+1;
+ if (hugoTrans.pkReadRecords(GETNDB(step), rows, batch, lm) != 0){
return NDBT_FAILED;
}
i++;
@@ -119,7 +124,9 @@ int runPkUpdateUntilStopped(NDBT_Context* ctx, NDBT_Step* step){
HugoTransactions hugoTrans(*ctx->getTab());
while (ctx->isTestStopped() == false) {
g_info << i << ": ";
- if (hugoTrans.pkUpdateRecords(GETNDB(step), records) != 0){
+ int rows = (rand()%records)+1;
+ int batch = (rand()%rows)+1;
+ if (hugoTrans.pkUpdateRecords(GETNDB(step), rows, batch) != 0){
return NDBT_FAILED;
}
i++;
@@ -127,6 +134,60 @@ int runPkUpdateUntilStopped(NDBT_Context* ctx, NDBT_Step* step){
return result;
}
+int runPkReadPkUpdateUntilStopped(NDBT_Context* ctx, NDBT_Step* step){
+ int result = NDBT_OK;
+ int records = ctx->getNumRecords();
+ Ndb* pNdb = GETNDB(step);
+ int i = 0;
+ HugoOperations hugoOps(*ctx->getTab());
+ while (ctx->isTestStopped() == false) {
+ g_info << i++ << ": ";
+ int rows = (rand()%records)+1;
+ int batch = (rand()%rows)+1;
+ int row = (records - rows) ? rand() % (records - rows) : 0;
+
+ int j,k;
+ for(j = 0; j<rows; j += batch)
+ {
+ k = batch;
+ if(j+k > rows)
+ k = rows - j;
+
+ if(hugoOps.startTransaction(pNdb) != 0)
+ goto err;
+
+ if(hugoOps.pkReadRecord(pNdb, row+j, k, NdbOperation::LM_Exclusive) != 0)
+ goto err;
+
+ if(hugoOps.execute_NoCommit(pNdb) != 0)
+ goto err;
+
+ if(hugoOps.pkUpdateRecord(pNdb, row+j, k, rand()) != 0)
+ goto err;
+
+ if(hugoOps.execute_Commit(pNdb) != 0)
+ goto err;
+
+ if(hugoOps.closeTransaction(pNdb) != 0)
+ return NDBT_FAILED;
+ }
+
+ continue;
+err:
+ NdbConnection* pCon = hugoOps.getTransaction();
+ if(pCon == 0)
+ continue;
+ NdbError error = pCon->getNdbError();
+ hugoOps.closeTransaction(pNdb);
+ if (error.status == NdbError::TemporaryError){
+ NdbSleep_MilliSleep(50);
+ continue;
+ }
+ return NDBT_FAILED;
+ }
+ return NDBT_OK;
+}
+
int runScanUpdateUntilStopped(NDBT_Context* ctx, NDBT_Step* step){
int result = NDBT_OK;
int records = ctx->getNumRecords();
@@ -158,6 +219,7 @@ int runScanReadVerify(NDBT_Context* ctx, NDBT_Step* step){
int runRestarter(NDBT_Context* ctx, NDBT_Step* step){
int result = NDBT_OK;
int loops = ctx->getNumLoops();
+ int sync_threads = ctx->getProperty("SyncThreads", (unsigned)0);
NdbRestarter restarter;
int i = 0;
int lastId = 0;
@@ -174,11 +236,11 @@ int runRestarter(NDBT_Context* ctx, NDBT_Step* step){
loops *= restarter.getNumDbNodes();
while(i<loops && result != NDBT_FAILED && !ctx->isTestStopped()){
-
+
int id = lastId % restarter.getNumDbNodes();
int nodeId = restarter.getDbNodeId(id);
ndbout << "Restart node " << nodeId << endl;
- if(restarter.restartOneDbNode(nodeId) != 0){
+ if(restarter.restartOneDbNode(nodeId, false, false, true) != 0){
g_err << "Failed to restartNextDbNode" << endl;
result = NDBT_FAILED;
break;
@@ -190,7 +252,7 @@ int runRestarter(NDBT_Context* ctx, NDBT_Step* step){
break;
}
- NdbSleep_SecSleep(1);
+ ctx->sync_up_and_wait("PauseThreads", sync_threads);
lastId++;
i++;
@@ -234,6 +296,54 @@ int runRestarts(NDBT_Context* ctx, NDBT_Step* step){
return result;
}
+int runDirtyRead(NDBT_Context* ctx, NDBT_Step* step){
+ int result = NDBT_OK;
+ int loops = ctx->getNumLoops();
+ int records = ctx->getNumRecords();
+ NdbRestarter restarter;
+ HugoOperations hugoOps(*ctx->getTab());
+ Ndb* pNdb = GETNDB(step);
+
+ int i = 0;
+ while(i<loops && result != NDBT_FAILED && !ctx->isTestStopped()){
+ g_info << i << ": ";
+
+ int id = i % restarter.getNumDbNodes();
+ int nodeId = restarter.getDbNodeId(id);
+ ndbout << "Restart node " << nodeId << endl;
+ restarter.insertErrorInAllNodes(5041);
+ restarter.insertErrorInAllNodes(8048 + (i & 1));
+
+ for(int j = 0; j<records; j++){
+ if(hugoOps.startTransaction(pNdb) != 0)
+ return NDBT_FAILED;
+
+ if(hugoOps.pkReadRecord(pNdb, j, 1, NdbOperation::LM_CommittedRead) != 0)
+ goto err;
+
+ int res;
+ if((res = hugoOps.execute_Commit(pNdb)) == 4119)
+ goto done;
+
+ if(res != 0)
+ goto err;
+
+ if(hugoOps.closeTransaction(pNdb) != 0)
+ return NDBT_FAILED;
+ }
+done:
+ if(hugoOps.closeTransaction(pNdb) != 0)
+ return NDBT_FAILED;
+
+ i++;
+ restarter.waitClusterStarted(60) ;
+ }
+ return result;
+err:
+ hugoOps.closeTransaction(pNdb);
+ return NDBT_FAILED;
+}
+
NDBT_TESTSUITE(testNodeRestart);
TESTCASE("NoLoad",
"Test that one node at a time can be stopped and then restarted "\
@@ -246,6 +356,27 @@ TESTCASE("NoLoad",
TESTCASE("PkRead",
"Test that one node at a time can be stopped and then restarted "\
"perform pk read while restarting. Do this loop number of times"){
+ TC_PROPERTY("ReadLockMode", NdbOperation::LM_Read);
+ INITIALIZER(runCheckAllNodesStarted);
+ INITIALIZER(runLoadTable);
+ STEP(runRestarter);
+ STEP(runPkReadUntilStopped);
+ FINALIZER(runClearTable);
+}
+TESTCASE("PkReadCommitted",
+ "Test that one node at a time can be stopped and then restarted "\
+ "perform pk read while restarting. Do this loop number of times"){
+ TC_PROPERTY("ReadLockMode", NdbOperation::LM_CommittedRead);
+ INITIALIZER(runCheckAllNodesStarted);
+ INITIALIZER(runLoadTable);
+ STEP(runRestarter);
+ STEP(runPkReadUntilStopped);
+ FINALIZER(runClearTable);
+}
+TESTCASE("MixedPkRead",
+ "Test that one node at a time can be stopped and then restarted "\
+ "perform pk read while restarting. Do this loop number of times"){
+ TC_PROPERTY("ReadLockMode", -1);
INITIALIZER(runCheckAllNodesStarted);
INITIALIZER(runLoadTable);
STEP(runRestarter);
@@ -255,14 +386,31 @@ TESTCASE("PkRead",
TESTCASE("PkReadPkUpdate",
"Test that one node at a time can be stopped and then restarted "\
"perform pk read and pk update while restarting. Do this loop number of times"){
+ TC_PROPERTY("ReadLockMode", NdbOperation::LM_Read);
INITIALIZER(runCheckAllNodesStarted);
INITIALIZER(runLoadTable);
STEP(runRestarter);
STEP(runPkReadUntilStopped);
+ STEP(runPkUpdateUntilStopped);
+ STEP(runPkReadPkUpdateUntilStopped);
STEP(runPkReadUntilStopped);
+ STEP(runPkUpdateUntilStopped);
+ STEP(runPkReadPkUpdateUntilStopped);
+ FINALIZER(runClearTable);
+}
+TESTCASE("MixedPkReadPkUpdate",
+ "Test that one node at a time can be stopped and then restarted "\
+ "perform pk read and pk update while restarting. Do this loop number of times"){
+ TC_PROPERTY("ReadLockMode", -1);
+ INITIALIZER(runCheckAllNodesStarted);
+ INITIALIZER(runLoadTable);
+ STEP(runRestarter);
STEP(runPkReadUntilStopped);
+ STEP(runPkUpdateUntilStopped);
+ STEP(runPkReadPkUpdateUntilStopped);
STEP(runPkReadUntilStopped);
STEP(runPkUpdateUntilStopped);
+ STEP(runPkReadPkUpdateUntilStopped);
FINALIZER(runClearTable);
}
TESTCASE("ReadUpdateScan",
@@ -273,6 +421,21 @@ TESTCASE("ReadUpdateScan",
STEP(runRestarter);
STEP(runPkReadUntilStopped);
STEP(runPkUpdateUntilStopped);
+ STEP(runPkReadPkUpdateUntilStopped);
+ STEP(runScanReadUntilStopped);
+ STEP(runScanUpdateUntilStopped);
+ FINALIZER(runClearTable);
+}
+TESTCASE("MixedReadUpdateScan",
+ "Test that one node at a time can be stopped and then restarted "\
+ "perform pk read, pk update and scan reads while restarting. Do this loop number of times"){
+ TC_PROPERTY("ReadLockMode", -1);
+ INITIALIZER(runCheckAllNodesStarted);
+ INITIALIZER(runLoadTable);
+ STEP(runRestarter);
+ STEP(runPkReadUntilStopped);
+ STEP(runPkUpdateUntilStopped);
+ STEP(runPkReadPkUpdateUntilStopped);
STEP(runScanReadUntilStopped);
STEP(runScanUpdateUntilStopped);
FINALIZER(runClearTable);
@@ -431,6 +594,12 @@ TESTCASE("StopOnError",
FINALIZER(runScanReadVerify);
FINALIZER(runClearTable);
}
+TESTCASE("CommittedRead",
+ "Test committed read"){
+ INITIALIZER(runLoadTable);
+ STEP(runDirtyRead);
+ FINALIZER(runClearTable);
+}
NDBT_TESTSUITE_END(testNodeRestart);
int main(int argc, const char** argv){
diff --git a/ndb/test/ndbapi/testOIBasic.cpp b/ndb/test/ndbapi/testOIBasic.cpp
index f9eb3514926..1c611d2b8ff 100644
--- a/ndb/test/ndbapi/testOIBasic.cpp
+++ b/ndb/test/ndbapi/testOIBasic.cpp
@@ -40,18 +40,21 @@ struct Opt {
bool m_core;
const char* m_csname;
CHARSET_INFO* m_cs;
+ int m_die;
bool m_dups;
NdbDictionary::Object::FragmentType m_fragtype;
- unsigned m_idxloop;
+ unsigned m_subsubloop;
const char* m_index;
unsigned m_loop;
- bool m_nologging;
bool m_msglock;
+ bool m_nologging;
+ bool m_noverify;
unsigned m_pctnull;
unsigned m_rows;
unsigned m_samples;
- unsigned m_scanrd;
- unsigned m_scanex;
+ unsigned m_scanbat;
+ unsigned m_scanpar;
+ unsigned m_scanstop;
unsigned m_seed;
unsigned m_subloop;
const char* m_table;
@@ -64,22 +67,25 @@ struct Opt {
m_core(false),
m_csname("latin1_bin"),
m_cs(0),
+ m_die(0),
m_dups(false),
m_fragtype(NdbDictionary::Object::FragUndefined),
- m_idxloop(4),
+ m_subsubloop(4),
m_index(0),
m_loop(1),
- m_nologging(false),
m_msglock(true),
+ m_nologging(false),
+ m_noverify(false),
m_pctnull(10),
m_rows(1000),
m_samples(0),
- m_scanrd(240),
- m_scanex(240),
+ m_scanbat(0),
+ m_scanpar(0),
+ m_scanstop(0),
m_seed(0),
m_subloop(4),
m_table(0),
- m_threads(4),
+ m_threads(10),
m_v(1) {
}
};
@@ -100,16 +106,18 @@ printhelp()
<< " -case abc only given test cases (letters a-z)" << endl
<< " -core core dump on error [" << d.m_core << "]" << endl
<< " -csname S charset (collation) of non-pk char column [" << d.m_csname << "]" << endl
+ << " -die nnn exit immediately on NDB error code nnn" << endl
<< " -dups allow duplicate tuples from index scan [" << d.m_dups << "]" << endl
<< " -fragtype T fragment type single/small/medium/large" << endl
<< " -index xyz only given index numbers (digits 1-9)" << endl
<< " -loop N loop count full suite 0=forever [" << d.m_loop << "]" << endl
<< " -nologging create tables in no-logging mode" << endl
+ << " -noverify skip index verifications" << endl
<< " -pctnull N pct NULL values in nullable column [" << d.m_pctnull << "]" << endl
<< " -rows N rows per thread [" << d.m_rows << "]" << endl
<< " -samples N samples for some timings (0=all) [" << d.m_samples << "]" << endl
- << " -scanrd N scan read parallelism [" << d.m_scanrd << "]" << endl
- << " -scanex N scan exclusive parallelism [" << d.m_scanex << "]" << endl
+ << " -scanbat N scan batch per fragment (ignored by ndb api) [" << d.m_scanbat << "]" << endl
+ << " -scanpar N scan parallelism [" << d.m_scanpar << "]" << endl
<< " -seed N srandom seed 0=loop number[" << d.m_seed << "]" << endl
<< " -subloop N subtest loop count [" << d.m_subloop << "]" << endl
<< " -table xyz only given table numbers (digits 1-9)" << endl
@@ -208,10 +216,14 @@ struct Par : public Opt {
Set& set() const { assert(m_set != 0); return *m_set; }
Tmr* m_tmr;
Tmr& tmr() const { assert(m_tmr != 0); return *m_tmr; }
+ unsigned m_lno;
+ unsigned m_slno;
unsigned m_totrows;
// value calculation
unsigned m_range;
unsigned m_pctrange;
+ // choice of key
+ bool m_randomkey;
// do verify after read
bool m_verify;
// deadlock possible
@@ -224,9 +236,12 @@ struct Par : public Opt {
m_tab(0),
m_set(0),
m_tmr(0),
+ m_lno(0),
+ m_slno(0),
m_totrows(m_threads * m_rows),
m_range(m_rows),
m_pctrange(0),
+ m_randomkey(false),
m_verify(false),
m_deadlock(false) {
}
@@ -688,13 +703,14 @@ struct Con {
int setBound(int num, int type, const void* value);
int execute(ExecType t);
int execute(ExecType t, bool& deadlock);
- int openScanRead(unsigned parallelism);
- int openScanExclusive(unsigned parallelism);
+ int openScanRead(unsigned scanbat, unsigned scanpar);
+ int openScanExclusive(unsigned scanbat, unsigned scanpar);
int executeScan();
int nextScanResult(bool fetchAllowed);
int nextScanResult(bool fetchAllowed, bool& deadlock);
int updateScanTuple(Con& con2);
int deleteScanTuple(Con& con2);
+ void closeScan();
void closeTransaction();
void printerror(NdbOut& out);
};
@@ -815,18 +831,20 @@ Con::execute(ExecType t, bool& deadlock)
}
int
-Con::openScanRead(unsigned parallelism)
+Con::openScanRead(unsigned scanbat, unsigned scanpar)
{
assert(m_tx != 0 && m_op != 0);
- CHKCON((m_resultset = m_scanop->readTuples(parallelism)) != 0, *this);
+ NdbOperation::LockMode lm = NdbOperation::LM_Read;
+ CHKCON((m_resultset = m_scanop->readTuples(lm, scanbat, scanpar)) != 0, *this);
return 0;
}
int
-Con::openScanExclusive(unsigned parallelism)
+Con::openScanExclusive(unsigned scanbat, unsigned scanpar)
{
assert(m_tx != 0 && m_op != 0);
- CHKCON((m_resultset = m_scanop->readTuplesExclusive(parallelism)) != 0, *this);
+ NdbOperation::LockMode lm = NdbOperation::LM_Exclusive;
+ CHKCON((m_resultset = m_scanop->readTuples(lm, scanbat, scanpar)) != 0, *this);
return 0;
}
@@ -880,11 +898,21 @@ Con::deleteScanTuple(Con& con2)
}
void
+Con::closeScan()
+{
+ assert(m_resultset != 0);
+ m_resultset->close();
+ m_scanop = 0, m_indexscanop = 0, m_resultset = 0;
+
+}
+
+void
Con::closeTransaction()
{
assert(m_ndb != 0 && m_tx != 0);
m_ndb->closeTransaction(m_tx);
m_tx = 0, m_op = 0;
+ m_scanop = 0, m_indexscanop = 0, m_resultset = 0;
}
void
@@ -893,27 +921,37 @@ Con::printerror(NdbOut& out)
m_errtype = ErrOther;
unsigned any = 0;
int code;
+ int die = 0;
if (m_ndb) {
if ((code = m_ndb->getNdbError().code) != 0) {
LL0(++any << " ndb: error " << m_ndb->getNdbError());
+ die += (code == g_opt.m_die);
}
if (m_dic && (code = m_dic->getNdbError().code) != 0) {
LL0(++any << " dic: error " << m_dic->getNdbError());
+ die += (code == g_opt.m_die);
}
if (m_tx) {
if ((code = m_tx->getNdbError().code) != 0) {
LL0(++any << " con: error " << m_tx->getNdbError());
+ die += (code == g_opt.m_die);
if (code == 266 || code == 274 || code == 296 || code == 297 || code == 499)
m_errtype = ErrDeadlock;
}
if (m_op && m_op->getNdbError().code != 0) {
LL0(++any << " op : error " << m_op->getNdbError());
+ die += (code == g_opt.m_die);
}
}
}
if (! any) {
LL0("failed but no NDB error code");
}
+ if (die) {
+ if (g_opt.m_core)
+ abort();
+ exit(1);
+ }
}
// dictionary operations
@@ -1965,9 +2003,21 @@ BSet::calcpk(Par par, unsigned i)
int
BSet::setbnd(Par par) const
{
- for (unsigned j = 0; j < m_bvals; j++) {
- const BVal& bval = *m_bval[j];
- CHK(bval.setbnd(par) == 0);
+ if (m_bvals != 0) {
+ unsigned p1 = urandom(m_bvals);
+ unsigned p2 = 10009; // prime
+ // random order
+ for (unsigned j = 0; j < m_bvals; j++) {
+ unsigned k = p1 + p2 * j;
+ const BVal& bval = *m_bval[k % m_bvals];
+ CHK(bval.setbnd(par) == 0);
+ }
+ // duplicate
+ if (urandom(5) == 0) {
+ unsigned k = urandom(m_bvals);
+ const BVal& bval = *m_bval[k];
+ CHK(bval.setbnd(par) == 0);
+ }
}
return 0;
}
@@ -2054,7 +2104,8 @@ pkinsert(Par par)
CHK(con.startTransaction() == 0);
Lst lst;
for (unsigned j = 0; j < par.m_rows; j++) {
- unsigned i = thrrow(par, j);
+ unsigned j2 = ! par.m_randomkey ? j : urandom(par.m_rows);
+ unsigned i = thrrow(par, j2);
set.lock();
if (set.exist(i) || set.pending(i)) {
set.unlock();
@@ -2107,7 +2158,8 @@ pkupdate(Par par)
Lst lst;
bool deadlock = false;
for (unsigned j = 0; j < par.m_rows; j++) {
- unsigned i = thrrow(par, j);
+ unsigned j2 = ! par.m_randomkey ? j : urandom(par.m_rows);
+ unsigned i = thrrow(par, j2);
set.lock();
if (! set.exist(i) || set.pending(i)) {
set.unlock();
@@ -2158,7 +2210,8 @@ pkdelete(Par par)
Lst lst;
bool deadlock = false;
for (unsigned j = 0; j < par.m_rows; j++) {
- unsigned i = thrrow(par, j);
+ unsigned j2 = ! par.m_randomkey ? j : urandom(par.m_rows);
+ unsigned i = thrrow(par, j2);
set.lock();
if (! set.exist(i) || set.pending(i)) {
set.unlock();
@@ -2268,7 +2321,7 @@ scanreadtable(Par par)
Set set2(tab, set.m_rows);
CHK(con.startTransaction() == 0);
CHK(con.getNdbScanOperation(tab) == 0);
- CHK(con.openScanRead(par.m_scanrd) == 0);
+ CHK(con.openScanRead(par.m_scanbat, par.m_scanpar) == 0);
set2.getval(par);
CHK(con.executeScan() == 0);
while (1) {
@@ -2296,7 +2349,7 @@ scanreadtablefast(Par par, unsigned countcheck)
LL3("scanfast " << tab.m_name);
CHK(con.startTransaction() == 0);
CHK(con.getNdbScanOperation(tab) == 0);
- CHK(con.openScanRead(par.m_scanrd) == 0);
+ CHK(con.openScanRead(par.m_scanbat, par.m_scanpar) == 0);
// get 1st column
NdbRecAttr* rec;
CHK(con.getValue((Uint32)0, rec) == 0);
@@ -2328,7 +2381,7 @@ scanreadindex(Par par, const ITab& itab, const BSet& bset)
Set set2(tab, set.m_rows);
CHK(con.startTransaction() == 0);
CHK(con.getNdbScanOperation(itab, tab) == 0);
- CHK(con.openScanRead(par.m_scanrd) == 0);
+ CHK(con.openScanRead(par.m_scanbat, par.m_scanpar) == 0);
CHK(bset.setbnd(par) == 0);
set2.getval(par);
CHK(con.executeScan() == 0);
@@ -2359,7 +2412,7 @@ scanreadindexfast(Par par, const ITab& itab, const BSet& bset, unsigned countche
LL4(bset);
CHK(con.startTransaction() == 0);
CHK(con.getNdbScanOperation(itab, tab) == 0);
- CHK(con.openScanRead(par.m_scanrd) == 0);
+ CHK(con.openScanRead(par.m_scanbat, par.m_scanpar) == 0);
CHK(bset.setbnd(par) == 0);
// get 1st column
NdbRecAttr* rec;
@@ -2382,7 +2435,7 @@ static int
scanreadindex(Par par, const ITab& itab)
{
const Tab& tab = par.tab();
- for (unsigned i = 0; i < par.m_idxloop; i++) {
+ for (unsigned i = 0; i < par.m_subsubloop; i++) {
BSet bset(tab, itab, par.m_rows);
bset.calc(par);
CHK(scanreadindex(par, itab, bset) == 0);
@@ -2478,7 +2531,7 @@ scanupdatetable(Par par)
Set set2(tab, set.m_rows);
CHK(con.startTransaction() == 0);
CHK(con.getNdbScanOperation(tab) == 0);
- CHK(con.openScanExclusive(par.m_scanex) == 0);
+ CHK(con.openScanExclusive(par.m_scanbat, par.m_scanpar) == 0);
set2.getval(par);
CHK(con.executeScan() == 0);
unsigned count = 0;
@@ -2498,6 +2551,10 @@ scanupdatetable(Par par)
LL1("scanupdatetable: stop on deadlock");
break;
}
+ if (par.m_scanstop != 0 && urandom(par.m_scanstop) == 0) {
+ con.closeScan();
+ break;
+ }
do {
unsigned i = (unsigned)-1;
CHK(set2.getkey(par, &i) == 0);
@@ -2557,7 +2614,7 @@ scanupdateindex(Par par, const ITab& itab, const BSet& bset)
Set set2(tab, set.m_rows);
CHK(con.startTransaction() == 0);
CHK(con.getNdbScanOperation(itab, tab) == 0);
- CHK(con.openScanExclusive(par.m_scanex) == 0);
+ CHK(con.openScanExclusive(par.m_scanbat, par.m_scanpar) == 0);
CHK(bset.setbnd(par) == 0);
set2.getval(par);
CHK(con.executeScan() == 0);
@@ -2578,6 +2635,10 @@ scanupdateindex(Par par, const ITab& itab, const BSet& bset)
LL1("scanupdateindex: stop on deadlock");
break;
}
+ if (par.m_scanstop != 0 && urandom(par.m_scanstop) == 0) {
+ con.closeScan();
+ break;
+ }
do {
unsigned i = (unsigned)-1;
CHK(set2.getkey(par, &i) == 0);
@@ -2629,7 +2690,7 @@ static int
scanupdateindex(Par par, const ITab& itab)
{
const Tab& tab = par.tab();
- for (unsigned i = 0; i < par.m_idxloop; i++) {
+ for (unsigned i = 0; i < par.m_subsubloop; i++) {
BSet bset(tab, itab, par.m_rows);
bset.calc(par);
CHK(scanupdateindex(par, itab, bset) == 0);
@@ -2663,6 +2724,8 @@ scanupdateall(Par par)
static int
readverify(Par par)
{
+ if (par.m_noverify)
+ return 0;
par.m_verify = true;
CHK(pkread(par) == 0);
CHK(scanreadall(par) == 0);
@@ -2670,6 +2733,55 @@ readverify(Par par)
}
static int
+readverifyfull(Par par)
+{
+ if (par.m_noverify)
+ return 0;
+ par.m_verify = true;
+ if (par.m_no == 0)
+ CHK(scanreadtable(par) == 0);
+ else {
+ const Tab& tab = par.tab();
+ unsigned i = par.m_no;
+ if (i <= tab.m_itabs && useindex(i)) {
+ const ITab& itab = tab.m_itab[i - 1];
+ BSet bset(tab, itab, par.m_rows);
+ CHK(scanreadindex(par, itab, bset) == 0);
+ }
+ }
+ return 0;
+}
+
+static int
+pkops(Par par)
+{
+ par.m_randomkey = true;
+ for (unsigned i = 0; i < par.m_subsubloop; i++) {
+ unsigned sel = urandom(10);
+ if (par.m_slno % 2 == 0) {
+ // favor insert
+ if (sel < 8) {
+ CHK(pkinsert(par) == 0);
+ } else if (sel < 9) {
+ CHK(pkupdate(par) == 0);
+ } else {
+ CHK(pkdelete(par) == 0);
+ }
+ } else {
+ // favor delete
+ if (sel < 1) {
+ CHK(pkinsert(par) == 0);
+ } else if (sel < 2) {
+ CHK(pkupdate(par) == 0);
+ } else {
+ CHK(pkdelete(par) == 0);
+ }
+ }
+ }
+ return 0;
+}
+
+static int
pkupdatescanread(Par par)
{
par.m_dups = true;
@@ -2691,6 +2803,7 @@ mixedoperations(Par par)
{
par.m_dups = true;
par.m_deadlock = true;
+ par.m_scanstop = par.m_totrows; // randomly close scans
unsigned sel = urandom(10);
if (sel < 2) {
CHK(pkdelete(par) == 0);
@@ -2710,6 +2823,7 @@ pkupdateindexbuild(Par par)
if (par.m_no == 0) {
CHK(createindex(par) == 0);
} else {
+ par.m_randomkey = true;
CHK(pkupdate(par) == 0);
}
return 0;
@@ -2913,6 +3027,8 @@ runstep(Par par, const char* fname, TFunc func, unsigned mode)
thr.m_par.m_tab = par.m_tab;
thr.m_par.m_set = par.m_set;
thr.m_par.m_tmr = par.m_tmr;
+ thr.m_par.m_lno = par.m_lno;
+ thr.m_par.m_slno = par.m_slno;
thr.m_func = func;
thr.start();
}
@@ -2936,8 +3052,8 @@ tbuild(Par par)
RUNSTEP(par, droptable, ST);
RUNSTEP(par, createtable, ST);
RUNSTEP(par, invalidatetable, MT);
- for (unsigned i = 0; i < par.m_subloop; i++) {
- if (i % 2 == 0) {
+ for (par.m_slno = 0; par.m_slno < par.m_subloop; par.m_slno++) {
+ if (par.m_slno % 2 == 0) {
RUNSTEP(par, createindex, ST);
RUNSTEP(par, invalidateindex, MT);
RUNSTEP(par, pkinsert, MT);
@@ -2946,9 +3062,10 @@ tbuild(Par par)
RUNSTEP(par, createindex, ST);
RUNSTEP(par, invalidateindex, MT);
}
- RUNSTEP(par, readverify, MT);
+ RUNSTEP(par, pkupdate, MT);
+ RUNSTEP(par, readverifyfull, MT);
RUNSTEP(par, pkdelete, MT);
- RUNSTEP(par, readverify, MT);
+ RUNSTEP(par, readverifyfull, MT);
RUNSTEP(par, dropindex, ST);
}
return 0;
@@ -2960,11 +3077,27 @@ tpkops(Par par)
RUNSTEP(par, droptable, ST);
RUNSTEP(par, createtable, ST);
RUNSTEP(par, invalidatetable, MT);
+ RUNSTEP(par, createindex, ST);
+ RUNSTEP(par, invalidateindex, MT);
+ for (par.m_slno = 0; par.m_slno < par.m_subloop; par.m_slno++) {
+ RUNSTEP(par, pkops, MT);
+ LL2("rows=" << par.set().count());
+ RUNSTEP(par, readverifyfull, MT);
+ }
+ return 0;
+}
+
+static int
+tpkopsread(Par par)
+{
+ RUNSTEP(par, droptable, ST);
+ RUNSTEP(par, createtable, ST);
+ RUNSTEP(par, invalidatetable, MT);
RUNSTEP(par, pkinsert, MT);
RUNSTEP(par, createindex, ST);
RUNSTEP(par, invalidateindex, MT);
RUNSTEP(par, readverify, ST);
- for (unsigned i = 0; i < par.m_subloop; i++) {
+ for (par.m_slno = 0; par.m_slno < par.m_subloop; par.m_slno++) {
RUNSTEP(par, pkupdatescanread, MT);
RUNSTEP(par, readverify, ST);
}
@@ -2983,7 +3116,7 @@ tmixedops(Par par)
RUNSTEP(par, createindex, ST);
RUNSTEP(par, invalidateindex, MT);
RUNSTEP(par, readverify, ST);
- for (unsigned i = 0; i < par.m_subloop; i++) {
+ for (par.m_slno = 0; par.m_slno < par.m_subloop; par.m_slno++) {
RUNSTEP(par, mixedoperations, MT);
RUNSTEP(par, readverify, ST);
}
@@ -2997,7 +3130,7 @@ tbusybuild(Par par)
RUNSTEP(par, createtable, ST);
RUNSTEP(par, invalidatetable, MT);
RUNSTEP(par, pkinsert, MT);
- for (unsigned i = 0; i < par.m_subloop; i++) {
+ for (par.m_slno = 0; par.m_slno < par.m_subloop; par.m_slno++) {
RUNSTEP(par, pkupdateindexbuild, MT);
RUNSTEP(par, invalidateindex, MT);
RUNSTEP(par, readverify, ST);
@@ -3013,7 +3146,7 @@ ttimebuild(Par par)
RUNSTEP(par, droptable, ST);
RUNSTEP(par, createtable, ST);
RUNSTEP(par, invalidatetable, MT);
- for (unsigned i = 0; i < par.m_subloop; i++) {
+ for (par.m_slno = 0; par.m_slno < par.m_subloop; par.m_slno++) {
RUNSTEP(par, pkinsert, MT);
t1.on();
RUNSTEP(par, createindex, ST);
@@ -3032,7 +3165,7 @@ ttimemaint(Par par)
RUNSTEP(par, droptable, ST);
RUNSTEP(par, createtable, ST);
RUNSTEP(par, invalidatetable, MT);
- for (unsigned i = 0; i < par.m_subloop; i++) {
+ for (par.m_slno = 0; par.m_slno < par.m_subloop; par.m_slno++) {
RUNSTEP(par, pkinsert, MT);
t1.on();
RUNSTEP(par, pkupdate, MT);
@@ -3057,7 +3190,7 @@ ttimescan(Par par)
RUNSTEP(par, droptable, ST);
RUNSTEP(par, createtable, ST);
RUNSTEP(par, invalidatetable, MT);
- for (unsigned i = 0; i < par.m_subloop; i++) {
+ for (par.m_slno = 0; par.m_slno < par.m_subloop; par.m_slno++) {
RUNSTEP(par, pkinsert, MT);
RUNSTEP(par, createindex, ST);
par.m_tmr = &t1;
@@ -3079,7 +3212,7 @@ ttimepkread(Par par)
RUNSTEP(par, droptable, ST);
RUNSTEP(par, createtable, ST);
RUNSTEP(par, invalidatetable, MT);
- for (unsigned i = 0; i < par.m_subloop; i++) {
+ for (par.m_slno = 0; par.m_slno < par.m_subloop; par.m_slno++) {
RUNSTEP(par, pkinsert, MT);
RUNSTEP(par, createindex, ST);
par.m_tmr = &t1;
@@ -3115,9 +3248,10 @@ struct TCase {
static const TCase
tcaselist[] = {
TCase("a", tbuild, "index build"),
- TCase("b", tpkops, "pk operations and scan reads"),
- TCase("c", tmixedops, "pk operations and scan operations"),
- TCase("d", tbusybuild, "pk operations and index build"),
+ TCase("b", tpkops, "pk operations"),
+ TCase("c", tpkopsread, "pk operations and scan reads"),
+ TCase("d", tmixedops, "pk operations and scan operations"),
+ TCase("e", tbusybuild, "pk operations and index build"),
TCase("t", ttimebuild, "time index build"),
TCase("u", ttimemaint, "time index maintenance"),
TCase("v", ttimescan, "time full scan table vs index on pk"),
@@ -3175,10 +3309,10 @@ runtest(Par par)
Thr& thr = *g_thrlist[n];
assert(thr.m_thread != 0);
}
- for (unsigned l = 0; par.m_loop == 0 || l < par.m_loop; l++) {
- LL1("loop " << l);
+ for (par.m_lno = 0; par.m_loop == 0 || par.m_lno < par.m_loop; par.m_lno++) {
+ LL1("loop " << par.m_lno);
if (par.m_seed == 0)
- srandom(l);
+ srandom(par.m_lno);
for (unsigned i = 0; i < tcasecount; i++) {
const TCase& tcase = tcaselist[i];
if (par.m_case != 0 && strchr(par.m_case, tcase.m_name[0]) == 0)
@@ -3252,6 +3386,12 @@ NDB_COMMAND(testOIBasic, "testOIBasic", "testOIBasic", "testOIBasic", 65535)
continue;
}
}
+ if (strcmp(arg, "-die") == 0) {
+ if (++argv, --argc > 0) {
+ g_opt.m_die = atoi(argv[0]);
+ continue;
+ }
+ }
if (strcmp(arg, "-dups") == 0) {
g_opt.m_dups = true;
continue;
@@ -3292,6 +3432,10 @@ NDB_COMMAND(testOIBasic, "testOIBasic", "testOIBasic", "testOIBasic", 65535)
g_opt.m_nologging = true;
continue;
}
+ if (strcmp(arg, "-noverify") == 0) {
+ g_opt.m_noverify = true;
+ continue;
+ }
if (strcmp(arg, "-pctnull") == 0) {
if (++argv, --argc > 0) {
g_opt.m_pctnull = atoi(argv[0]);
@@ -3310,15 +3454,15 @@ NDB_COMMAND(testOIBasic, "testOIBasic", "testOIBasic", "testOIBasic", 65535)
continue;
}
}
- if (strcmp(arg, "-scanrd") == 0) {
+ if (strcmp(arg, "-scanbat") == 0) {
if (++argv, --argc > 0) {
- g_opt.m_scanrd = atoi(argv[0]);
+ g_opt.m_scanbat = atoi(argv[0]);
continue;
}
}
- if (strcmp(arg, "-scanex") == 0) {
+ if (strcmp(arg, "-scanpar") == 0) {
if (++argv, --argc > 0) {
- g_opt.m_scanex = atoi(argv[0]);
+ g_opt.m_scanpar = atoi(argv[0]);
continue;
}
}
diff --git a/ndb/test/ndbapi/testOperations.cpp b/ndb/test/ndbapi/testOperations.cpp
index ba41e1d1c40..f31906dd737 100644
--- a/ndb/test/ndbapi/testOperations.cpp
+++ b/ndb/test/ndbapi/testOperations.cpp
@@ -86,7 +86,7 @@ OperationTestCase matrix[] = {
{ "DeleteRead", true, "DELETE", 0, 0, "READ", 626, 0, 0, 0 },
{ "DeleteReadEx", true, "DELETE", 0, 0, "READ-EX", 626, 0, 0, 0 },
{ "DeleteSimpleRead", true, "DELETE", 0, 0, "S-READ", 626, 0, 0, 0 },
- { "DeleteDirtyRead", true, "DELETE", 0, 0, "D-READ", 626, 0, 0, 0 },
+ { "DeleteDirtyRead", true, "DELETE", 0, 0, "D-READ", 626, 0, 626, 0 },
{ "DeleteInsert", true, "DELETE", 0, 0, "INSERT", 0, 1, 0, 1 },
{ "DeleteUpdate", true, "DELETE", 0, 0, "UPDATE", 626, 1, 0, 0 },
{ "DeleteDelete", true, "DELETE", 0, 0, "DELETE", 626, 0, 0, 0 }
@@ -110,13 +110,13 @@ runOp(HugoOperations & hugoOps,
return NDBT_FAILED; }}
if(strcmp(op, "READ") == 0){
- C2(hugoOps.pkReadRecord(pNdb, 1, false, 1), 0);
+ C2(hugoOps.pkReadRecord(pNdb, 1, 1, NdbOperation::LM_Read), 0);
} else if(strcmp(op, "READ-EX") == 0){
- C2(hugoOps.pkReadRecord(pNdb, 1, true, 1), 0);
+ C2(hugoOps.pkReadRecord(pNdb, 1, 1, NdbOperation::LM_Exclusive), 0);
} else if(strcmp(op, "S-READ") == 0){
- C2(hugoOps.pkSimpleReadRecord(pNdb, 1, 1), 0);
+ C2(hugoOps.pkReadRecord(pNdb, 1, 1, NdbOperation::LM_Read), 0);
} else if(strcmp(op, "D-READ") == 0){
- C2(hugoOps.pkDirtyReadRecord(pNdb, 1, 1), 0);
+ C2(hugoOps.pkReadRecord(pNdb, 1, 1, NdbOperation::LM_CommittedRead), 0);
} else if(strcmp(op, "INSERT") == 0){
C2(hugoOps.pkInsertRecord(pNdb, 1, 1, value), 0);
} else if(strcmp(op, "UPDATE") == 0){
diff --git a/ndb/test/ndbapi/testReadPerf.cpp b/ndb/test/ndbapi/testReadPerf.cpp
index 7cf3755d66f..8d0d78cbe8c 100644
--- a/ndb/test/ndbapi/testReadPerf.cpp
+++ b/ndb/test/ndbapi/testReadPerf.cpp
@@ -130,9 +130,9 @@ main(int argc, const char** argv){
for(int i = optind; i<argc; i++){
const char * T = argv[i];
g_info << "Testing " << T << endl;
- snprintf(g_table, sizeof(g_table), T);
- snprintf(g_ordered, sizeof(g_ordered), "IDX_O_%s", T);
- snprintf(g_unique, sizeof(g_unique), "IDX_U_%s", T);
+ BaseString::snprintf(g_table, sizeof(g_table), T);
+ BaseString::snprintf(g_ordered, sizeof(g_ordered), "IDX_O_%s", T);
+ BaseString::snprintf(g_unique, sizeof(g_unique), "IDX_U_%s", T);
if(create_table())
goto error;
if(load_table())
diff --git a/ndb/test/ndbapi/testRestartGci.cpp b/ndb/test/ndbapi/testRestartGci.cpp
index 4cdfca29e6f..e817245af55 100644
--- a/ndb/test/ndbapi/testRestartGci.cpp
+++ b/ndb/test/ndbapi/testRestartGci.cpp
@@ -63,7 +63,7 @@ int runInsertRememberGci(NDBT_Context* ctx, NDBT_Step* step){
result = NDBT_FAILED;
break;
}
- CHECK(hugoOps.pkReadRecord(pNdb, i, false) == 0);
+ CHECK(hugoOps.pkReadRecord(pNdb, i) == 0);
if (hugoOps.execute_Commit(pNdb) != 0){
ndbout << "Did not find record in DB " << i << endl;
result = NDBT_FAILED;
@@ -146,7 +146,7 @@ int runVerifyInserts(NDBT_Context* ctx, NDBT_Step* step){
// gci as in the vector
for (unsigned i = 0; i < savedRecords.size(); i++){
CHECK(hugoOps.startTransaction(pNdb) == 0);
- CHECK(hugoOps.pkReadRecord(pNdb, i, false) == 0);
+ CHECK(hugoOps.pkReadRecord(pNdb, i) == 0);
if (hugoOps.execute_Commit(pNdb) != 0){
// Record was not found in db'
diff --git a/ndb/test/ndbapi/testScanInterpreter.cpp b/ndb/test/ndbapi/testScanInterpreter.cpp
index 3a5ef22b613..5a7ca30cd2a 100644
--- a/ndb/test/ndbapi/testScanInterpreter.cpp
+++ b/ndb/test/ndbapi/testScanInterpreter.cpp
@@ -90,7 +90,7 @@ int runCreateResultTable(NDBT_Context* ctx, NDBT_Step* step){
const NdbDictionary::Table* pTab = ctx->getTab();
char newTabName[256];
- snprintf(newTabName, 256, "%s_RES", pTab->getName());
+ BaseString::snprintf(newTabName, 256, "%s_RES", pTab->getName());
ctx->setProperty("ResultTabName", newTabName);
NdbDictionary::Table resTab(* pTab);
diff --git a/ndb/test/ndbapi/testScanPerf.cpp b/ndb/test/ndbapi/testScanPerf.cpp
index 8c1a41047ca..c1334125978 100644
--- a/ndb/test/ndbapi/testScanPerf.cpp
+++ b/ndb/test/ndbapi/testScanPerf.cpp
@@ -110,8 +110,8 @@ main(int argc, const char** argv){
for(int i = optind; i<argc; i++){
const char * T = argv[i];
g_info << "Testing " << T << endl;
- snprintf(g_tablename, sizeof(g_tablename), T);
- snprintf(g_indexname, sizeof(g_indexname), "IDX_%s", T);
+ BaseString::snprintf(g_tablename, sizeof(g_tablename), T);
+ BaseString::snprintf(g_indexname, sizeof(g_indexname), "IDX_%s", T);
if(create_table())
goto error;
if(load_table())
diff --git a/ndb/test/ndbapi/testTimeout.cpp b/ndb/test/ndbapi/testTimeout.cpp
index 5cabb86541d..e310e12df81 100644
--- a/ndb/test/ndbapi/testTimeout.cpp
+++ b/ndb/test/ndbapi/testTimeout.cpp
@@ -108,7 +108,7 @@ int runTimeoutTrans(NDBT_Context* ctx, NDBT_Step* step){
do{
// Commit transaction
CHECK(hugoOps.startTransaction(pNdb) == 0);
- CHECK(hugoOps.pkReadRecord(pNdb, stepNo, true) == 0);
+ CHECK(hugoOps.pkReadRecord(pNdb, stepNo) == 0);
CHECK(hugoOps.execute_NoCommit(pNdb) == 0);
int sleep = minSleep + myRandom48(maxSleep-minSleep);
@@ -162,25 +162,25 @@ int runTimeoutTrans2(NDBT_Context* ctx, NDBT_Step* step){
case 0:
break;
case 1:
- if(hugoOps.pkReadRecord(pNdb, stepNo, true) != 0){
+ if(hugoOps.pkReadRecord(pNdb, stepNo) != 0){
g_err << stepNo << ": Fail" << __LINE__ << endl;
result = NDBT_FAILED; break;
}
break;
case 2:
- if(hugoOps.pkUpdateRecord(pNdb, stepNo, true) != 0){
+ if(hugoOps.pkUpdateRecord(pNdb, stepNo) != 0){
g_err << stepNo << ": Fail" << __LINE__ << endl;
result = NDBT_FAILED; break;
}
break;
case 3:
- if(hugoOps.pkDeleteRecord(pNdb, stepNo, true) != 0){
+ if(hugoOps.pkDeleteRecord(pNdb, stepNo) != 0){
g_err << stepNo << ": Fail" << __LINE__ << endl;
result = NDBT_FAILED; break;
}
break;
case 4:
- if(hugoOps.pkInsertRecord(pNdb, stepNo+records+l, true) != 0){
+ if(hugoOps.pkInsertRecord(pNdb, stepNo+records+l) != 0){
g_err << stepNo << ": Fail" << __LINE__ << endl;
result = NDBT_FAILED; break;
}
@@ -204,25 +204,25 @@ int runTimeoutTrans2(NDBT_Context* ctx, NDBT_Step* step){
case 0:
break;
case 1:
- if(hugoOps.pkReadRecord(pNdb, stepNo, true) != 0){
+ if(hugoOps.pkReadRecord(pNdb, stepNo) != 0){
g_err << stepNo << ": Fail" << __LINE__ << endl;
result = NDBT_FAILED; break;
}
break;
case 2:
- if(hugoOps.pkUpdateRecord(pNdb, stepNo, true) != 0){
+ if(hugoOps.pkUpdateRecord(pNdb, stepNo) != 0){
g_err << stepNo << ": Fail" << __LINE__ << endl;
result = NDBT_FAILED; break;
}
break;
case 3:
- if(hugoOps.pkDeleteRecord(pNdb, stepNo, true) != 0){
+ if(hugoOps.pkDeleteRecord(pNdb, stepNo) != 0){
g_err << stepNo << ": Fail" << __LINE__ << endl;
result = NDBT_FAILED; break;
}
break;
case 4:
- if(hugoOps.pkInsertRecord(pNdb, stepNo+2*records+l, true) != 0){
+ if(hugoOps.pkInsertRecord(pNdb, stepNo+2*records+l) != 0){
g_err << stepNo << ": Fail" << __LINE__ << endl;
result = NDBT_FAILED; break;
}
@@ -263,7 +263,7 @@ int runDontTimeoutTrans(NDBT_Context* ctx, NDBT_Step* step){
do{
// Commit transaction
CHECK(hugoOps.startTransaction(pNdb) == 0);
- CHECK(hugoOps.pkReadRecord(pNdb, stepNo, true) == 0);
+ CHECK(hugoOps.pkReadRecord(pNdb, stepNo) == 0);
CHECK(hugoOps.execute_NoCommit(pNdb) == 0);
int sleep = myRandom48(maxSleep);
@@ -299,7 +299,7 @@ int runBuddyTransNoTimeout(NDBT_Context* ctx, NDBT_Step* step){
// Start an insert trans
CHECK(hugoOps.startTransaction(pNdb) == 0);
int recordNo = records + (stepNo*loops) + l;
- CHECK(hugoOps.pkInsertRecord(pNdb, recordNo, true) == 0);
+ CHECK(hugoOps.pkInsertRecord(pNdb, recordNo) == 0);
CHECK(hugoOps.execute_NoCommit(pNdb) == 0);
for (int i = 0; i < 3; i++){
diff --git a/ndb/test/ndbapi/testTransactions.cpp b/ndb/test/ndbapi/testTransactions.cpp
index 2dca9e24fb4..46be808d8a5 100644
--- a/ndb/test/ndbapi/testTransactions.cpp
+++ b/ndb/test/ndbapi/testTransactions.cpp
@@ -190,13 +190,13 @@ runOp(HugoOperations & hugoOps,
return NDBT_FAILED; }
if(strcmp(op, "READ") == 0){
- C2(hugoOps.pkReadRecord(pNdb, 1, false, 1) == 0);
+ C2(hugoOps.pkReadRecord(pNdb, 1, 1, NdbOperation::LM_Read) == 0);
} else if(strcmp(op, "READ-EX") == 0){
- C2(hugoOps.pkReadRecord(pNdb, 1, true, 1) == 0);
+ C2(hugoOps.pkReadRecord(pNdb, 1, 1, NdbOperation::LM_Exclusive) == 0);
} else if(strcmp(op, "S-READ") == 0){
- C2(hugoOps.pkSimpleReadRecord(pNdb, 1, 1) == 0);
+ C2(hugoOps.pkReadRecord(pNdb, 1, 1, NdbOperation::LM_Read) == 0);
} else if(strcmp(op, "D-READ") == 0){
- C2(hugoOps.pkDirtyReadRecord(pNdb, 1, 1) == 0);
+ C2(hugoOps.pkReadRecord(pNdb, 1, 1, NdbOperation::LM_CommittedRead) == 0);
} else if(strcmp(op, "INSERT") == 0){
C2(hugoOps.pkInsertRecord(pNdb, 1, 1, value) == 0);
} else if(strcmp(op, "UPDATE") == 0){
diff --git a/ndb/test/ndbapi/userInterface.cpp b/ndb/test/ndbapi/userInterface.cpp
index fdbc229cc98..2f77c0f4857 100644
--- a/ndb/test/ndbapi/userInterface.cpp
+++ b/ndb/test/ndbapi/userInterface.cpp
@@ -103,7 +103,7 @@ void showTime()
now = ::time((time_t*)NULL);
tm_now = ::gmtime(&now);
- ::snprintf(buf, 128,
+ BaseString::snprintf(buf, 128,
"%d-%.2d-%.2d %.2d:%.2d:%.2d",
tm_now->tm_year + 1900,
tm_now->tm_mon,
diff --git a/ndb/test/run-test/daily-devel-tests.txt b/ndb/test/run-test/daily-devel-tests.txt
index f2abc961807..5c0b2821d85 100644
--- a/ndb/test/run-test/daily-devel-tests.txt
+++ b/ndb/test/run-test/daily-devel-tests.txt
@@ -52,26 +52,30 @@ args: -n SR4 T6
#
max-time: 1500
cmd: testSystemRestart
-args: -n SR_FULLDB T1
+args: -n SR_FULLDB T6
#
# NODE RESTARTS
#
max-time: 2500
cmd: testNodeRestart
-args: -n NoLoad T6 T8 T13
+args: -n NoLoad T6
max-time: 2500
cmd: testNodeRestart
-args: -n PkRead T6 T8 T13
+args: -n MixedPkRead T6 T8 T13
max-time: 2500
cmd: testNodeRestart
-args: -l 1 -n PkReadPkUpdate
+args: -l 1 -n MixedPkReadPkUpdate
max-time: 2500
cmd: testNodeRestart
-args: -l 1 -n ReadUpdateScan
+args: -l 1 -n MixedReadUpdateScan
+
+max-time: 2500
+cmd: testNodeRestart
+args: -n CommittedRead T1
max-time: 2500
cmd: testNodeRestart
@@ -186,10 +190,6 @@ max-time: 2500
cmd: testDict
args: -n NF1 T1 T6 T13
-max-time: 2500
-cmd: test_event
-args: -n BasicEventOperation T1 T6
-
#
max-time: 1500
cmd: testSystemRestart
@@ -206,3 +206,9 @@ args: -l 1 -n SR8 T1
max-time: 1500
cmd: testSystemRestart
args: -l 1 -n SR9 T1
+
+#
+max-time: 2500
+cmd: test_event
+args: -n BasicEventOperation T1 T6
+
diff --git a/ndb/test/src/HugoCalculator.cpp b/ndb/test/src/HugoCalculator.cpp
index 147c8b104d8..62c35c54a7a 100644
--- a/ndb/test/src/HugoCalculator.cpp
+++ b/ndb/test/src/HugoCalculator.cpp
@@ -96,7 +96,7 @@ HugoCalculator::calcValue(int record,
// of the string, then fill with other chars
// The string length is set to the same size as the attribute
len = attr->getLength();
- snprintf(buf, len, "%d", val);
+ BaseString::snprintf(buf, len, "%d", val);
for(int i=strlen(buf); i < len; i++)
buf[i] = a[((val^i)%25)];
} else{
diff --git a/ndb/test/src/HugoOperations.cpp b/ndb/test/src/HugoOperations.cpp
index 7c05cb86a93..e8e2d992345 100644
--- a/ndb/test/src/HugoOperations.cpp
+++ b/ndb/test/src/HugoOperations.cpp
@@ -52,8 +52,8 @@ NdbConnection* HugoOperations::getTransaction(){
int HugoOperations::pkReadRecord(Ndb* pNdb,
int recordNo,
- bool exclusive,
- int numRecords){
+ int numRecords,
+ NdbOperation::LockMode lm){
int a;
allocRows(numRecords);
int check;
@@ -64,94 +64,22 @@ int HugoOperations::pkReadRecord(Ndb* pNdb,
return NDBT_FAILED;
}
- if (exclusive == true)
- check = pOp->readTupleExclusive();
- else
+rand_lock_mode:
+ switch(lm){
+ case NdbOperation::LM_Read:
check = pOp->readTuple();
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- return NDBT_FAILED;
- }
-
- // Define primary keys
- for(a = 0; a<tab.getNoOfColumns(); a++){
- if (tab.getColumn(a)->getPrimaryKey() == true){
- if(equalForAttr(pOp, a, r+recordNo) != 0){
- ERR(pTrans->getNdbError());
- return NDBT_FAILED;
- }
- }
- }
-
- // Define attributes to read
- for(a = 0; a<tab.getNoOfColumns(); a++){
- if((rows[r]->attributeStore(a) =
- pOp->getValue(tab.getColumn(a)->getName())) == 0) {
- ERR(pTrans->getNdbError());
- return NDBT_FAILED;
- }
- }
- }
- return NDBT_OK;
-}
-
-int HugoOperations::pkDirtyReadRecord(Ndb* pNdb,
- int recordNo,
- int numRecords){
- int a;
- allocRows(numRecords);
- int check;
- for(int r=0; r < numRecords; r++){
- NdbOperation* pOp = pTrans->getNdbOperation(tab.getName());
- if (pOp == NULL) {
- ERR(pTrans->getNdbError());
- return NDBT_FAILED;
- }
-
- check = pOp->dirtyRead();
-
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- return NDBT_FAILED;
- }
-
- // Define primary keys
- for(a = 0; a<tab.getNoOfColumns(); a++){
- if (tab.getColumn(a)->getPrimaryKey() == true){
- if(equalForAttr(pOp, a, r+recordNo) != 0){
- ERR(pTrans->getNdbError());
- return NDBT_FAILED;
- }
- }
- }
-
- // Define attributes to read
- for(a = 0; a<tab.getNoOfColumns(); a++){
- if((rows[r]->attributeStore(a) =
- pOp->getValue(tab.getColumn(a)->getName())) == 0) {
- ERR(pTrans->getNdbError());
- return NDBT_FAILED;
- }
- }
- }
- return NDBT_OK;
-}
-
-int HugoOperations::pkSimpleReadRecord(Ndb* pNdb,
- int recordNo,
- int numRecords){
- int a;
- allocRows(numRecords);
- int check;
- for(int r=0; r < numRecords; r++){
- NdbOperation* pOp = pTrans->getNdbOperation(tab.getName());
- if (pOp == NULL) {
- ERR(pTrans->getNdbError());
- return NDBT_FAILED;
+ break;
+ case NdbOperation::LM_Exclusive:
+ check = pOp->readTupleExclusive();
+ break;
+ case NdbOperation::LM_CommittedRead:
+ check = pOp->dirtyRead();
+ break;
+ default:
+ lm = (NdbOperation::LockMode)((rand() >> 16) & 3);
+ goto rand_lock_mode;
}
- check = pOp->simpleRead();
-
if( check == -1 ) {
ERR(pTrans->getNdbError());
return NDBT_FAILED;
diff --git a/ndb/test/src/HugoTransactions.cpp b/ndb/test/src/HugoTransactions.cpp
index 994a45de3dc..456bfffbb77 100644
--- a/ndb/test/src/HugoTransactions.cpp
+++ b/ndb/test/src/HugoTransactions.cpp
@@ -1230,7 +1230,7 @@ int
HugoTransactions::pkReadRecords(Ndb* pNdb,
int records,
int batchsize,
- bool dirty){
+ NdbOperation::LockMode lm){
int reads = 0;
int r = 0;
int retryAttempt = 0;
@@ -1275,11 +1275,22 @@ HugoTransactions::pkReadRecords(Ndb* pNdb,
return NDBT_FAILED;
}
- if (dirty == true){
- check = pOp->dirtyRead();
- } else {
+ rand_lock_mode:
+ switch(lm){
+ case NdbOperation::LM_Read:
check = pOp->readTuple();
+ break;
+ case NdbOperation::LM_Exclusive:
+ check = pOp->readTupleExclusive();
+ break;
+ case NdbOperation::LM_CommittedRead:
+ check = pOp->dirtyRead();
+ break;
+ default:
+ lm = (NdbOperation::LockMode)((rand() >> 16) & 3);
+ goto rand_lock_mode;
}
+
if( check == -1 ) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
diff --git a/ndb/test/src/NDBT_ResultRow.cpp b/ndb/test/src/NDBT_ResultRow.cpp
index 7c419444760..f82963901b1 100644
--- a/ndb/test/src/NDBT_ResultRow.cpp
+++ b/ndb/test/src/NDBT_ResultRow.cpp
@@ -58,10 +58,14 @@ NDBT_ResultRow::attributeStore(int i){
return data[i];
}
+const NdbRecAttr*
+NDBT_ResultRow::attributeStore(int i) const {
+ return data[i];
+}
const
NdbRecAttr *
-NDBT_ResultRow::attributeStore(const char* name){
+NDBT_ResultRow::attributeStore(const char* name) const {
for(int i = 0; i<cols; i++){
if (strcmp(names[i], name) == 0)
return data[i];
diff --git a/ndb/test/src/NDBT_Table.cpp b/ndb/test/src/NDBT_Table.cpp
index d283cdf5912..8d398b75d81 100644
--- a/ndb/test/src/NDBT_Table.cpp
+++ b/ndb/test/src/NDBT_Table.cpp
@@ -24,7 +24,7 @@ operator <<(class NdbOut& ndbout, const NDBT_Table & tab)
ndbout << "-- " << tab.getName() << " --" << endl;
ndbout << "Version: " << tab.getObjectVersion() << endl;
- ndbout << "Fragment type: " << tab.getFragmentType() << endl;
+ ndbout << "Fragment type: " << (unsigned) tab.getFragmentType() << endl;
ndbout << "K Value: " << tab.getKValue()<< endl;
ndbout << "Min load factor: " << tab.getMinLoadFactor()<< endl;
ndbout << "Max load factor: " << tab.getMaxLoadFactor()<< endl;
@@ -47,7 +47,7 @@ operator <<(class NdbOut& ndbout, const NDBT_Table & tab)
ndbout << "Retrieved" << endl;
break;
default:
- ndbout << "Unknown(" << tab.getObjectStatus() << ")" << endl;
+ ndbout << "Unknown(" << (unsigned) tab.getObjectStatus() << ")" << endl;
}
ndbout << "-- Attributes -- " << endl;
@@ -81,7 +81,7 @@ class NdbOut& operator <<(class NdbOut&, const NdbDictionary::Index & idx)
ndbout << "OrderedIndex";
break;
default:
- ndbout << "Type " << idx.getType();
+ ndbout << "Type " << (unsigned) idx.getType();
break;
}
return ndbout;
diff --git a/ndb/test/src/NDBT_Test.cpp b/ndb/test/src/NDBT_Test.cpp
index 4ff94bcf296..367223f8c98 100644
--- a/ndb/test/src/NDBT_Test.cpp
+++ b/ndb/test/src/NDBT_Test.cpp
@@ -484,7 +484,7 @@ void NDBT_TestCaseImpl1::startStepInThread(int stepNo, NDBT_Context* ctx){
NDBT_Step* pStep = steps[stepNo];
pStep->setContext(ctx);
char buf[16];
- snprintf(buf, sizeof(buf), "step_%d", stepNo);
+ BaseString::snprintf(buf, sizeof(buf), "step_%d", stepNo);
NdbThread* pThread = NdbThread_Create(runStep_C,
(void**)pStep,
65535,
@@ -704,7 +704,7 @@ void NDBT_TestCaseImpl1::printTestResult(){
res = "FAILED TO CREATE TABLE";
else if (tcr->getResult() == FAILED_TO_DISCOVER)
res = "FAILED TO DISCOVER TABLE";
- snprintf(buf, 255," %-10s %-5s %-20s", tcr->getName(), res, tcr->getTimeStr());
+ BaseString::snprintf(buf, 255," %-10s %-5s %-20s", tcr->getName(), res, tcr->getTimeStr());
ndbout << buf<<endl;
}
}
@@ -1078,7 +1078,7 @@ const char* NDBT_TestSuite::getDate(){
tm_now = gmtime(&now);
#endif
- snprintf(theTime, 128,
+ BaseString::snprintf(theTime, 128,
"%d-%.2d-%.2d %.2d:%.2d:%.2d",
tm_now->tm_year + 1900,
tm_now->tm_mon + 1,
@@ -1150,6 +1150,20 @@ void NDBT_Step::print(){
}
+void
+NDBT_Context::sync_down(const char * key){
+ Uint32 threads = getProperty(key, (unsigned)0);
+ if(threads){
+ decProperty(key);
+ }
+}
+
+void
+NDBT_Context::sync_up_and_wait(const char * key, Uint32 value){
+ setProperty(key, value);
+ getPropertyWait(key, (unsigned)0);
+}
+
template class Vector<NDBT_TestCase*>;
template class Vector<NDBT_TestCaseResult*>;
template class Vector<NDBT_Step*>;
diff --git a/ndb/test/src/NdbBackup.cpp b/ndb/test/src/NdbBackup.cpp
index ad26dbeab16..1ce48d495a5 100644
--- a/ndb/test/src/NdbBackup.cpp
+++ b/ndb/test/src/NdbBackup.cpp
@@ -143,7 +143,7 @@ NdbBackup::execRestore(bool _restore_data,
* Copy backup files to local dir
*/
- snprintf(buf, buf_len,
+ BaseString::snprintf(buf, buf_len,
"scp %s:%s/BACKUP/BACKUP-%d/BACKUP-%d*.%d.* .",
host, path,
_backup_id,
@@ -155,7 +155,7 @@ NdbBackup::execRestore(bool _restore_data,
ndbout << "scp res: " << res << endl;
- snprintf(buf, 255, "%sndb_restore -c \"host=%s\" -n %d -b %d %s %s .",
+ BaseString::snprintf(buf, 255, "%sndb_restore -c \"host=%s\" -n %d -b %d %s %s .",
#if 1
"",
#else
diff --git a/ndb/test/src/NdbGrep.cpp b/ndb/test/src/NdbGrep.cpp
index 8b7442b0e77..6c0c9cabfcb 100644
--- a/ndb/test/src/NdbGrep.cpp
+++ b/ndb/test/src/NdbGrep.cpp
@@ -60,10 +60,10 @@ NdbGrep::verify(NDBT_Context * ctx){
return -1;
char cheat_table[255];
- snprintf(cheat_table, 255, "TEST_DB/def/%s",ctx->getTab()->getName());
+ BaseString::snprintf(cheat_table, 255, "TEST_DB/def/%s",ctx->getTab()->getName());
char buf[255];
- snprintf(buf, 255, "testGrepVerify -c \"nodeid=%d;host=%s\" -t %s -r %d",
+ BaseString::snprintf(buf, 255, "testGrepVerify -c \"nodeid=%d;host=%s\" -t %s -r %d",
4, //cheat. Hardcoded nodeid....
ctx->getRemoteMgm(),
cheat_table,
diff --git a/ndb/test/src/UtilTransactions.cpp b/ndb/test/src/UtilTransactions.cpp
index 506356dd140..c0e6effd244 100644
--- a/ndb/test/src/UtilTransactions.cpp
+++ b/ndb/test/src/UtilTransactions.cpp
@@ -383,11 +383,20 @@ UtilTransactions::clearTable3(Ndb* pNdb,
pOp = pTrans->getNdbScanOperation(tab.getName());
if (pOp == NULL) {
+ err = pTrans->getNdbError();
+ if(err.status == NdbError::TemporaryError){
+ ERR(err);
+ pNdb->closeTransaction(pTrans);
+ NdbSleep_MilliSleep(50);
+ par = 1;
+ goto restart;
+ }
goto failed;
}
NdbResultSet * rs = pOp->readTuplesExclusive(par);
if( rs == 0 ) {
+ err = pTrans->getNdbError();
goto failed;
}
@@ -647,8 +656,16 @@ UtilTransactions::scanReadRecords(Ndb* pNdb,
pOp = pTrans->getNdbScanOperation(tab.getName());
if (pOp == NULL) {
- ERR(pTrans->getNdbError());
+ const NdbError err = pNdb->getNdbError();
pNdb->closeTransaction(pTrans);
+
+ if (err.status == NdbError::TemporaryError){
+ ERR(err);
+ NdbSleep_MilliSleep(50);
+ retryAttempt++;
+ continue;
+ }
+ ERR(err);
return NDBT_FAILED;
}
@@ -854,11 +871,12 @@ UtilTransactions::verifyIndex(Ndb* pNdb,
ndbout << " Index " << indexName << " does not exist!" << endl;
return NDBT_FAILED;
}
-
+
switch (pIndex->getType()){
case NdbDictionary::Index::UniqueHashIndex:
+ return verifyUniqueIndex(pNdb, pIndex, parallelism, transactional);
case NdbDictionary::Index::OrderedIndex:
- return verifyUniqueIndex(pNdb, indexName, parallelism, transactional);
+ return verifyOrderedIndex(pNdb, pIndex, parallelism, transactional);
break;
default:
ndbout << "Unknown index type" << endl;
@@ -870,7 +888,7 @@ UtilTransactions::verifyIndex(Ndb* pNdb,
int
UtilTransactions::verifyUniqueIndex(Ndb* pNdb,
- const char* indexName,
+ const NdbDictionary::Index * pIndex,
int parallelism,
bool transactional){
@@ -882,7 +900,7 @@ UtilTransactions::verifyUniqueIndex(Ndb* pNdb,
*/
if (scanAndCompareUniqueIndex(pNdb,
- indexName,
+ pIndex,
parallelism,
transactional) != NDBT_OK){
return NDBT_FAILED;
@@ -896,7 +914,7 @@ UtilTransactions::verifyUniqueIndex(Ndb* pNdb,
int
UtilTransactions::scanAndCompareUniqueIndex(Ndb* pNdb,
- const char * indexName,
+ const NdbDictionary::Index* pIndex,
int parallelism,
bool transactional){
@@ -933,8 +951,15 @@ UtilTransactions::scanAndCompareUniqueIndex(Ndb* pNdb,
pOp = pTrans->getNdbScanOperation(tab.getName());
if (pOp == NULL) {
- ERR(pTrans->getNdbError());
+ const NdbError err = pNdb->getNdbError();
pNdb->closeTransaction(pTrans);
+ ERR(err);
+
+ if (err.status == NdbError::TemporaryError){
+ NdbSleep_MilliSleep(50);
+ retryAttempt++;
+ continue;
+ }
return NDBT_FAILED;
}
@@ -996,7 +1021,7 @@ UtilTransactions::scanAndCompareUniqueIndex(Ndb* pNdb,
if (readRowFromTableAndIndex(pNdb,
pTrans,
- indexName,
+ pIndex,
row) != NDBT_OK){
pNdb->closeTransaction(pTrans);
return NDBT_FAILED;
@@ -1027,15 +1052,9 @@ UtilTransactions::scanAndCompareUniqueIndex(Ndb* pNdb,
int
UtilTransactions::readRowFromTableAndIndex(Ndb* pNdb,
NdbConnection* scanTrans,
- const char * indexName,
+ const NdbDictionary::Index* pIndex,
NDBT_ResultRow& row ){
- const NdbDictionary::Index* pIndex
- = pNdb->getDictionary()->getIndex(indexName, tab.getName());
- if (pIndex == 0){
- ndbout << " Index " << indexName << " does not exist!" << endl;
- return NDBT_FAILED;
- }
NdbDictionary::Index::Type indexType= pIndex->getType();
int retryAttempt = 0;
@@ -1050,7 +1069,7 @@ UtilTransactions::readRowFromTableAndIndex(Ndb* pNdb,
// Allocate place to store the result
NDBT_ResultRow tabRow(tab);
NDBT_ResultRow indexRow(tab);
-
+ const char * indexName = pIndex->getName();
while (true){
if(retryAttempt)
@@ -1281,3 +1300,239 @@ close_all:
return return_code;
}
+
+int
+UtilTransactions::verifyOrderedIndex(Ndb* pNdb,
+ const NdbDictionary::Index* pIndex,
+ int parallelism,
+ bool transactional){
+
+ int retryAttempt = 0;
+ const int retryMax = 100;
+ int check;
+ NdbConnection *pTrans;
+ NdbScanOperation *pOp;
+ NdbIndexScanOperation * iop = 0;
+ NdbResultSet* cursor= 0;
+
+ NDBT_ResultRow scanRow(tab);
+ NDBT_ResultRow pkRow(tab);
+ NDBT_ResultRow indexRow(tab);
+ const char * indexName = pIndex->getName();
+
+ int res;
+ parallelism = 1;
+
+ while (true){
+
+ if (retryAttempt >= retryMax){
+ g_info << "ERROR: has retried this operation " << retryAttempt
+ << " times, failing!" << endl;
+ return NDBT_FAILED;
+ }
+
+ pTrans = pNdb->startTransaction();
+ if (pTrans == NULL) {
+ const NdbError err = pNdb->getNdbError();
+
+ if (err.status == NdbError::TemporaryError){
+ ERR(err);
+ NdbSleep_MilliSleep(50);
+ retryAttempt++;
+ continue;
+ }
+ ERR(err);
+ return NDBT_FAILED;
+ }
+
+ pOp = pTrans->getNdbScanOperation(tab.getName());
+ if (pOp == NULL) {
+ ERR(pTrans->getNdbError());
+ pNdb->closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ NdbResultSet*
+ rs = pOp->readTuples(NdbScanOperation::LM_Read, 0, parallelism);
+
+ if( rs == 0 ) {
+ ERR(pTrans->getNdbError());
+ pNdb->closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pOp->interpret_exit_ok();
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ pNdb->closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ if(get_values(pOp, scanRow))
+ {
+ abort();
+ }
+
+ check = pTrans->execute(NoCommit);
+ if( check == -1 ) {
+ const NdbError err = pTrans->getNdbError();
+
+ if (err.status == NdbError::TemporaryError){
+ ERR(err);
+ pNdb->closeTransaction(pTrans);
+ NdbSleep_MilliSleep(50);
+ retryAttempt++;
+ continue;
+ }
+ ERR(err);
+ pNdb->closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ int eof;
+ int rows = 0;
+ while(check == 0 && (eof = rs->nextResult()) == 0){
+ rows++;
+
+ bool null_found= false;
+ for(int a = 0; a<(int)pIndex->getNoOfColumns(); a++){
+ const NdbDictionary::Column * col = pIndex->getColumn(a);
+ if (scanRow.attributeStore(col->getName())->isNULL())
+ {
+ null_found= true;
+ break;
+ }
+ }
+
+ // Do pk lookup
+ NdbOperation * pk = pTrans->getNdbOperation(tab.getName());
+ if(!pk || pk->readTuple())
+ goto error;
+ if(equal(&tab, pk, scanRow) || get_values(pk, pkRow))
+ goto error;
+
+ if(!null_found)
+ {
+ if(!iop && (iop= pTrans->getNdbIndexScanOperation(indexName,
+ tab.getName())))
+ {
+ cursor= iop->readTuples(NdbScanOperation::LM_CommittedRead,
+ parallelism);
+ iop->interpret_exit_ok();
+ if(!cursor || get_values(iop, indexRow))
+ goto error;
+ }
+ else if(!iop || iop->reset_bounds())
+ {
+ goto error;
+ }
+
+ if(equal(pIndex, iop, scanRow))
+ goto error;
+ }
+
+ check = pTrans->execute(NoCommit);
+ if(check)
+ goto error;
+
+ if(scanRow.c_str() != pkRow.c_str()){
+ g_err << "Error when comapring records" << endl;
+ g_err << " scanRow: \n" << scanRow.c_str().c_str() << endl;
+ g_err << " pkRow: \n" << pkRow.c_str().c_str() << endl;
+ pNdb->closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ if(!null_found)
+ {
+
+ if((res= cursor->nextResult()) != 0){
+ g_err << "Failed to find row using index: " << res << endl;
+ ERR(pTrans->getNdbError());
+ pNdb->closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ if(scanRow.c_str() != indexRow.c_str()){
+ g_err << "Error when comapring records" << endl;
+ g_err << " scanRow: \n" << scanRow.c_str().c_str() << endl;
+ g_err << " indexRow: \n" << indexRow.c_str().c_str() << endl;
+ pNdb->closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ if(cursor->nextResult() == 0){
+ g_err << "Found extra row!!" << endl;
+ g_err << " indexRow: \n" << indexRow.c_str().c_str() << endl;
+ pNdb->closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+ }
+ }
+
+ if (eof == -1 || check == -1) {
+ error:
+ const NdbError err = pTrans->getNdbError();
+
+ if (err.status == NdbError::TemporaryError){
+ ERR(err);
+ iop = 0;
+ pNdb->closeTransaction(pTrans);
+ NdbSleep_MilliSleep(50);
+ retryAttempt++;
+ rows--;
+ continue;
+ }
+ ERR(err);
+ pNdb->closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ pNdb->closeTransaction(pTrans);
+
+ return NDBT_OK;
+ }
+ return NDBT_FAILED;
+}
+
+int
+UtilTransactions::get_values(NdbOperation* op, NDBT_ResultRow& dst)
+{
+ for (int a = 0; a < tab.getNoOfColumns(); a++){
+ NdbRecAttr*& ref= dst.attributeStore(a);
+ if ((ref= op->getValue(a)) == 0)
+ {
+ return NDBT_FAILED;
+ }
+ }
+ return 0;
+}
+
+int
+UtilTransactions::equal(const NdbDictionary::Index* pIndex,
+ NdbOperation* op, const NDBT_ResultRow& src)
+{
+ for(Uint32 a = 0; a<pIndex->getNoOfColumns(); a++){
+ const NdbDictionary::Column * col = pIndex->getColumn(a);
+ if(op->equal(col->getName(),
+ src.attributeStore(col->getName())->aRef()) != 0){
+ return NDBT_FAILED;
+ }
+ }
+ return 0;
+}
+
+int
+UtilTransactions::equal(const NdbDictionary::Table* pTable,
+ NdbOperation* op, const NDBT_ResultRow& src)
+{
+ for(Uint32 a = 0; a<tab.getNoOfColumns(); a++){
+ const NdbDictionary::Column* attr = tab.getColumn(a);
+ if (attr->getPrimaryKey() == true){
+ if (op->equal(attr->getName(), src.attributeStore(a)->aRef()) != 0){
+ return NDBT_FAILED;
+ }
+ }
+ }
+ return 0;
+}
diff --git a/ndb/test/tools/transproxy.cpp b/ndb/test/tools/transproxy.cpp
index 90e216ec785..88267801172 100644
--- a/ndb/test/tools/transproxy.cpp
+++ b/ndb/test/tools/transproxy.cpp
@@ -32,7 +32,7 @@ fatal(char const* fmt, ...)
va_list ap;
char buf[200];
va_start(ap, fmt);
- vsnprintf(buf, sizeof(buf), fmt, ap);
+ BaseString::vsnprintf(buf, sizeof(buf), fmt, ap);
va_end(ap);
ndbout << "FATAL: " << buf << endl;
sleep(1);
@@ -45,7 +45,7 @@ debug(char const* fmt, ...)
va_list ap;
char buf[200];
va_start(ap, fmt);
- vsnprintf(buf, sizeof(buf), fmt, ap);
+ BaseString::vsnprintf(buf, sizeof(buf), fmt, ap);
va_end(ap);
ndbout << buf << endl;
}
diff --git a/ndb/tools/listTables.cpp b/ndb/tools/listTables.cpp
index 4b24929ee4b..4fc5bcd7f21 100644
--- a/ndb/tools/listTables.cpp
+++ b/ndb/tools/listTables.cpp
@@ -38,7 +38,7 @@ fatal(char const* fmt, ...)
va_list ap;
char buf[500];
va_start(ap, fmt);
- vsnprintf(buf, sizeof(buf), fmt, ap);
+ BaseString::vsnprintf(buf, sizeof(buf), fmt, ap);
va_end(ap);
ndbout << buf;
if (ndb)
@@ -54,7 +54,7 @@ fatal_dict(char const* fmt, ...)
va_list ap;
char buf[500];
va_start(ap, fmt);
- vsnprintf(buf, sizeof(buf), fmt, ap);
+ BaseString::vsnprintf(buf, sizeof(buf), fmt, ap);
va_end(ap);
ndbout << buf;
if (dic)
diff --git a/ndb/tools/waiter.cpp b/ndb/tools/waiter.cpp
index c27b46c9356..c01a3f9192e 100644
--- a/ndb/tools/waiter.cpp
+++ b/ndb/tools/waiter.cpp
@@ -15,8 +15,8 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+#include <ndb_global.h>
#include <mgmapi.h>
-#include <string.h>
#include <NdbMain.h>
#include <NdbOut.hpp>
#include <NdbSleep.h>
@@ -68,7 +68,7 @@ int main(int argc, const char** argv){
return NDBT_ProgramExit(NDBT_FAILED);
}
- for (int i = 0; i<lcfg.ids.size();i++)
+ for (unsigned i = 0; i<lcfg.ids.size();i++)
{
MgmtSrvrId * m = &lcfg.ids[i];
@@ -292,8 +292,8 @@ waitClusterStatus(const char* _addr,
if (ndbNode->node_status < _status)
allInState = false;
else
- g_info << "node_status(" << ndbNode->node_status
- <<") != _status("<<_status<<")"<<endl;
+ g_info << "node_status(" << (unsigned)ndbNode->node_status
+ << ") != _status("<< (unsigned)_status << ")" <<endl;
} else if (ndbNode->start_phase < _startphase)
allInState = false;
} else {
diff --git a/regex/regcomp.c b/regex/regcomp.c
index 31899609e3c..5f0351c32aa 100644
--- a/regex/regcomp.c
+++ b/regex/regcomp.c
@@ -1183,6 +1183,7 @@ register cset *cs;
return(n);
}
+#ifdef USE_ORIG_REGEX_CODE
/*
- mcadd - add a collating element to a cset
== static void mcadd(register struct parse *p, register cset *cs, \
@@ -1209,6 +1210,7 @@ register char *cp;
(void) strcpy(cs->multis + oldend - 1, cp);
cs->multis[cs->smultis - 1] = '\0';
}
+#endif
#ifdef NOT_USED
/*
diff --git a/regex/regcomp.ih b/regex/regcomp.ih
index 32f1f6e89eb..5deba89217a 100644
--- a/regex/regcomp.ih
+++ b/regex/regcomp.ih
@@ -27,7 +27,9 @@ static void freeset(register struct parse *p, register cset *cs);
static int freezeset(register struct parse *p, register cset *cs);
static int firstch(register struct parse *p, register cset *cs);
static int nch(register struct parse *p, register cset *cs);
+#ifdef USE_ORIG_REGEX_CODE
static void mcadd(register struct parse *p, register cset *cs, register char *cp);
+#endif
#ifdef NOT_USED
static void mcsub(register cset *cs, register char *cp);
static int mcin(register cset *cs, register char *cp);
diff --git a/scripts/Makefile.am b/scripts/Makefile.am
index d4da77d0387..4158b5a34dc 100644
--- a/scripts/Makefile.am
+++ b/scripts/Makefile.am
@@ -139,6 +139,7 @@ SUFFIXES = .sh
-e 's!@''IS_LINUX''@!@IS_LINUX@!' \
-e "s!@""CONF_COMMAND""@!@CONF_COMMAND@!" \
-e 's!@''MYSQLD_USER''@!@MYSQLD_USER@!' \
+ -e "s!@MAKE@!$(MAKE)!" \
$< > $@-t
@CHMOD@ +x $@-t
@MV@ $@-t $@
diff --git a/scripts/make_binary_distribution.sh b/scripts/make_binary_distribution.sh
index 9af7913999f..281ef9bd469 100644
--- a/scripts/make_binary_distribution.sh
+++ b/scripts/make_binary_distribution.sh
@@ -267,8 +267,8 @@ fi
# NDB Cluster
if [ x$NDBCLUSTER = x1 ]; then
- ( cd ndb ; make DESTDIR=$BASE/ndb-stage install )
- ( cd mysql-test/ndb ; make DESTDIR=$BASE/ndb-stage install )
+ ( cd ndb ; @MAKE@ DESTDIR=$BASE/ndb-stage install )
+ ( cd mysql-test/ndb ; @MAKE@ DESTDIR=$BASE/ndb-stage install )
$CP $BASE/ndb-stage@bindir@/* $BASE/bin/.
$CP $BASE/ndb-stage@libexecdir@/* $BASE/bin/.
$CP $BASE/ndb-stage@pkglibdir@/* $BASE/lib/.
diff --git a/scripts/mysqlhotcopy.sh b/scripts/mysqlhotcopy.sh
index b8494727975..2cfe91da115 100644
--- a/scripts/mysqlhotcopy.sh
+++ b/scripts/mysqlhotcopy.sh
@@ -8,7 +8,7 @@ use File::Path;
use DBI;
use Sys::Hostname;
use File::Copy;
-use File::Temp;
+use File::Temp qw(tempfile);
=head1 NAME
@@ -39,7 +39,7 @@ WARNING: THIS PROGRAM IS STILL IN BETA. Comments/patches welcome.
# Documentation continued at end of file
-my $VERSION = "1.21";
+my $VERSION = "1.22";
my $opt_tmpdir = $ENV{TMPDIR} || "/tmp";
@@ -655,8 +655,8 @@ sub copy_index
}
elsif ($opt{method} =~ /^scp\b/)
{
- my ($fh, $tmp)=tempfile('mysqlhotcopy-XXXXXX', DIR => $opt_tmpdir);
- die "Can\'t create/open file in $opt_tmpdir\n";
+ my ($fh, $tmp)= tempfile('mysqlhotcopy-XXXXXX', DIR => $opt_tmpdir) or
+ die "Can\'t create/open file in $opt_tmpdir\n";
if (syswrite($fh,$buff) != length($buff))
{
die "Error when writing data to $tmp: $!\n";
diff --git a/sql-common/client.c b/sql-common/client.c
index 43e116eb0b6..9fca38f3857 100644
--- a/sql-common/client.c
+++ b/sql-common/client.c
@@ -2249,7 +2249,7 @@ static void mysql_close_free(MYSQL *mysql)
stmt_list pointer to mysql->stmts
*/
-void mysql_detach_stmt_list(LIST **stmt_list)
+void mysql_detach_stmt_list(LIST **stmt_list __attribute__((unused)))
{
#ifdef MYSQL_CLIENT
/* Reset connection handle in all prepared statements. */
diff --git a/sql-common/my_time.c b/sql-common/my_time.c
index 4b5daf53bea..93549f7340c 100644
--- a/sql-common/my_time.c
+++ b/sql-common/my_time.c
@@ -726,3 +726,75 @@ void set_zero_time(MYSQL_TIME *tm)
tm->time_type= MYSQL_TIMESTAMP_NONE;
}
+
+/*
+ Functions to convert time/date/datetime value to a string,
+ using default format.
+ This functions don't check that given TIME structure members are
+ in valid range. If they are not, return value won't reflect any
+ valid date either. Additionally, make_time doesn't take into
+ account time->day member: it's assumed that days have been converted
+ to hours already.
+
+ RETURN
+ number of characters written to 'to'
+*/
+
+int my_time_to_str(const MYSQL_TIME *l_time, char *to)
+{
+ return my_sprintf(to, (to, "%s%02d:%02d:%02d",
+ (l_time->neg ? "-" : ""),
+ l_time->hour,
+ l_time->minute,
+ l_time->second));
+}
+
+int my_date_to_str(const MYSQL_TIME *l_time, char *to)
+{
+ return my_sprintf(to, (to, "%04d-%02d-%02d",
+ l_time->year,
+ l_time->month,
+ l_time->day));
+}
+
+int my_datetime_to_str(const MYSQL_TIME *l_time, char *to)
+{
+ return my_sprintf(to, (to, "%04d-%02d-%02d %02d:%02d:%02d",
+ l_time->year,
+ l_time->month,
+ l_time->day,
+ l_time->hour,
+ l_time->minute,
+ l_time->second));
+}
+
+
+/*
+ Convert struct DATE/TIME/DATETIME value to string using built-in
+ MySQL time conversion formats.
+
+ SYNOPSIS
+ my_TIME_to_string()
+
+ NOTE
+ The string must have at least MAX_DATE_STRING_REP_LENGTH bytes reserved.
+*/
+
+int my_TIME_to_str(const MYSQL_TIME *l_time, char *to)
+{
+ switch (l_time->time_type) {
+ case MYSQL_TIMESTAMP_DATETIME:
+ return my_datetime_to_str(l_time, to);
+ case MYSQL_TIMESTAMP_DATE:
+ return my_date_to_str(l_time, to);
+ case MYSQL_TIMESTAMP_TIME:
+ return my_time_to_str(l_time, to);
+ case MYSQL_TIMESTAMP_NONE:
+ case MYSQL_TIMESTAMP_ERROR:
+ to[0]='\0';
+ return 0;
+ default:
+ DBUG_ASSERT(0);
+ return 0;
+ }
+}
diff --git a/sql/examples/ha_archive.cc b/sql/examples/ha_archive.cc
index c7d08772109..6fbfb3f9f9d 100644
--- a/sql/examples/ha_archive.cc
+++ b/sql/examples/ha_archive.cc
@@ -103,14 +103,15 @@
rows - This is an unsigned long long which is the number of rows in the data
file.
check point - Reserved for future use
- dirty - Status of the file, whether or not its values are the latest. This flag
- is what causes a repair to occur
+ dirty - Status of the file, whether or not its values are the latest. This
+ flag is what causes a repair to occur
The data file:
check - Just an int of 254 to make sure that the the file we are opening was
never corrupted.
version - The current version of the file format.
data - The data is stored in a "row +blobs" format.
+*/
/* Variables for archive share methods */
pthread_mutex_t archive_mutex;
diff --git a/sql/examples/ha_example.cc b/sql/examples/ha_example.cc
index 097abd48e05..cb0780ea74d 100644
--- a/sql/examples/ha_example.cc
+++ b/sql/examples/ha_example.cc
@@ -263,8 +263,8 @@ int ha_example::write_row(byte * buf)
clause was used. Consecutive ordering is not guarenteed.
Currently new_data will not have an updated auto_increament record, or
and updated timestamp field. You can do these for example by doing these:
- if (table->timestamp_on_update_now)
- update_timestamp(new_row+table->timestamp_on_update_now-1);
+ if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
+ table->timestamp_field->set_time();
if (table->next_number_field && record == table->record[0])
update_auto_increment();
diff --git a/sql/examples/ha_tina.cc b/sql/examples/ha_tina.cc
index 06a19e478ae..0345a170c3c 100644
--- a/sql/examples/ha_tina.cc
+++ b/sql/examples/ha_tina.cc
@@ -428,8 +428,8 @@ int ha_tina::write_row(byte * buf)
statistic_increment(ha_write_count,&LOCK_status);
- if (table->timestamp_default_now)
- update_timestamp(buf+table->timestamp_default_now-1);
+ if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
+ table->timestamp_field->set_time();
size= encode_quote(buf);
@@ -464,8 +464,8 @@ int ha_tina::update_row(const byte * old_data, byte * new_data)
statistic_increment(ha_update_count,&LOCK_status);
- if (table->timestamp_default_now)
- update_timestamp(new_data+table->timestamp_default_now-1);
+ if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
+ table->timestamp_field->set_time();
size= encode_quote(new_data);
diff --git a/sql/field.cc b/sql/field.cc
index 3dc1375dff3..aae507cd0ec 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -304,14 +304,11 @@ bool Field::field_cast_compatible(Field::field_cast_enum type)
{
DBUG_ASSERT(type != FIELD_CAST_STOP);
Field::field_cast_enum *array= field_cast_array[field_cast_type()];
- uint i= 0;
- Field::field_cast_enum tp;
- do
+ while (*array != FIELD_CAST_STOP)
{
- tp= array[i++];
- if (tp == type)
+ if (*(array++) == type)
return 1;
- } while (tp != FIELD_CAST_STOP);
+ }
return 0;
}
@@ -455,11 +452,9 @@ bool Field::get_time(TIME *ltime)
void Field::store_time(TIME *ltime,timestamp_type type)
{
- char buff[MAX_DATE_REP_LENGTH];
- String tmp;
- tmp.set(buff, sizeof(buff), &my_charset_bin);
- TIME_to_string(ltime, &tmp);
- store(buff, tmp.length(), &my_charset_bin);
+ char buff[MAX_DATE_STRING_REP_LENGTH];
+ uint length= (uint) my_TIME_to_str(ltime, buff);
+ store(buff, length, &my_charset_bin);
}
@@ -4438,13 +4433,9 @@ char *Field_string::pack(char *to, const char *from, uint max_length)
while (end > from && end[-1] == ' ')
end--;
length= (end-from);
+ *to++= (char) (uchar) length;
if (field_length > 255)
- {
- int2store(to, length);
- to+= 2;
- }
- else
- *to++= (char) (uchar) length;
+ *to++= (char) (uchar) (length >> 8);
memcpy(to, from, (int) length);
return to+length;
}
@@ -4459,13 +4450,9 @@ char *Field_string::pack_key(char *to, const char *from, uint max_length)
set_if_smaller(length, char_length);
while (length && from[length-1] == ' ')
length--;
+ *to++= (char) (uchar) length;
if (field_length > 255)
- {
- int2store(to, length);
- to+= 2;
- }
- else
- *to++= (char) (uchar) length;
+ *to++= (char) (uchar) (length >> 8);
memcpy(to, from, length);
return to+length;
}
diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc
index d748c005d02..8d9ecb95fc0 100644
--- a/sql/ha_innodb.cc
+++ b/sql/ha_innodb.cc
@@ -302,7 +302,7 @@ convert_error_code_to_mysql(
} else if (error == (int) DB_CANNOT_DROP_CONSTRAINT) {
- return(HA_ERR_CANNOT_ADD_FOREIGN); /* TODO: This is a bit
+ return(HA_ERR_ROW_IS_REFERENCED); /* TODO: This is a bit
misleading, a new MySQL error
code should be introduced */
} else if (error == (int) DB_COL_APPEARS_TWICE_IN_INDEX) {
@@ -429,6 +429,36 @@ innobase_mysql_print_thd(
putc('\n', f);
}
+/**********************************************************************
+Compares NUL-terminated UTF-8 strings case insensitively.
+
+NOTE that the exact prototype of this function has to be in
+/innobase/dict/dict0dict.c! */
+extern "C"
+int
+innobase_strcasecmp(
+/*================*/
+ /* out: 0 if a=b, <0 if a<b, >1 if a>b */
+ const char* a, /* in: first string to compare */
+ const char* b) /* in: second string to compare */
+{
+ return(my_strcasecmp(system_charset_info, a, b));
+}
+
+/**********************************************************************
+Makes all characters in a NUL-terminated UTF-8 string lower case.
+
+NOTE that the exact prototype of this function has to be in
+/innobase/dict/dict0dict.c! */
+extern "C"
+void
+innobase_casedn_str(
+/*================*/
+ char* a) /* in/out: string to put in lower case */
+{
+ my_casedn_str(system_charset_info, a);
+}
+
/*************************************************************************
Creates a temporary file. */
extern "C"
@@ -687,14 +717,7 @@ innobase_query_caching_of_table_permitted(
separator between db and table */
norm_name[full_name_len] = '\0';
#ifdef __WIN__
- /* Put to lower case */
-
- char* ptr = norm_name;
-
- while (*ptr != '\0') {
- *ptr = tolower(*ptr);
- ptr++;
- }
+ innobase_casedn_str(norm_name);
#endif
/* The call of row_search_.. will start a new transaction if it is
not yet started */
@@ -855,7 +878,7 @@ innobase_init(void)
Note that when using the embedded server, the datadirectory is not
necessarily the current directory of this program. */
- if (mysql_embedded) {
+ if (mysqld_embedded) {
default_path = mysql_real_data_home;
fil_path_to_mysql_datadir = mysql_real_data_home;
} else {
@@ -993,7 +1016,7 @@ innobase_init(void)
srv_max_n_open_files = (ulint) innobase_open_files;
srv_innodb_status = (ibool) innobase_create_status_file;
- srv_print_verbose_log = mysql_embedded ? 0 : 1;
+ srv_print_verbose_log = mysqld_embedded ? 0 : 1;
/* Store the default charset-collation number of this MySQL
installation */
@@ -1539,14 +1562,7 @@ normalize_table_name(
norm_name[name_ptr - db_ptr - 1] = '/';
#ifdef __WIN__
- /* Put to lower case */
-
- ptr = norm_name;
-
- while (*ptr != '\0') {
- *ptr = tolower(*ptr);
- ptr++;
- }
+ innobase_casedn_str(norm_name);
#endif
}
@@ -2445,9 +2461,10 @@ ha_innobase::write_row(
/* If the insert did not succeed we restore the value of
the auto-inc counter we used; note that this behavior was
introduced only in version 4.0.4.
- NOTE that a REPLACE command handles a duplicate key error
+ NOTE that a REPLACE command and LOAD DATA INFILE REPLACE
+ handles a duplicate key error
itself, and we must not decrement the autoinc counter
- if we are performing a REPLACE statement.
+ if we are performing a those statements.
NOTE 2: if there was an error, for example a deadlock,
which caused InnoDB to roll back the whole transaction
already in the call of row_insert_for_mysql(), we may no
@@ -2459,7 +2476,9 @@ ha_innobase::write_row(
if (error == DB_DUPLICATE_KEY
&& (user_thd->lex->sql_command == SQLCOM_REPLACE
|| user_thd->lex->sql_command
- == SQLCOM_REPLACE_SELECT)) {
+ == SQLCOM_REPLACE_SELECT
+ || (user_thd->lex->sql_command == SQLCOM_LOAD
+ && user_thd->lex->duplicates == DUP_REPLACE))) {
skip_auto_inc_decr= TRUE;
}
@@ -3559,9 +3578,9 @@ create_index(
field = form->field[j];
- if (0 == ut_cmp_in_lower_case(
- (char*)field->field_name,
- (char*)key_part->field->field_name)) {
+ if (0 == innobase_strcasecmp(
+ field->field_name,
+ key_part->field->field_name)) {
/* Found the corresponding column */
break;
@@ -4003,7 +4022,7 @@ innobase_drop_database(
namebuf[len] = '/';
namebuf[len + 1] = '\0';
#ifdef __WIN__
- my_casedn_str(system_charset_info, namebuf);
+ innobase_casedn_str(namebuf);
#endif
trx = trx_allocate_for_mysql();
trx->mysql_thd = current_thd;
@@ -4318,6 +4337,8 @@ ha_innobase::info(
ha_rows rec_per_key;
ulong j;
ulong i;
+ char path[FN_REFLEN];
+ os_file_stat_t stat_info;
DBUG_ENTER("info");
@@ -4355,6 +4376,26 @@ ha_innobase::info(
prebuilt->trx->op_info = (char*)
"returning various info to MySQL";
+
+ if (ib_table->space != 0) {
+ my_snprintf(path, sizeof(path), "%s/%s%s",
+ mysql_data_home, ib_table->name,
+ ".ibd");
+ unpack_filename(path,path);
+ } else {
+ my_snprintf(path, sizeof(path), "%s/%s%s",
+ mysql_data_home, ib_table->name,
+ reg_ext);
+
+ unpack_filename(path,path);
+ }
+
+ /* Note that we do not know the access time of the table,
+ nor the CHECK TABLE time, nor the UPDATE or INSERT time. */
+
+ if (os_file_get_status(path,&stat_info)) {
+ create_time = stat_info.ctime;
+ }
}
if (flag & HA_STATUS_VARIABLE) {
@@ -4942,7 +4983,8 @@ ha_innobase::external_lock(
}
if (prebuilt->select_lock_type != LOCK_NONE) {
- if (thd->in_lock_tables) {
+ if (thd->in_lock_tables &&
+ thd->variables.innodb_table_locks) {
ulint error;
error = row_lock_table_for_mysql(prebuilt);
@@ -5468,4 +5510,30 @@ innobase_get_at_most_n_mbchars(
}
}
+extern "C" {
+/**********************************************************************
+This function returns true if SQL-query in the current thread
+is either REPLACE or LOAD DATA INFILE REPLACE.
+NOTE that /mysql/innobase/row/row0ins.c must contain the
+prototype for this function ! */
+
+ibool
+innobase_query_is_replace(void)
+/*===========================*/
+{
+ THD* thd;
+
+ thd = (THD *)innobase_current_thd();
+
+ if ( thd->lex->sql_command == SQLCOM_REPLACE ||
+ thd->lex->sql_command == SQLCOM_REPLACE_SELECT ||
+ ( thd->lex->sql_command == SQLCOM_LOAD &&
+ thd->lex->duplicates == DUP_REPLACE )) {
+ return true;
+ } else {
+ return false;
+ }
+}
+}
+
#endif /* HAVE_INNOBASE_DB */
diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc
index 0b993ebe793..6504dd321a0 100644
--- a/sql/ha_myisam.cc
+++ b/sql/ha_myisam.cc
@@ -537,6 +537,7 @@ int ha_myisam::repair(THD* thd, HA_CHECK_OPT *check_opt)
int ha_myisam::optimize(THD* thd, HA_CHECK_OPT *check_opt)
{
+ int error;
if (!file) return HA_ADMIN_INTERNAL_ERROR;
MI_CHECK param;
@@ -546,7 +547,14 @@ int ha_myisam::optimize(THD* thd, HA_CHECK_OPT *check_opt)
param.testflag = (check_opt->flags | T_SILENT | T_FORCE_CREATE |
T_REP_BY_SORT | T_STATISTICS | T_SORT_INDEX);
param.sort_buffer_length= check_opt->sort_buffer_size;
- return repair(thd,param,1);
+ if ((error= repair(thd,param,1)) && param.retry_repair)
+ {
+ sql_print_warning("Warning: Optimize table got errno %d, retrying",
+ my_errno);
+ param.testflag&= ~T_REP_BY_SORT;
+ error= repair(thd,param,1);
+ }
+ return error;
}
@@ -913,7 +921,13 @@ int ha_myisam::enable_indexes(uint mode)
param.myf_rw&= ~MY_WAIT_IF_FULL;
param.sort_buffer_length= thd->variables.myisam_sort_buff_size;
param.tmpdir=&mysql_tmpdir_list;
- error=repair(thd,param,0) != HA_ADMIN_OK;
+ if ((error= (repair(thd,param,0) != HA_ADMIN_OK)) && param.retry_repair)
+ {
+ sql_print_warning("Warning: Enabling keys got errno %d, retrying",
+ my_errno);
+ param.testflag&= ~(T_REP_BY_SORT | T_QUICK);
+ error= (repair(thd,param,0) != HA_ADMIN_OK);
+ }
info(HA_STATUS_CONST);
thd->proc_info=save_proc_info;
}
diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc
index 3441ee1e339..145fd23ff43 100644
--- a/sql/ha_ndbcluster.cc
+++ b/sql/ha_ndbcluster.cc
@@ -65,7 +65,7 @@ typedef NdbDictionary::Table NDBTAB;
typedef NdbDictionary::Index NDBINDEX;
typedef NdbDictionary::Dictionary NDBDICT;
-bool ndbcluster_inited= false;
+bool ndbcluster_inited= FALSE;
static Ndb* g_ndb= NULL;
static Ndb_cluster_connection* g_ndb_cluster_connection= NULL;
@@ -90,6 +90,12 @@ static int ndb_get_table_statistics(Ndb*, const char *,
/*
+ Dummy buffer to read zero pack_length fields
+ which are mapped to 1 char
+*/
+static byte dummy_buf[1];
+
+/*
Error handling functions
*/
@@ -134,8 +140,13 @@ static int ndb_to_mysql_error(const NdbError *err)
uint i;
for (i=0 ; err_map[i].ndb_err != err->code ; i++)
{
- if (err_map[i].my_err == -1)
+ if (err_map[i].my_err == -1){
+ // Push the NDB error message as warning
+ push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
+ ER_GET_ERRMSG, ER(ER_GET_ERRMSG),
+ err->code, err->message, "NDB");
return err->code;
+ }
}
return err_map[i].my_err;
}
@@ -146,8 +157,10 @@ inline
int execute_no_commit(ha_ndbcluster *h, NdbConnection *trans)
{
int m_batch_execute= 0;
- if (false && m_batch_execute)
+#ifdef NOT_USED
+ if (m_batch_execute)
return 0;
+#endif
return trans->execute(NoCommit,AbortOnError,1);
}
@@ -155,8 +168,10 @@ inline
int execute_commit(ha_ndbcluster *h, NdbConnection *trans)
{
int m_batch_execute= 0;
- if (false && m_batch_execute)
+#ifdef NOT_USED
+ if (m_batch_execute)
return 0;
+#endif
return trans->execute(Commit,AbortOnError,1);
}
@@ -164,8 +179,10 @@ inline
int execute_no_commit_ie(ha_ndbcluster *h, NdbConnection *trans)
{
int m_batch_execute= 0;
- if (false && m_batch_execute)
+#ifdef NOT_USED
+ if (m_batch_execute)
return 0;
+#endif
return trans->execute(NoCommit,IgnoreError,1);
}
@@ -326,7 +343,7 @@ bool ha_ndbcluster::get_error_message(int error,
Ndb *ndb= ((Thd_ndb*)current_thd->transaction.thd_ndb)->ndb;
if (!ndb)
- DBUG_RETURN(false);
+ DBUG_RETURN(FALSE);
const NdbError err= ndb->getNdbError(error);
bool temporary= err.status==NdbError::TemporaryError;
@@ -367,12 +384,12 @@ static inline bool ndb_supported_type(enum_field_types type)
case MYSQL_TYPE_LONG_BLOB:
case MYSQL_TYPE_ENUM:
case MYSQL_TYPE_SET:
- return true;
+ return TRUE;
case MYSQL_TYPE_NULL:
case MYSQL_TYPE_GEOMETRY:
break;
}
- return false;
+ return FALSE;
}
@@ -432,6 +449,13 @@ int ha_ndbcluster::set_ndb_value(NdbOperation *ndb_op, Field *field,
if (ndb_supported_type(field->type()))
{
+ // ndb currently does not support size 0
+ const byte *empty_field= "";
+ if (pack_len == 0)
+ {
+ pack_len= 1;
+ field_ptr= empty_field;
+ }
if (! (field->flags & BLOB_FLAG))
{
if (field->is_null())
@@ -466,7 +490,7 @@ int ha_ndbcluster::set_ndb_value(NdbOperation *ndb_op, Field *field,
DBUG_DUMP("value", (char*)blob_ptr, min(blob_len, 26));
if (set_blob_value)
- *set_blob_value= true;
+ *set_blob_value= TRUE;
// No callback needed to write value
DBUG_RETURN(ndb_blob->setValue(blob_ptr, blob_len) != 0);
}
@@ -575,7 +599,11 @@ int ha_ndbcluster::get_ndb_value(NdbOperation *ndb_op, Field *field,
DBUG_ASSERT(field->ptr != NULL);
if (! (field->flags & BLOB_FLAG))
{
- byte *field_buf= buf + (field->ptr - table->record[0]);
+ byte *field_buf;
+ if (field->pack_length() != 0)
+ field_buf= buf + (field->ptr - table->record[0]);
+ else
+ field_buf= dummy_buf;
m_value[fieldnr].rec= ndb_op->getValue(fieldnr,
field_buf);
DBUG_RETURN(m_value[fieldnr].rec == NULL);
@@ -609,24 +637,24 @@ int ha_ndbcluster::get_ndb_value(NdbOperation *ndb_op, Field *field,
bool ha_ndbcluster::uses_blob_value(bool all_fields)
{
if (table->blob_fields == 0)
- return false;
+ return FALSE;
if (all_fields)
- return true;
+ return TRUE;
{
uint no_fields= table->fields;
int i;
- THD *thd= current_thd;
+ THD *thd= table->in_use;
// They always put blobs at the end..
for (i= no_fields - 1; i >= 0; i--)
{
Field *field= table->field[i];
if (thd->query_id == field->query_id)
{
- return true;
+ return TRUE;
}
}
}
- return false;
+ return FALSE;
}
@@ -645,7 +673,7 @@ int ha_ndbcluster::get_metadata(const char *path)
NDBDICT *dict= m_ndb->getDictionary();
const NDBTAB *tab;
int error;
- bool invalidating_ndb_table= false;
+ bool invalidating_ndb_table= FALSE;
DBUG_ENTER("get_metadata");
DBUG_PRINT("enter", ("m_tabname: %s, path: %s", m_tabname, path));
@@ -676,7 +704,7 @@ int ha_ndbcluster::get_metadata(const char *path)
{
DBUG_PRINT("info", ("Invalidating table"));
dict->invalidateTable(m_tabname);
- invalidating_ndb_table= true;
+ invalidating_ndb_table= TRUE;
}
else
{
@@ -687,12 +715,12 @@ int ha_ndbcluster::get_metadata(const char *path)
DBUG_DUMP("pack_data", (char*)pack_data, pack_length);
DBUG_DUMP("frm", (char*)tab->getFrmData(), tab->getFrmLength());
error= 3;
- invalidating_ndb_table= false;
+ invalidating_ndb_table= FALSE;
}
}
else
{
- invalidating_ndb_table= false;
+ invalidating_ndb_table= FALSE;
}
my_free((char*)data, MYF(0));
my_free((char*)pack_data, MYF(0));
@@ -755,7 +783,7 @@ int ha_ndbcluster::build_index_list(TABLE *tab, enum ILBP phase)
error= create_ordered_index(index_name, key_info);
break;
default:
- DBUG_ASSERT(false);
+ DBUG_ASSERT(FALSE);
break;
}
if (error)
@@ -824,13 +852,10 @@ void ha_ndbcluster::release_metadata()
int ha_ndbcluster::get_ndb_lock_type(enum thr_lock_type type)
{
- if (type == TL_WRITE_ALLOW_WRITE)
+ if (type >= TL_WRITE_ALLOW_WRITE)
return NdbOperation::LM_Exclusive;
else if (uses_blob_value(retrieve_all_fields))
- /*
- TODO use a new scan mode to read + lock + keyinfo
- */
- return NdbOperation::LM_Exclusive;
+ return NdbOperation::LM_Read;
else
return NdbOperation::LM_CommittedRead;
}
@@ -1161,7 +1186,7 @@ inline int ha_ndbcluster::next_result(byte *buf)
If this an update or delete, call nextResult with false
to process any records already cached in NdbApi
*/
- bool contact_ndb= m_lock.type != TL_WRITE_ALLOW_WRITE;
+ bool contact_ndb= m_lock.type < TL_WRITE_ALLOW_WRITE;
do {
DBUG_PRINT("info", ("Call nextResult, contact_ndb: %d", contact_ndb));
/*
@@ -1172,7 +1197,7 @@ inline int ha_ndbcluster::next_result(byte *buf)
if (execute_no_commit(this,trans) != 0)
DBUG_RETURN(ndb_err(trans));
ops_pending= 0;
- blobs_pending= false;
+ blobs_pending= FALSE;
}
check= cursor->nextResult(contact_ndb);
if (check == 0)
@@ -1225,114 +1250,204 @@ inline int ha_ndbcluster::next_result(byte *buf)
DBUG_RETURN(HA_ERR_END_OF_FILE);
}
-
/*
- Set bounds for a ordered index scan, use key_range
+ Set bounds for ordered index scan.
*/
int ha_ndbcluster::set_bounds(NdbIndexScanOperation *op,
- const key_range *key,
- int bound)
+ const key_range *keys[2])
{
- uint key_len, key_store_len, tot_len, key_tot_len;
- byte *key_ptr;
- KEY* key_info= table->key_info + active_index;
- KEY_PART_INFO* key_part= key_info->key_part;
- KEY_PART_INFO* end= key_part+key_info->key_parts;
- Field* field;
- bool key_nullable, key_null;
+ const KEY *const key_info= table->key_info + active_index;
+ const uint key_parts= key_info->key_parts;
+ uint key_tot_len[2];
+ uint tot_len;
+ int i, j;
DBUG_ENTER("set_bounds");
- DBUG_PRINT("enter", ("bound: %d", bound));
- DBUG_PRINT("enter", ("key_parts: %d", key_info->key_parts));
- DBUG_PRINT("enter", ("key->length: %d", key->length));
- DBUG_PRINT("enter", ("key->flag: %d", key->flag));
+ DBUG_PRINT("info", ("key_parts=%d", key_parts));
- // Set bounds using key data
+ for (j= 0; j <= 1; j++)
+ {
+ const key_range *key= keys[j];
+ if (key != NULL)
+ {
+ // for key->flag see ha_rkey_function
+ DBUG_PRINT("info", ("key %d length=%d flag=%d",
+ j, key->length, key->flag));
+ key_tot_len[j]= key->length;
+ }
+ else
+ {
+ DBUG_PRINT("info", ("key %d not present", j));
+ key_tot_len[j]= 0;
+ }
+ }
tot_len= 0;
- key_ptr= (byte *) key->key;
- key_tot_len= key->length;
- for (; key_part != end; key_part++)
+
+ for (i= 0; i < key_parts; i++)
{
- field= key_part->field;
- key_len= key_part->length;
- key_store_len= key_part->store_length;
- key_nullable= (bool) key_part->null_bit;
- key_null= (field->maybe_null() && *key_ptr);
- tot_len+= key_store_len;
-
- const char* bounds[]= {"LE", "LT", "GE", "GT", "EQ"};
- DBUG_ASSERT(bound >= 0 && bound <= 4);
- DBUG_PRINT("info", ("Set Bound%s on %s %s %s",
- bounds[bound],
- field->field_name,
- key_nullable ? "NULLABLE" : "",
- key_null ? "NULL":""));
- DBUG_PRINT("info", ("Total length %d", tot_len));
-
- DBUG_DUMP("key", (char*) key_ptr, key_store_len);
-
- if (op->setBound(field->field_name,
- bound,
- key_null ? 0 : (key_nullable ? key_ptr + 1 : key_ptr),
- key_null ? 0 : key_len) != 0)
- ERR_RETURN(op->getNdbError());
-
- key_ptr+= key_store_len;
+ KEY_PART_INFO *key_part= &key_info->key_part[i];
+ Field *field= key_part->field;
+ uint part_len= key_part->length;
+ uint part_store_len= key_part->store_length;
+ bool part_nullable= (bool) key_part->null_bit;
+ // Info about each key part
+ struct part_st {
+ bool part_last;
+ const key_range *key;
+ const byte *part_ptr;
+ bool part_null;
+ int bound_type;
+ const char* bound_ptr;
+ };
+ struct part_st part[2];
+
+ for (j= 0; j <= 1; j++)
+ {
+ struct part_st &p = part[j];
+ p.key= NULL;
+ p.bound_type= -1;
+ if (tot_len < key_tot_len[j])
+ {
+ p.part_last= (tot_len + part_store_len >= key_tot_len[j]);
+ p.key= keys[j];
+ p.part_ptr= &p.key->key[tot_len];
+ p.part_null= (field->maybe_null() && *p.part_ptr);
+ p.bound_ptr= (const char *)
+ p.part_null ? 0 : part_nullable ? p.part_ptr + 1 : p.part_ptr;
+
+ if (j == 0)
+ {
+ switch (p.key->flag)
+ {
+ case HA_READ_KEY_EXACT:
+ p.bound_type= NdbIndexScanOperation::BoundEQ;
+ break;
+ case HA_READ_KEY_OR_NEXT:
+ p.bound_type= NdbIndexScanOperation::BoundLE;
+ break;
+ case HA_READ_AFTER_KEY:
+ if (! p.part_last)
+ p.bound_type= NdbIndexScanOperation::BoundLE;
+ else
+ p.bound_type= NdbIndexScanOperation::BoundLT;
+ break;
+ default:
+ break;
+ }
+ }
+ if (j == 1) {
+ switch (p.key->flag)
+ {
+ case HA_READ_BEFORE_KEY:
+ if (! p.part_last)
+ p.bound_type= NdbIndexScanOperation::BoundGE;
+ else
+ p.bound_type= NdbIndexScanOperation::BoundGT;
+ break;
+ case HA_READ_AFTER_KEY: // weird
+ p.bound_type= NdbIndexScanOperation::BoundGE;
+ break;
+ default:
+ break;
+ }
+ }
- if (tot_len >= key_tot_len)
- break;
+ if (p.bound_type == -1)
+ {
+ DBUG_PRINT("error", ("key %d unknown flag %d", j, p.key->flag));
+ DBUG_ASSERT(false);
+ // Stop setting bounds but continue with what we have
+ DBUG_RETURN(0);
+ }
+ }
+ }
- /*
- Only one bound which is not EQ can be set
- so if this bound was not EQ, bail out and make
- a best effort attempt
- */
- if (bound != NdbIndexScanOperation::BoundEQ)
- break;
- }
+ // Seen with e.g. b = 1 and c > 1
+ if (part[0].bound_type == NdbIndexScanOperation::BoundLE &&
+ part[1].bound_type == NdbIndexScanOperation::BoundGE &&
+ memcmp(part[0].part_ptr, part[1].part_ptr, part_store_len) == 0)
+ {
+ DBUG_PRINT("info", ("replace LE/GE pair by EQ"));
+ part[0].bound_type= NdbIndexScanOperation::BoundEQ;
+ part[1].bound_type= -1;
+ }
+ // Not seen but was in previous version
+ if (part[0].bound_type == NdbIndexScanOperation::BoundEQ &&
+ part[1].bound_type == NdbIndexScanOperation::BoundGE &&
+ memcmp(part[0].part_ptr, part[1].part_ptr, part_store_len) == 0)
+ {
+ DBUG_PRINT("info", ("remove GE from EQ/GE pair"));
+ part[1].bound_type= -1;
+ }
+ for (j= 0; j <= 1; j++)
+ {
+ struct part_st &p = part[j];
+ // Set bound if not done with this key
+ if (p.key != NULL)
+ {
+ DBUG_PRINT("info", ("key %d:%d offset=%d length=%d last=%d bound=%d",
+ j, i, tot_len, part_len, p.part_last, p.bound_type));
+ DBUG_DUMP("info", (const char*)p.part_ptr, part_store_len);
+
+ // Set bound if not cancelled via type -1
+ if (p.bound_type != -1)
+ if (op->setBound(field->field_name, p.bound_type, p.bound_ptr))
+ ERR_RETURN(op->getNdbError());
+ }
+ }
+
+ tot_len+= part_store_len;
+ }
DBUG_RETURN(0);
}
-#ifndef DBUG_OFF
-
-const char* key_flag_strs[] =
-{ "HA_READ_KEY_EXACT",
- "HA_READ_KEY_OR_NEXT",
- "HA_READ_KEY_OR_PREV",
- "HA_READ_AFTER_KEY",
- "HA_READ_BEFORE_KEY",
- "HA_READ_PREFIX",
- "HA_READ_PREFIX_LAST",
- "HA_READ_PREFIX_LAST_OR_PREV",
- "HA_READ_MBR_CONTAIN",
- "HA_READ_MBR_INTERSECT",
- "HA_READ_MBR_WITHIN",
- "HA_READ_MBR_DISJOINT",
- "HA_READ_MBR_EQUAL"
-};
+inline
+int ha_ndbcluster::define_read_attrs(byte* buf, NdbOperation* op)
+{
+ uint i;
+ THD *thd= current_thd;
+ NdbConnection *trans= m_active_trans;
-const int no_of_key_flags = sizeof(key_flag_strs)/sizeof(char*);
+ DBUG_ENTER("define_read_attrs");
-void print_key(const key_range* key, const char* info)
-{
- if (key)
- {
- const char* str= key->flag < no_of_key_flags ?
- key_flag_strs[key->flag] : "Unknown flag";
-
- DBUG_LOCK_FILE;
- fprintf(DBUG_FILE,"%s: %s, length=%d, key=", info, str, key->length);
- uint i;
- for (i=0; i<key->length-1; i++)
- fprintf(DBUG_FILE,"%0d ", key->key[i]);
- fprintf(DBUG_FILE, "\n");
- DBUG_UNLOCK_FILE;
+ // Define attributes to read
+ for (i= 0; i < table->fields; i++)
+ {
+ Field *field= table->field[i];
+ if ((thd->query_id == field->query_id) ||
+ (field->flags & PRI_KEY_FLAG) ||
+ retrieve_all_fields)
+ {
+ if (get_ndb_value(op, field, i, buf))
+ ERR_RETURN(op->getNdbError());
+ }
+ else
+ {
+ m_value[i].ptr= NULL;
+ }
}
- return;
-}
+
+ if (table->primary_key == MAX_KEY)
+ {
+ DBUG_PRINT("info", ("Getting hidden key"));
+ // Scanning table with no primary key
+ int hidden_no= table->fields;
+#ifndef DBUG_OFF
+ const NDBTAB *tab= (const NDBTAB *) m_table;
+ if (!tab->getColumn(hidden_no))
+ DBUG_RETURN(1);
#endif
+ if (get_ndb_value(op, NULL, hidden_no, NULL))
+ ERR_RETURN(op->getNdbError());
+ }
+
+ if (execute_no_commit(this,trans) != 0)
+ DBUG_RETURN(ndb_err(trans));
+ DBUG_PRINT("exit", ("Scan started successfully"));
+ DBUG_RETURN(next_result(buf));
+}
/*
Start ordered index scan in NDB
@@ -1342,6 +1457,7 @@ int ha_ndbcluster::ordered_index_scan(const key_range *start_key,
const key_range *end_key,
bool sorted, byte* buf)
{
+ bool restart;
NdbConnection *trans= m_active_trans;
NdbResultSet *cursor;
NdbIndexScanOperation *op;
@@ -1350,44 +1466,51 @@ int ha_ndbcluster::ordered_index_scan(const key_range *start_key,
DBUG_PRINT("enter", ("index: %u, sorted: %d", active_index, sorted));
DBUG_PRINT("enter", ("Starting new ordered scan on %s", m_tabname));
- DBUG_EXECUTE("enter", print_key(start_key, "start_key"););
- DBUG_EXECUTE("enter", print_key(end_key, "end_key"););
+ // Check that sorted seems to be initialised
+ DBUG_ASSERT(sorted == 0 || sorted == 1);
+ if (m_active_cursor == 0)
+ {
+ restart= false;
+ NdbOperation::LockMode lm=
+ (NdbOperation::LockMode)get_ndb_lock_type(m_lock.type);
+ if (!(op= trans->getNdbIndexScanOperation((NDBINDEX *)
+ m_index[active_index].index,
+ (const NDBTAB *) m_table)) ||
+ !(cursor= op->readTuples(lm, 0, parallelism, sorted)))
+ ERR_RETURN(trans->getNdbError());
+ m_active_cursor= cursor;
+ } else {
+ restart= true;
+ op= (NdbIndexScanOperation*)m_active_cursor->getOperation();
+
+ DBUG_ASSERT(op->getSorted() == sorted);
+ DBUG_ASSERT(op->getLockMode() ==
+ (NdbOperation::LockMode)get_ndb_lock_type(m_lock.type));
+ if(op->reset_bounds())
+ DBUG_RETURN(ndb_err(m_active_trans));
+ }
- NdbOperation::LockMode lm=
- (NdbOperation::LockMode)get_ndb_lock_type(m_lock.type);
- if (!(op= trans->getNdbIndexScanOperation((NDBINDEX *)
- m_index[active_index].index,
- (const NDBTAB *) m_table)) ||
- !(cursor= op->readTuples(lm, 0, parallelism, sorted)))
- ERR_RETURN(trans->getNdbError());
- m_active_cursor= cursor;
-
- if (start_key &&
- set_bounds(op, start_key,
- (start_key->flag == HA_READ_KEY_EXACT) ?
- NdbIndexScanOperation::BoundEQ :
- (start_key->flag == HA_READ_AFTER_KEY) ?
- NdbIndexScanOperation::BoundLT :
- NdbIndexScanOperation::BoundLE))
- DBUG_RETURN(1);
+ {
+ const key_range *keys[2]= { start_key, end_key };
+ int ret= set_bounds(op, keys);
+ if (ret)
+ DBUG_RETURN(ret);
+ }
- if (end_key)
+ if (!restart)
{
- if (start_key && start_key->flag == HA_READ_KEY_EXACT)
- {
- DBUG_PRINT("info", ("start_key is HA_READ_KEY_EXACT ignoring end_key"));
- }
- else if (set_bounds(op, end_key,
- (end_key->flag == HA_READ_AFTER_KEY) ?
- NdbIndexScanOperation::BoundGE :
- NdbIndexScanOperation::BoundGT))
- DBUG_RETURN(1);
+ DBUG_RETURN(define_read_attrs(buf, op));
+ }
+ else
+ {
+ if (execute_no_commit(this,trans) != 0)
+ DBUG_RETURN(ndb_err(trans));
+
+ DBUG_RETURN(next_result(buf));
}
- DBUG_RETURN(define_read_attrs(buf, op));
}
-
/*
Start a filtered scan in NDB.
@@ -1496,53 +1619,6 @@ int ha_ndbcluster::full_table_scan(byte *buf)
DBUG_RETURN(define_read_attrs(buf, op));
}
-inline
-int ha_ndbcluster::define_read_attrs(byte* buf, NdbOperation* op)
-{
- uint i;
- THD *thd= current_thd;
- NdbConnection *trans= m_active_trans;
-
- DBUG_ENTER("define_read_attrs");
-
- // Define attributes to read
- for (i= 0; i < table->fields; i++)
- {
- Field *field= table->field[i];
- if ((thd->query_id == field->query_id) ||
- (field->flags & PRI_KEY_FLAG) ||
- retrieve_all_fields)
- {
- if (get_ndb_value(op, field, i, buf))
- ERR_RETURN(op->getNdbError());
- }
- else
- {
- m_value[i].ptr= NULL;
- }
- }
-
- if (table->primary_key == MAX_KEY)
- {
- DBUG_PRINT("info", ("Getting hidden key"));
- // Scanning table with no primary key
- int hidden_no= table->fields;
-#ifndef DBUG_OFF
- const NDBTAB *tab= (const NDBTAB *) m_table;
- if (!tab->getColumn(hidden_no))
- DBUG_RETURN(1);
-#endif
- if (get_ndb_value(op, NULL, hidden_no, NULL))
- ERR_RETURN(op->getNdbError());
- }
-
- if (execute_no_commit(this,trans) != 0)
- DBUG_RETURN(ndb_err(trans));
- DBUG_PRINT("exit", ("Scan started successfully"));
- DBUG_RETURN(next_result(buf));
-}
-
-
/*
Insert one record into NDB
*/
@@ -1585,7 +1661,7 @@ int ha_ndbcluster::write_row(byte *record)
if (has_auto_increment)
{
- skip_auto_increment= false;
+ skip_auto_increment= FALSE;
update_auto_increment();
skip_auto_increment= !auto_increment_column_changed;
}
@@ -1595,14 +1671,14 @@ int ha_ndbcluster::write_row(byte *record)
}
// Set non-key attribute(s)
- bool set_blob_value= false;
+ bool set_blob_value= FALSE;
for (i= 0; i < table->fields; i++)
{
Field *field= table->field[i];
if (!(field->flags & PRI_KEY_FLAG) &&
set_ndb_value(op, field, i, &set_blob_value))
{
- skip_auto_increment= true;
+ skip_auto_increment= TRUE;
ERR_RETURN(op->getNdbError());
}
}
@@ -1616,7 +1692,7 @@ int ha_ndbcluster::write_row(byte *record)
*/
rows_inserted++;
no_uncommitted_rows_update(1);
- bulk_insert_not_flushed= true;
+ bulk_insert_not_flushed= TRUE;
if ((rows_to_insert == 1) ||
((rows_inserted % bulk_insert_rows) == 0) ||
set_blob_value)
@@ -1627,12 +1703,12 @@ int ha_ndbcluster::write_row(byte *record)
"rows_inserted:%d, bulk_insert_rows: %d",
(int)rows_inserted, (int)bulk_insert_rows));
- bulk_insert_not_flushed= false;
+ bulk_insert_not_flushed= FALSE;
if (thd->transaction.on)
{
if (execute_no_commit(this,trans) != 0)
{
- skip_auto_increment= true;
+ skip_auto_increment= TRUE;
no_uncommitted_rows_execute_failure();
DBUG_RETURN(ndb_err(trans));
}
@@ -1641,7 +1717,7 @@ int ha_ndbcluster::write_row(byte *record)
{
if (execute_commit(this,trans) != 0)
{
- skip_auto_increment= true;
+ skip_auto_increment= TRUE;
no_uncommitted_rows_execute_failure();
DBUG_RETURN(ndb_err(trans));
}
@@ -1655,11 +1731,11 @@ int ha_ndbcluster::write_row(byte *record)
DBUG_PRINT("info",
("Trying to set next auto increment value to %lu",
(ulong) next_val));
- if (m_ndb->setAutoIncrementValue((const NDBTAB *) m_table, next_val, true))
+ if (m_ndb->setAutoIncrementValue((const NDBTAB *) m_table, next_val, TRUE))
DBUG_PRINT("info",
("Setting next auto increment value to %u", next_val));
}
- skip_auto_increment= true;
+ skip_auto_increment= TRUE;
DBUG_RETURN(0);
}
@@ -1763,8 +1839,8 @@ int ha_ndbcluster::update_row(const byte *old_data, byte *new_data)
if (!(op= cursor->updateTuple()))
ERR_RETURN(trans->getNdbError());
ops_pending++;
- if (uses_blob_value(false))
- blobs_pending= true;
+ if (uses_blob_value(FALSE))
+ blobs_pending= TRUE;
}
else
{
@@ -1920,7 +1996,7 @@ void ha_ndbcluster::unpack_record(byte* buf)
else
{
NdbBlob* ndb_blob= (*value).blob;
- bool isNull= true;
+ bool isNull= TRUE;
int ret= ndb_blob->getNull(isNull);
DBUG_ASSERT(ret == 0);
if (isNull)
@@ -1988,7 +2064,7 @@ void ha_ndbcluster::print_results()
else
{
ndb_blob= value.blob;
- bool isNull= true;
+ bool isNull= TRUE;
ndb_blob->getNull(isNull);
if (isNull) {
fprintf(DBUG_FILE, "NULL\n");
@@ -2165,19 +2241,16 @@ int ha_ndbcluster::index_read(byte *buf,
break;
default:
case UNDEFINED_INDEX:
- DBUG_ASSERT(false);
- return 1;
+ DBUG_ASSERT(FALSE);
+ DBUG_RETURN(1);
break;
}
- if (m_active_cursor)
- close_scan();
-
key_range start_key;
start_key.key = key;
start_key.length = key_len;
start_key.flag = find_flag;
- error= ordered_index_scan(&start_key, 0, true, buf);
+ error= ordered_index_scan(&start_key, 0, TRUE, buf);
DBUG_RETURN(error == HA_ERR_END_OF_FILE ? HA_ERR_KEY_NOT_FOUND : error);
}
@@ -2219,7 +2292,7 @@ int ha_ndbcluster::index_first(byte *buf)
// Start the ordered index scan and fetch the first row
// Only HA_READ_ORDER indexes get called by index_first
- DBUG_RETURN(ordered_index_scan(0, 0, true, buf));
+ DBUG_RETURN(ordered_index_scan(0, 0, TRUE, buf));
}
@@ -2228,9 +2301,9 @@ int ha_ndbcluster::index_last(byte *buf)
DBUG_ENTER("index_last");
statistic_increment(ha_read_last_count,&LOCK_status);
int res;
- if((res= ordered_index_scan(0, 0, true, buf)) == 0){
+ if((res= ordered_index_scan(0, 0, TRUE, buf)) == 0){
NdbResultSet *cursor= m_active_cursor;
- while((res= cursor->nextResult(true)) == 0);
+ while((res= cursor->nextResult(TRUE)) == 0);
if(res == 1){
unpack_record(buf);
table->status= 0;
@@ -2241,20 +2314,6 @@ int ha_ndbcluster::index_last(byte *buf)
}
-int ha_ndbcluster::read_range_first(const key_range *start_key,
- const key_range *end_key,
- bool eq_range, bool sorted)
-{
- byte* buf= table->record[0];
- DBUG_ENTER("ha_ndbcluster::read_range_first");
-
- DBUG_RETURN(read_range_first_to_buf(start_key,
- end_key,
- eq_range,
- sorted,
- buf));
-}
-
inline
int ha_ndbcluster::read_range_first_to_buf(const key_range *start_key,
const key_range *end_key,
@@ -2266,9 +2325,6 @@ int ha_ndbcluster::read_range_first_to_buf(const key_range *start_key,
DBUG_ENTER("ha_ndbcluster::read_range_first_to_buf");
DBUG_PRINT("info", ("eq_range: %d, sorted: %d", eq_range, sorted));
- if (m_active_cursor)
- close_scan();
-
switch (get_index_type(active_index)){
case PRIMARY_KEY_ORDERED_INDEX:
case PRIMARY_KEY_INDEX:
@@ -2296,15 +2352,26 @@ int ha_ndbcluster::read_range_first_to_buf(const key_range *start_key,
break;
}
-
// Start the ordered index scan and fetch the first row
- error= ordered_index_scan(start_key, end_key, sorted,
- buf);
-
+ error= ordered_index_scan(start_key, end_key, sorted, buf);
DBUG_RETURN(error);
}
+int ha_ndbcluster::read_range_first(const key_range *start_key,
+ const key_range *end_key,
+ bool eq_range, bool sorted)
+{
+ byte* buf= table->record[0];
+ DBUG_ENTER("ha_ndbcluster::read_range_first");
+
+ DBUG_RETURN(read_range_first_to_buf(start_key,
+ end_key,
+ eq_range,
+ sorted,
+ buf));
+}
+
int ha_ndbcluster::read_range_next()
{
DBUG_ENTER("ha_ndbcluster::read_range_next");
@@ -2584,8 +2651,8 @@ int ha_ndbcluster::extra(enum ha_extra_function operation)
case HA_EXTRA_NO_IGNORE_DUP_KEY:
DBUG_PRINT("info", ("HA_EXTRA_NO_IGNORE_DUP_KEY"));
DBUG_PRINT("info", ("Turning OFF use of write instead of insert"));
- m_use_write= false;
- m_ignore_dup_key_not_supported= false;
+ m_use_write= FALSE;
+ m_ignore_dup_key_not_supported= FALSE;
break;
case HA_EXTRA_RETRIEVE_ALL_COLS: /* Retrieve all columns, not just those
where field->query_id is the same as
@@ -2671,7 +2738,7 @@ int ha_ndbcluster::end_bulk_insert()
DBUG_PRINT("info", ("Sending inserts to NDB, "\
"rows_inserted:%d, bulk_insert_rows: %d",
rows_inserted, bulk_insert_rows));
- bulk_insert_not_flushed= false;
+ bulk_insert_not_flushed= FALSE;
if (execute_no_commit(this,trans) != 0) {
no_uncommitted_rows_execute_failure();
my_errno= error= ndb_err(trans);
@@ -2731,6 +2798,9 @@ THR_LOCK_DATA **ha_ndbcluster::store_lock(THD *thd,
/* If we are not doing a LOCK TABLE, then allow multiple
writers */
+ /* Since NDB does not currently have table locks
+ this is treated as a ordinary lock */
+
if ((lock_type >= TL_WRITE_ALLOW_WRITE &&
lock_type <= TL_WRITE) && !thd->in_lock_tables)
lock_type= TL_WRITE_ALLOW_WRITE;
@@ -3110,7 +3180,10 @@ static int create_ndb_column(NDBCOL &col,
col.setType(NDBCOL::Char);
col.setCharset(cs);
}
- col.setLength(field->pack_length());
+ if (field->pack_length() == 0)
+ col.setLength(1); // currently ndb does not support size 0
+ else
+ col.setLength(field->pack_length());
break;
case MYSQL_TYPE_VAR_STRING:
if (field->flags & BINARY_FLAG)
@@ -3210,7 +3283,7 @@ static int create_ndb_column(NDBCOL &col,
col.setAutoIncrementInitialValue(value);
}
else
- col.setAutoIncrement(false);
+ col.setAutoIncrement(FALSE);
return 0;
}
@@ -3280,7 +3353,7 @@ int ha_ndbcluster::create(const char *name,
col.setName("$PK");
col.setType(NdbDictionary::Column::Bigunsigned);
col.setLength(1);
- col.setNullable(false);
+ col.setNullable(FALSE);
col.setPrimaryKey(TRUE);
col.setAutoIncrement(TRUE);
tab.addColumn(col);
@@ -3315,7 +3388,7 @@ int ha_ndbcluster::create_ordered_index(const char *name,
KEY *key_info)
{
DBUG_ENTER("create_ordered_index");
- DBUG_RETURN(create_index(name, key_info, false));
+ DBUG_RETURN(create_index(name, key_info, FALSE));
}
int ha_ndbcluster::create_unique_index(const char *name,
@@ -3323,7 +3396,7 @@ int ha_ndbcluster::create_unique_index(const char *name,
{
DBUG_ENTER("create_unique_index");
- DBUG_RETURN(create_index(name, key_info, true));
+ DBUG_RETURN(create_index(name, key_info, TRUE));
}
@@ -3349,7 +3422,7 @@ int ha_ndbcluster::create_index(const char *name,
{
ndb_index.setType(NdbDictionary::Index::OrderedIndex);
// TODO Only temporary ordered indexes supported
- ndb_index.setLogging(false);
+ ndb_index.setLogging(FALSE);
}
ndb_index.setTable(m_tabname);
@@ -3512,15 +3585,15 @@ ha_ndbcluster::ha_ndbcluster(TABLE *table_arg):
HA_AUTO_PART_KEY |
HA_NO_PREFIX_CHAR_KEYS),
m_share(0),
- m_use_write(false),
- m_ignore_dup_key_not_supported(false),
+ m_use_write(FALSE),
+ m_ignore_dup_key_not_supported(FALSE),
retrieve_all_fields(FALSE),
rows_to_insert(1),
rows_inserted(0),
bulk_insert_rows(1024),
- bulk_insert_not_flushed(false),
+ bulk_insert_not_flushed(FALSE),
ops_pending(0),
- skip_auto_increment(true),
+ skip_auto_increment(TRUE),
blobs_pending(0),
blobs_buffer(0),
blobs_buffer_size(0),
@@ -3929,11 +4002,11 @@ int ndbcluster_find_files(THD *thd,const char *db,const char *path,
TABLE_LIST table_list;
bzero((char*) &table_list,sizeof(table_list));
table_list.db= (char*) db;
- table_list.real_name=(char*)file_name;
+ table_list.alias=table_list.real_name=(char*)file_name;
(void)mysql_rm_table_part2(thd, &table_list,
- /* if_exists */ true,
- /* drop_temporary */ false,
- /* dont_log_query*/ true);
+ /* if_exists */ TRUE,
+ /* drop_temporary */ FALSE,
+ /* dont_log_query*/ TRUE);
}
}
@@ -3942,7 +4015,7 @@ int ndbcluster_find_files(THD *thd,const char *db,const char *path,
while ((file_name=it2++))
{
DBUG_PRINT("info", ("Table %s need discovery", name));
- if (ha_create_table_from_engine(thd, db, file_name, true) == 0)
+ if (ha_create_table_from_engine(thd, db, file_name, TRUE) == 0)
files->push_back(thd->strdup(file_name));
}
@@ -4009,7 +4082,7 @@ bool ndbcluster_init()
if (ndb_discover_tables() != 0)
DBUG_RETURN(TRUE);
#endif
- DBUG_RETURN(false);
+ DBUG_RETURN(FALSE);
}
@@ -4367,7 +4440,7 @@ ndb_get_table_statistics(Ndb* ndb, const char * table,
Uint64 sum_rows= 0;
Uint64 sum_commits= 0;
- while((check= rs->nextResult(true)) == 0)
+ while((check= rs->nextResult(TRUE)) == 0)
{
sum_rows+= rows;
sum_commits+= commits;
diff --git a/sql/ha_ndbcluster.h b/sql/ha_ndbcluster.h
index 36452033516..8224d1c4167 100644
--- a/sql/ha_ndbcluster.h
+++ b/sql/ha_ndbcluster.h
@@ -139,12 +139,12 @@ class ha_ndbcluster: public handler
bool low_byte_first() const
{
#ifdef WORDS_BIGENDIAN
- return false;
+ return FALSE;
#else
- return true;
+ return TRUE;
#endif
}
- bool has_transactions() { return true; }
+ bool has_transactions() { return TRUE; }
const char* index_type(uint key_number) {
switch (get_index_type(key_number)) {
@@ -214,8 +214,7 @@ class ha_ndbcluster: public handler
int set_primary_key(NdbOperation *op, const byte *key);
int set_primary_key(NdbOperation *op);
int set_primary_key_from_old_data(NdbOperation *op, const byte *old_data);
- int set_bounds(NdbIndexScanOperation *ndb_op, const key_range *key,
- int bound);
+ int set_bounds(NdbIndexScanOperation *ndb_op, const key_range *keys[2]);
int key_cmp(uint keynr, const byte * old_row, const byte * new_row);
void print_results();
diff --git a/sql/handler.cc b/sql/handler.cc
index e59358d44bf..cecf5689464 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -1105,6 +1105,11 @@ void handler::print_error(int error, myf errflag)
break;
case HA_ERR_NO_SUCH_TABLE:
{
+ /*
+ We have to use path to find database name instead of using
+ table->table_cache_key because if the table didn't exist, then
+ table_cache_key was not set up
+ */
char *db;
char buff[FN_REFLEN];
uint length=dirname_part(buff,table->path);
@@ -1276,23 +1281,26 @@ int ha_create_table_from_engine(THD* thd,
const char *name,
bool create_if_found)
{
- int error= 0;
- const void* frmblob = NULL;
- uint frmlen = 0;
+ int error;
+ const void *frmblob;
+ uint frmlen;
char path[FN_REFLEN];
HA_CREATE_INFO create_info;
TABLE table;
DBUG_ENTER("ha_create_table_from_engine");
- DBUG_PRINT("enter", ("db: %s, name: %s", db, name));
- DBUG_PRINT("enter", ("create_if_found: %d", create_if_found));
+ DBUG_PRINT("enter", ("name '%s'.'%s' create_if_found: %d",
+ db, name, create_if_found));
bzero((char*) &create_info,sizeof(create_info));
if ((error= ha_discover(thd, db, name, &frmblob, &frmlen)))
DBUG_RETURN(error);
+ /*
+ Table exists in handler
+ frmblob and frmlen are set
+ */
- // Table exists in handler
- if (create_if_found)
+ if (create_if_found)
{
(void)strxnmov(path,FN_REFLEN,mysql_data_home,"/",db,"/",name,NullS);
// Save the frm file
@@ -1309,9 +1317,7 @@ int ha_create_table_from_engine(THD* thd,
!(table.file->table_flags() & HA_FILE_BASED))
{
/* Ensure that handler gets name in lower case */
- strmov(path, name);
my_casedn_str(files_charset_info, path);
- name= path;
}
error=table.file->create(path,&table,&create_info);
@@ -1319,8 +1325,7 @@ int ha_create_table_from_engine(THD* thd,
}
err_end:
- if (frmblob)
- my_free((char*) frmblob,MYF(0));
+ my_free((char*) frmblob, MYF(MY_ALLOW_ZERO_PTR));
DBUG_RETURN(error);
}
@@ -1429,10 +1434,14 @@ int ha_change_key_cache(KEY_CACHE *old_key_cache,
/*
Try to discover one table from handler(s)
+
+ RETURN
+ 0 ok. In this case *frmblob and *frmlen are set
+ 1 error. frmblob and frmlen may not be set
*/
-int ha_discover(THD* thd, const char* db, const char* name,
- const void** frmblob, uint* frmlen)
+int ha_discover(THD *thd, const char *db, const char *name,
+ const void **frmblob, uint *frmlen)
{
int error= 1; // Table does not exist in any handler
DBUG_ENTER("ha_discover");
@@ -1470,6 +1479,8 @@ ha_find_files(THD *thd,const char *db,const char *path,
}
+#ifdef NOT_YET_USED
+
/*
Ask handler if the table exists in engine
@@ -1491,6 +1502,7 @@ int ha_table_exists(THD* thd, const char* db, const char* name)
DBUG_RETURN(error);
}
+#endif
/*
diff --git a/sql/item.cc b/sql/item.cc
index 0366ea29485..b4c416e7741 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -348,17 +348,45 @@ Item_field::Item_field(Field *f)
:Item_ident(NullS, f->table_name, f->field_name)
{
set_field(f);
- collation.set(DERIVATION_IMPLICIT);
- fixed= 1;
+ /*
+ field_name and talbe_name should not point to garbage
+ if this item is to be reused
+ */
+ orig_table_name= orig_field_name= "";
}
Item_field::Item_field(THD *thd, Field *f)
- :Item_ident(NullS, thd->strdup(f->table_name),
- thd->strdup(f->field_name))
+ :Item_ident(f->table->table_cache_key, f->table_name, f->field_name)
{
+ /*
+ We always need to provide Item_field with a fully qualified field
+ name to avoid ambiguity when executing prepared statements like
+ SELECT * from d1.t1, d2.t1; (assuming d1.t1 and d2.t1 have columns
+ with same names).
+ This is because prepared statements never deal with wildcards in
+ select list ('*') and always fix fields using fully specified path
+ (i.e. db.table.column).
+ No check for OOM: if db_name is NULL, we'll just get
+ "Field not found" error.
+ We need to copy db_name, table_name and field_name because they must
+ be allocated in the statement memory, not in table memory (the table
+ structure can go away and pop up again between subsequent executions
+ of a prepared statement).
+ */
+ if (thd->current_arena->is_stmt_prepare())
+ {
+ if (db_name)
+ orig_db_name= thd->strdup(db_name);
+ orig_table_name= thd->strdup(table_name);
+ orig_field_name= thd->strdup(field_name);
+ /*
+ We don't restore 'name' in cleanup because it's not changed
+ during execution. Still we need it to point to persistent
+ memory if this item is to be reused.
+ */
+ name= (char*) orig_field_name;
+ }
set_field(f);
- collation.set(DERIVATION_IMPLICIT);
- fixed= 1;
}
// Constructor need to process subselect with temporary tables (see Item)
@@ -381,6 +409,21 @@ void Item_field::set_field(Field *field_par)
db_name=field_par->table->table_cache_key;
unsigned_flag=test(field_par->flags & UNSIGNED_FLAG);
collation.set(field_par->charset(), DERIVATION_IMPLICIT);
+ fixed= 1;
+}
+
+
+/*
+ Reset this item to point to a field from the new temporary table.
+ This is used when we create a new temporary table for each execution
+ of prepared statement.
+*/
+
+void Item_field::reset_field(Field *f)
+{
+ set_field(f);
+ /* 'name' is pointing at field->field_name of old field */
+ name= (char*) f->field_name;
}
const char *Item_ident::full_name() const
@@ -988,9 +1031,10 @@ String *Item_param::val_str(String* str)
return str;
case TIME_VALUE:
{
- if (str->reserve(MAX_DATE_REP_LENGTH))
+ if (str->reserve(MAX_DATE_STRING_REP_LENGTH))
break;
- TIME_to_string(&value.time, str);
+ str->length((uint) my_TIME_to_str(&value.time, (char*) str->ptr()));
+ str->set_charset(&my_charset_bin);
return str;
}
case NULL_VALUE:
@@ -1020,24 +1064,19 @@ const String *Item_param::query_val_str(String* str) const
case TIME_VALUE:
{
char *buf, *ptr;
- String tmp;
str->length(0);
/*
TODO: in case of error we need to notify replication
that binary log contains wrong statement
*/
- if (str->reserve(MAX_DATE_REP_LENGTH+3))
+ if (str->reserve(MAX_DATE_STRING_REP_LENGTH+3))
break;
/* Create date string inplace */
buf= str->c_ptr_quick();
ptr= buf;
*ptr++= '\'';
- tmp.set(ptr, MAX_DATE_REP_LENGTH, &my_charset_bin);
- tmp.length(0);
- TIME_to_string(&value.time, &tmp);
-
- ptr+= tmp.length();
+ ptr+= (uint) my_TIME_to_str(&value.time, ptr);
*ptr++= '\'';
str->length((uint32) (ptr - buf));
break;
@@ -1196,7 +1235,7 @@ bool Item_ref_null_helper::get_date(TIME *ltime, uint fuzzydate)
static void mark_as_dependent(THD *thd, SELECT_LEX *last, SELECT_LEX *current,
Item_ident *item)
{
- // store pointer on SELECT_LEX from wich item is dependent
+ // store pointer on SELECT_LEX from which item is dependent
item->depended_from= last;
current->mark_as_dependent(last);
if (thd->lex->describe & DESCRIBE_EXTENDED)
@@ -1378,8 +1417,8 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
field->query_id=thd->query_id;
table->used_fields++;
table->used_keys.intersect(field->part_of_key);
+ fixed= 1;
}
- fixed= 1;
return 0;
}
@@ -1872,10 +1911,11 @@ bool Item_field::send(Protocol *protocol, String *buffer)
return protocol->store(result_field);
}
+
/*
This is used for HAVING clause
Find field in select list having the same name
- */
+*/
bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
{
@@ -1904,8 +1944,9 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
REPORT_ALL_ERRORS ), &not_used)) ==
(Item **)not_found_item)
{
- upward_lookup= 1;
Field *tmp= (Field*) not_found_field;
+ SELECT_LEX *last= 0;
+ upward_lookup= 1;
/*
We can't find table field in select list of current select,
consequently we have to find it in outer subselect(s).
@@ -1915,7 +1956,6 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
mention of table name, but if we join tables in one list it will
cause error ER_NON_UNIQ_ERROR in find_item_in_list.
*/
- SELECT_LEX *last=0;
for ( ; sl ; sl= (prev_unit= sl->master_unit())->outer_select())
{
last= sl;
@@ -1967,9 +2007,9 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
if (!ref)
return 1;
- else if (!tmp)
+ if (!tmp)
return -1;
- else if (ref == (Item **)not_found_item && tmp == not_found_field)
+ if (ref == (Item **)not_found_item && tmp == not_found_field)
{
if (upward_lookup)
{
@@ -1984,31 +2024,33 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
*(thd->lex->current_select->get_item_list()),
&counter, REPORT_ALL_ERRORS, &not_used);
}
- ref= 0;
+ ref= 0; // Safety
return 1;
}
- else if (tmp != not_found_field)
+ if (tmp != not_found_field)
{
- ref= 0; // To prevent "delete *ref;" on ~Item_ref() of this item
- Item_field* fld= new Item_field(tmp);
- if (!fld)
+ Item_field* fld;
+ /*
+ Set ref to 0 as we are replacing this item with the found item
+ and this will ensure we get an error if this item would be
+ used elsewhere
+ */
+ ref= 0; // Safety
+ if (!(fld= new Item_field(tmp)))
return 1;
thd->change_item_tree(reference, fld);
mark_as_dependent(thd, last, thd->lex->current_select, fld);
return 0;
}
- else
+ if (!(*ref)->fixed)
{
- if (!(*ref)->fixed)
- {
- my_error(ER_ILLEGAL_REFERENCE, MYF(0), name,
- "forward reference in item list");
- return -1;
- }
- mark_as_dependent(thd, last, thd->lex->current_select,
- this);
- ref= last->ref_pointer_array + counter;
+ my_error(ER_ILLEGAL_REFERENCE, MYF(0), name,
+ "forward reference in item list");
+ return -1;
}
+ mark_as_dependent(thd, last, thd->lex->current_select,
+ this);
+ ref= last->ref_pointer_array + counter;
}
else if (!ref)
return 1;
@@ -2121,7 +2163,6 @@ bool Item_default_value::fix_fields(THD *thd,
def_field->move_field(def_field->table->default_values -
def_field->table->record[0]);
set_field(def_field);
- fixed= 1;
return 0;
}
@@ -2179,7 +2220,6 @@ bool Item_insert_value::fix_fields(THD *thd,
set_field(new Field_null(0, 0, Field::NONE, tmp_field->field_name,
tmp_field->table, &my_charset_bin));
}
- fixed= 1;
return 0;
}
@@ -2523,12 +2563,13 @@ bool Item_type_holder::join_types(THD *thd, Item *item)
uint32 new_length= real_length(item);
bool use_new_field= 0, use_expression_type= 0;
Item_result new_result_type= type_convertor[item_type][item->result_type()];
+ bool item_is_a_field= item->type() == Item::FIELD_ITEM;
/*
Check if both items point to fields: in this case we
can adjust column types of result table in the union smartly.
*/
- if (field_example && item->type() == Item::FIELD_ITEM)
+ if (field_example && item_is_a_field)
{
Field *field= ((Item_field *)item)->field;
/* Can 'field_example' field store data of the column? */
@@ -2545,23 +2586,25 @@ bool Item_type_holder::join_types(THD *thd, Item *item)
!is_attr_compatible(this, item));
}
}
- else if (field_example || item->type() == Item::FIELD_ITEM)
+ else if (field_example || item_is_a_field)
{
/*
Expression types can't be mixed with field types, we have to use
expression types.
*/
+ use_new_field= 1; // make next if test easier
use_expression_type= 1;
}
/* Check whether size/type of the result item should be changed */
- if (use_new_field || use_expression_type ||
+ if (use_new_field ||
(new_result_type != item_type) || (new_length > max_length) ||
(!maybe_null && item->maybe_null) ||
- (item_type == STRING_RESULT &&
- !my_charset_same(collation.collation, item->collation.collation)))
+ (item_type == STRING_RESULT &&
+ collation.collation != item->collation.collation))
{
- if (use_expression_type || item->type() != Item::FIELD_ITEM)
+ const char *old_cs,*old_derivation;
+ if (use_expression_type || !item_is_a_field)
field_example= 0;
else
{
@@ -2572,8 +2615,8 @@ bool Item_type_holder::join_types(THD *thd, Item *item)
field_example= ((Item_field*) item)->field;
}
- const char *old_cs= collation.collation->name,
- *old_derivation= collation.derivation_name();
+ old_cs= collation.collation->name;
+ old_derivation= collation.derivation_name();
if (item_type == STRING_RESULT && collation.aggregate(item->collation))
{
my_error(ER_CANT_AGGREGATE_2COLLATIONS, MYF(0),
@@ -2593,12 +2636,12 @@ bool Item_type_holder::join_types(THD *thd, Item *item)
return 0;
}
+
uint32 Item_type_holder::real_length(Item *item)
{
if (item->type() == Item::FIELD_ITEM)
- {
return ((Item_field *)item)->max_disp_length();
- }
+
switch (item->result_type())
{
case STRING_RESULT:
diff --git a/sql/item.h b/sql/item.h
index 68fa013647c..116dc86390c 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -310,6 +310,7 @@ public:
class st_select_lex;
class Item_ident :public Item
{
+protected:
/*
We have to store initial values of db_name, table_name and field_name
to be able to restore them during cleanup() because they can be
@@ -356,13 +357,21 @@ public:
:Item_ident(db_par,table_name_par,field_name_par),
field(0), result_field(0)
{ collation.set(DERIVATION_IMPLICIT); }
- // Constructor need to process subselect with temporary tables (see Item)
+ /*
+ Constructor needed to process subselect with temporary tables (see Item)
+ */
Item_field(THD *thd, Item_field *item);
/*
- Constructor used inside setup_wild(), ensures that field and table
- names will live as long as Item_field (important in prep. stmt.)
+ Constructor used inside setup_wild(), ensures that field, table,
+ and database names will live as long as Item_field (this is important
+ in prepared statements).
*/
Item_field(THD *thd, Field *field);
+ /*
+ If this constructor is used, fix_fields() won't work, because
+ db_name, table_name and column_name are unknown. It's necessary to call
+ reset_field() before fix_fields() for all fields created this way.
+ */
Item_field(Field *field);
enum Type type() const { return FIELD_ITEM; }
bool eq(const Item *item, bool binary_cmp) const;
@@ -373,6 +382,7 @@ public:
longlong val_int_result();
String *str_result(String* tmp);
bool send(Protocol *protocol, String *str_arg);
+ void reset_field(Field *f);
bool fix_fields(THD *, struct st_table_list *, Item **);
void make_field(Send_field *tmp_field);
int save_in_field(Field *field,bool no_conversions);
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 248b56fe064..f6730c84979 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -859,6 +859,10 @@ void Item_func_between::fix_length_and_dec()
Field *field=((Item_field*) args[0])->field;
if (field->can_be_compared_as_longlong())
{
+ /*
+ The following can't be recoded with || as convert_constant_item
+ changes the argument
+ */
if (convert_constant_item(thd, field,&args[1]))
cmp_type=INT_RESULT; // Works for all types.
if (convert_constant_item(thd, field,&args[2]))
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index dcc32441e88..69528099aa1 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -845,7 +845,7 @@ public:
char escape;
Item_func_like(Item *a,Item *b, Item *escape_arg)
- :Item_bool_func2(a,b), canDoTurboBM(false), pattern(0), pattern_len(0),
+ :Item_bool_func2(a,b), canDoTurboBM(FALSE), pattern(0), pattern_len(0),
bmGs(0), bmBc(0), escape_item(escape_arg) {}
longlong val_int();
enum Functype functype() const { return LIKE_FUNC; }
diff --git a/sql/item_func.cc b/sql/item_func.cc
index f20d69bf2ad..17cf8642ce5 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -651,11 +651,11 @@ void Item_func_int_div::fix_length_and_dec()
double Item_func_mod::val()
{
DBUG_ASSERT(fixed == 1);
- double value= floor(args[0]->val()+0.5);
- double val2=floor(args[1]->val()+0.5);
- if ((null_value=val2 == 0.0 || args[0]->null_value || args[1]->null_value))
+ double x= args[0]->val();
+ double y= args[1]->val();
+ if ((null_value= (y == 0.0) || args[0]->null_value || args[1]->null_value))
return 0.0; /* purecov: inspected */
- return fmod(value,val2);
+ return fmod(x, y);
}
longlong Item_func_mod::val_int()
@@ -670,10 +670,7 @@ longlong Item_func_mod::val_int()
void Item_func_mod::fix_length_and_dec()
{
- max_length=args[1]->max_length;
- decimals=0;
- maybe_null=1;
- find_num_type();
+ Item_num_op::fix_length_and_dec();
}
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index 301836fa839..d78a3ac88a4 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -2709,41 +2709,40 @@ longlong Item_func_crc32::val_int()
String *Item_func_compress::val_str(String *str)
{
+ int err= Z_OK, code;
+ ulong new_size;
+ String *res;
+ Byte *body;
+ char *tmp, *last_char;
DBUG_ASSERT(fixed == 1);
- String *res= args[0]->val_str(str);
- if (!res)
+
+ if (!(res= args[0]->val_str(str)))
{
null_value= 1;
return 0;
}
if (res->is_empty()) return res;
- int err= Z_OK;
- int code;
-
/*
- citation from zlib.h (comment for compress function):
+ Citation from zlib.h (comment for compress function):
Compresses the source buffer into the destination buffer. sourceLen is
- the byte length of the source buffer. Upon entry, destLen is the total
- size of the destination buffer, which must be at least 0.1% larger than
- sourceLen plus 12 bytes.
-
- Proportion 120/100 founded by Sinisa with help of procedure
- compress(compress(compress(...)))
- I.e. zlib give number 'at least'..
+ the byte length of the source buffer. Upon entry, destLen is the total
+ size of the destination buffer, which must be at least 0.1% larger than
+ sourceLen plus 12 bytes.
+ We assume here that the buffer can't grow more than .25 %.
*/
- ulong new_size= res->length() + res->length() / 5 + 12;
+ new_size= res->length() + res->length() / 5 + 12;
- // Will check new_size overflow: new_size <= res->length()
- if (((uint32) new_size <= res->length()) ||
+ // Check new_size overflow: new_size <= res->length()
+ if (((uint32) (new_size+5) <= res->length()) ||
buffer.realloc((uint32) new_size + 4 + 1))
{
null_value= 1;
return 0;
}
- Byte *body= ((Byte*)buffer.ptr()) + 4;
+ body= ((Byte*)buffer.ptr()) + 4;
// As far as we have checked res->is_empty() we can use ptr()
if ((err= compress(body, &new_size,
@@ -2755,11 +2754,11 @@ String *Item_func_compress::val_str(String *str)
return 0;
}
- char *tmp= (char*)buffer.ptr(); // int4store is a macro; avoid side effects
+ tmp= (char*)buffer.ptr(); // int4store is a macro; avoid side effects
int4store(tmp, res->length() & 0x3FFFFFFF);
- /* This is for the stupid char fields which trim ' ': */
- char *last_char= ((char*)body)+new_size-1;
+ /* This is to ensure that things works for CHAR fields, which trim ' ': */
+ last_char= ((char*)body)+new_size-1;
if (*last_char == ' ')
{
*++last_char= '.';
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index 863b041044e..48c1f2c5443 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -1292,14 +1292,13 @@ String *Item_func_curtime::val_str(String *str)
void Item_func_curtime::fix_length_and_dec()
{
TIME ltime;
- String tmp((char*) buff,sizeof(buff), &my_charset_bin);
decimals=0;
collation.set(&my_charset_bin);
store_now_in_TIME(&ltime);
value= TIME_to_ulonglong_time(&ltime);
- make_time((DATE_TIME_FORMAT *) 0, &ltime, &tmp);
- max_length= buff_length= tmp.length();
+ buff_length= (uint) my_time_to_str(&ltime, buff);
+ max_length= buff_length;
}
@@ -1341,16 +1340,14 @@ String *Item_func_now::val_str(String *str)
void Item_func_now::fix_length_and_dec()
{
- String tmp((char*) buff,sizeof(buff),&my_charset_bin);
-
decimals=0;
collation.set(&my_charset_bin);
store_now_in_TIME(&ltime);
value= (longlong) TIME_to_ulonglong_datetime(&ltime);
- make_datetime((DATE_TIME_FORMAT *) 0, &ltime, &tmp);
- max_length= buff_length= tmp.length();
+ buff_length= (uint) my_datetime_to_str(&ltime, buff);
+ max_length= buff_length;
}
diff --git a/sql/lock.cc b/sql/lock.cc
index 215059b8a46..646babea6a1 100644
--- a/sql/lock.cc
+++ b/sql/lock.cc
@@ -792,9 +792,15 @@ bool wait_if_global_read_lock(THD *thd, bool abort_on_refresh,
{
if (thd->global_read_lock) // This thread had the read locks
{
- my_error(ER_CANT_UPDATE_WITH_READLOCK,MYF(0));
+ if (is_not_commit)
+ my_error(ER_CANT_UPDATE_WITH_READLOCK,MYF(0));
(void) pthread_mutex_unlock(&LOCK_open);
- DBUG_RETURN(1);
+ /*
+ We allow FLUSHer to COMMIT; we assume FLUSHer knows what it does.
+ This allowance is needed to not break existing versions of innobackup
+ which do a BEGIN; INSERT; FLUSH TABLES WITH READ LOCK; COMMIT.
+ */
+ DBUG_RETURN(is_not_commit);
}
old_message=thd->enter_cond(&COND_refresh, &LOCK_open,
"Waiting for release of readlock");
diff --git a/sql/log_event.h b/sql/log_event.h
index 28d1f44df92..8070c334d8b 100644
--- a/sql/log_event.h
+++ b/sql/log_event.h
@@ -571,7 +571,7 @@ public:
{
fname= afname;
fname_len= alen;
- local_fname= true;
+ local_fname= TRUE;
}
/* fname doesn't point to memory inside Log_event::temp_buf */
int check_fname_outside_temp_buf()
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 1a0879c6347..391199942e0 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -284,14 +284,6 @@ void debug_sync_point(const char* lock_name, uint lock_timeout);
#define WEEK_MONDAY_FIRST 1
#define WEEK_YEAR 2
#define WEEK_FIRST_WEEKDAY 4
-/*
- Required buffer length for make_date, make_time, make_datetime
- and TIME_to_string functions. Note, that the caller is still
- responsible to check that given TIME structure has values
- in valid ranges, otherwise size of the buffer could be not
- enough.
-*/
-#define MAX_DATE_REP_LENGTH 30
enum enum_parsing_place
{
@@ -374,7 +366,7 @@ int multi_delete_precheck(THD *thd, TABLE_LIST *tables, uint *table_count);
int insert_select_precheck(THD *thd, TABLE_LIST *tables);
int update_precheck(THD *thd, TABLE_LIST *tables);
int delete_precheck(THD *thd, TABLE_LIST *tables);
-int insert_precheck(THD *thd, TABLE_LIST *tables, bool update);
+int insert_precheck(THD *thd, TABLE_LIST *tables);
int create_table_precheck(THD *thd, TABLE_LIST *tables,
TABLE_LIST *create_table);
Item *negate_expression(THD *thd, Item *expr);
@@ -897,7 +889,7 @@ extern uint test_flags,select_errors,ha_open_options;
extern uint protocol_version, mysqld_port, dropping_tables;
extern uint delay_key_write_options, lower_case_table_names;
extern bool opt_endinfo, using_udf_functions, locked_in_memory;
-extern bool opt_using_transactions, mysql_embedded;
+extern bool opt_using_transactions, mysqld_embedded;
extern bool using_update_log, opt_large_files, server_id_supplied;
extern bool opt_log, opt_update_log, opt_bin_log, opt_slow_log, opt_error_log;
extern bool opt_disable_networking, opt_skip_show_db;
@@ -1046,7 +1038,6 @@ void make_date(const DATE_TIME_FORMAT *format, const TIME *l_time,
String *str);
void make_time(const DATE_TIME_FORMAT *format, const TIME *l_time,
String *str);
-void TIME_to_string(const TIME *time, String *str);
ulonglong TIME_to_ulonglong_datetime(const TIME *time);
ulonglong TIME_to_ulonglong_date(const TIME *time);
ulonglong TIME_to_ulonglong_time(const TIME *time);
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index d7d0f637ec2..384f76029f9 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -449,9 +449,9 @@ pthread_cond_t eventShutdown;
#endif
#ifndef EMBEDDED_LIBRARY
-bool mysql_embedded=0;
+bool mysqld_embedded=0;
#else
-bool mysql_embedded=1;
+bool mysqld_embedded=1;
#endif
#ifndef DBUG_OFF
@@ -4012,6 +4012,7 @@ enum options_mysqld
OPT_INNODB_FORCE_RECOVERY,
OPT_INNODB_STATUS_FILE,
OPT_INNODB_MAX_DIRTY_PAGES_PCT,
+ OPT_INNODB_TABLE_LOCKS,
OPT_INNODB_OPEN_FILES,
OPT_INNODB_AUTOEXTEND_INCREMENT,
OPT_BDB_CACHE_SIZE,
@@ -4250,6 +4251,11 @@ Disable with --skip-innodb (will save memory).",
"Enable SHOW INNODB STATUS output in the innodb_status.<pid> file",
(gptr*) &innobase_create_status_file, (gptr*) &innobase_create_status_file,
0, GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0},
+ {"innodb_table_locks", OPT_INNODB_TABLE_LOCKS,
+ "If Innodb should enforce LOCK TABLE",
+ (gptr*) &global_system_variables.innodb_table_locks,
+ (gptr*) &global_system_variables.innodb_table_locks,
+ 0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0},
#endif /* End HAVE_INNOBASE_DB */
{"isam", OPT_ISAM, "Enable ISAM (if this version of MySQL supports it). \
Disable with --skip-isam.",
@@ -4812,7 +4818,7 @@ replicating a LOAD DATA INFILE command.",
(gptr*) &dflt_key_cache_var.param_buff_size,
(gptr*) 0,
0, (GET_ULL | GET_ASK_ADDR),
- REQUIRED_ARG, KEY_CACHE_SIZE, MALLOC_OVERHEAD, (long) ~0, MALLOC_OVERHEAD,
+ REQUIRED_ARG, KEY_CACHE_SIZE, MALLOC_OVERHEAD, UINT_MAX32, MALLOC_OVERHEAD,
IO_SIZE, 0},
{"key_cache_age_threshold", OPT_KEY_CACHE_AGE_THRESHOLD,
"This characterizes the number of hits a hot block has to be untouched until it is considered aged enough to be downgraded to a warm block. This specifies the percentage ratio of that number of hits to the total number of blocks in key cache",
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 9c5b0235767..541acc69ec7 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -393,7 +393,7 @@ SQL_SELECT::~SQL_SELECT()
#undef index // Fix for Unixware 7
QUICK_SELECT::QUICK_SELECT(THD *thd, TABLE *table, uint key_nr, bool no_alloc)
- :dont_free(0),error(0),index(key_nr),max_used_key_length(0),
+ :dont_free(0),sorted(0),error(0),index(key_nr),max_used_key_length(0),
used_key_parts(0), head(table), it(ranges),range(0)
{
if (!no_alloc)
diff --git a/sql/protocol.cc b/sql/protocol.cc
index c2d9117b062..060dc14be10 100644
--- a/sql/protocol.cc
+++ b/sql/protocol.cc
@@ -880,10 +880,9 @@ bool Protocol_simple::store_date(TIME *tm)
field_types[field_pos] == MYSQL_TYPE_DATE);
field_pos++;
#endif
- char buff[40];
- String tmp((char*) buff,sizeof(buff),&my_charset_bin);
- make_date((DATE_TIME_FORMAT *) 0, tm, &tmp);
- return net_store_data((char*) tmp.ptr(), tmp.length());
+ char buff[MAX_DATE_STRING_REP_LENGTH];
+ int length= my_date_to_str(tm, buff);
+ return net_store_data(buff, (uint) length);
}
diff --git a/sql/set_var.cc b/sql/set_var.cc
index d661470576b..b5e479b9985 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -351,6 +351,8 @@ sys_var_thd_ulong sys_net_wait_timeout("wait_timeout",
#ifdef HAVE_INNOBASE_DB
sys_var_long_ptr sys_innodb_max_dirty_pages_pct("innodb_max_dirty_pages_pct",
&srv_max_buf_pool_modified_pct);
+sys_var_thd_bool sys_innodb_table_locks("innodb_table_locks",
+ &SV::innodb_table_locks);
sys_var_long_ptr sys_innodb_autoextend_increment("innodb_autoextend_increment",
&srv_auto_extend_increment);
sys_var_long_ptr sys_innodb_max_purge_lag("innodb_max_purge_lag",
@@ -605,6 +607,7 @@ sys_var *sys_variables[]=
&sys_os,
#ifdef HAVE_INNOBASE_DB
&sys_innodb_max_dirty_pages_pct,
+ &sys_innodb_table_locks,
&sys_innodb_max_purge_lag,
&sys_innodb_autoextend_increment,
#endif
@@ -700,6 +703,7 @@ struct show_var_st init_vars[]= {
{"innodb_log_files_in_group", (char*) &innobase_log_files_in_group, SHOW_LONG},
{"innodb_log_group_home_dir", (char*) &innobase_log_group_home_dir, SHOW_CHAR_PTR},
{sys_innodb_max_dirty_pages_pct.name, (char*) &sys_innodb_max_dirty_pages_pct, SHOW_SYS},
+ {sys_innodb_table_locks.name, (char*) &sys_innodb_table_locks, SHOW_SYS},
{sys_innodb_max_purge_lag.name, (char*) &sys_innodb_max_purge_lag, SHOW_SYS},
{"innodb_mirrored_log_groups", (char*) &innobase_mirrored_log_groups, SHOW_LONG},
{"innodb_open_files", (char*) &innobase_open_files, SHOW_LONG },
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index fc252c1f5ac..b7eecac4e48 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -2398,7 +2398,8 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list,
table_list->db,
table_list->real_name,
rights, column_priv, revoke_grant))
- { // Crashend table ??
+ {
+ /* Should only happen if table is crashed */
result= -1; /* purecov: deadcode */
}
else if (tables[2].table)
@@ -3636,12 +3637,17 @@ int mysql_revoke_all(THD *thd, List <LEX_USER> &list)
if (!strcmp(lex_user->user.str,user) &&
!my_strcasecmp(system_charset_info, lex_user->host.str, host))
{
- if (replace_db_table(tables[1].table, acl_db->db, *lex_user, ~0, 1))
- result= -1;
- else
+ if (!replace_db_table(tables[1].table, acl_db->db, *lex_user, ~0, 1))
+ {
+ /*
+ Don't increment counter as replace_db_table deleted the
+ current element in acl_db's and shifted the higher elements down
+ */
continue;
+ }
+ result= -1; // Something went wrong
}
- ++counter;
+ counter++;
}
/* Remove column access */
@@ -3664,26 +3670,27 @@ int mysql_revoke_all(THD *thd, List <LEX_USER> &list)
~0, 0, 1))
{
result= -1;
+ continue;
}
else
{
- if (grant_table->cols)
- {
- List<LEX_COLUMN> columns;
- if (replace_column_table(grant_table,tables[3].table, *lex_user,
- columns,
- grant_table->db,
- grant_table->tname,
- ~0, 1))
- result= -1;
- else
- continue;
- }
- else
- continue;
+ if (!grant_table->cols)
+ continue;
+ List<LEX_COLUMN> columns;
+ if (replace_column_table(grant_table,tables[3].table, *lex_user,
+ columns,
+ grant_table->db,
+ grant_table->tname,
+ ~0, 1))
+ result= -1;
+ /*
+ Safer to do continue here as replace_table_table changed
+ column_priv_hash and we want to test the current element
+ */
+ continue;
}
}
- ++counter;
+ counter++;
}
}
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 31b2ab9ea89..cd7b643e146 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -818,6 +818,7 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name,
table->query_id=thd->query_id;
table->clear_query_id=1;
thd->tmp_table_used= 1;
+ DBUG_PRINT("info",("Using temporary table"));
goto reset;
}
}
@@ -832,6 +833,7 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name,
table->query_id != thd->query_id)
{
table->query_id=thd->query_id;
+ DBUG_PRINT("info",("Using locked table"));
goto reset;
}
}
@@ -1368,7 +1370,7 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db,
*/
if (discover_retry_count++ != 0)
goto err;
- if (ha_create_table_from_engine(thd, db, name, true) != 0)
+ if (ha_create_table_from_engine(thd, db, name, TRUE) != 0)
goto err;
thd->clear_error(); // Clear error message
@@ -2653,8 +2655,8 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
strlen(t1_field_name), 0, 0,
&not_used_field_index)))
{
- Item_func_eq *tmp=new Item_func_eq(new Item_field(*t1_field),
- new Item_field(t2_field));
+ Item_func_eq *tmp=new Item_func_eq(new Item_field(thd, *t1_field),
+ new Item_field(thd, t2_field));
if (!tmp)
goto err;
/* Mark field used for table cache */
@@ -2846,8 +2848,15 @@ void flush_tables()
/*
-** Mark all entries with the table as deleted to force an reopen of the table
-** Returns true if the table is in use by another thread
+ Mark all entries with the table as deleted to force an reopen of the table
+
+ The table will be closed (not stored in cache) by the current thread when
+ close_thread_tables() is called.
+
+ RETURN
+ 0 This thread now have exclusive access to this table and no other thread
+ can access the table until close_thread_tables() is called.
+ 1 Table is in use by another thread
*/
bool remove_table_from_cache(THD *thd, const char *db, const char *table_name,
diff --git a/sql/sql_class.h b/sql/sql_class.h
index aea31f7db54..e73b35966a9 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -396,6 +396,9 @@ struct system_variables
my_bool low_priority_updates;
my_bool new_mode;
my_bool query_cache_wlock_invalidate;
+#ifdef HAVE_INNOBASE_DB
+ my_bool innodb_table_locks;
+#endif /* HAVE_INNOBASE_DB */
my_bool old_passwords;
/* Only charset part of these variables is sensible */
@@ -461,6 +464,8 @@ public:
inline bool is_stmt_prepare() const { return (int)state < (int)PREPARED; }
inline bool is_first_stmt_execute() const { return state == PREPARED; }
+ inline bool is_stmt_execute() const
+ { return state == PREPARED || state == EXECUTED; }
inline bool is_conventional_execution() const
{ return state == CONVENTIONAL_EXECUTION; }
inline gptr alloc(unsigned int size) { return alloc_root(&mem_root,size); }
@@ -1109,6 +1114,13 @@ public:
unit= u;
return 0;
}
+ /*
+ Because of peculiarities of prepared statements protocol
+ we need to know number of columns in the result set (if
+ there is a result set) apart from sending columns metadata.
+ */
+ virtual uint field_count(List<Item> &fields) const
+ { return fields.elements; }
virtual bool send_fields(List<Item> &list,uint flag)=0;
virtual bool send_data(List<Item> &items)=0;
virtual bool initialize_tables (JOIN *join=0) { return 0; }
@@ -1123,6 +1135,20 @@ public:
};
+/*
+ Base class for select_result descendands which intercept and
+ transform result set rows. As the rows are not sent to the client,
+ sending of result set metadata should be suppressed as well.
+*/
+
+class select_result_interceptor: public select_result
+{
+public:
+ uint field_count(List<Item> &fields) const { return 0; }
+ bool send_fields(List<Item> &fields, uint flag) { return FALSE; }
+};
+
+
class select_send :public select_result {
public:
select_send() {}
@@ -1132,7 +1158,7 @@ public:
};
-class select_to_file :public select_result {
+class select_to_file :public select_result_interceptor {
protected:
sql_exchange *exchange;
File file;
@@ -1144,7 +1170,6 @@ public:
select_to_file(sql_exchange *ex) :exchange(ex), file(-1),row_count(0L)
{ path[0]=0; }
~select_to_file();
- bool send_fields(List<Item> &list, uint flag) { return 0; }
void send_error(uint errcode,const char *err);
bool send_eof();
void cleanup();
@@ -1171,7 +1196,7 @@ public:
};
-class select_insert :public select_result {
+class select_insert :public select_result_interceptor {
public:
TABLE *table;
List<Item> *fields;
@@ -1187,8 +1212,6 @@ class select_insert :public select_result {
}
~select_insert();
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
- bool send_fields(List<Item> &list, uint flag)
- { return 0; }
bool send_data(List<Item> &items);
void send_error(uint errcode,const char *err);
bool send_eof();
@@ -1271,7 +1294,7 @@ public:
}
};
-class select_union :public select_result {
+class select_union :public select_result_interceptor {
public:
TABLE *table;
COPY_INFO info;
@@ -1280,8 +1303,6 @@ class select_union :public select_result {
select_union(TABLE *table_par);
~select_union();
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
- bool send_fields(List<Item> &list, uint flag)
- { return 0; }
bool send_data(List<Item> &items);
bool send_eof();
bool flush();
@@ -1289,13 +1310,12 @@ class select_union :public select_result {
};
/* Base subselect interface class */
-class select_subselect :public select_result
+class select_subselect :public select_result_interceptor
{
protected:
Item_subselect *item;
public:
select_subselect(Item_subselect *item);
- bool send_fields(List<Item> &list, uint flag) { return 0; };
bool send_data(List<Item> &items)=0;
bool send_eof() { return 0; };
};
@@ -1432,7 +1452,7 @@ public:
};
-class multi_delete :public select_result
+class multi_delete :public select_result_interceptor
{
TABLE_LIST *delete_tables, *table_being_deleted;
Unique **tempfiles;
@@ -1445,8 +1465,6 @@ public:
multi_delete(THD *thd, TABLE_LIST *dt, uint num_of_tables);
~multi_delete();
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
- bool send_fields(List<Item> &list,
- uint flag) { return 0; }
bool send_data(List<Item> &items);
bool initialize_tables (JOIN *join);
void send_error(uint errcode,const char *err);
@@ -1455,7 +1473,7 @@ public:
};
-class multi_update :public select_result
+class multi_update :public select_result_interceptor
{
TABLE_LIST *all_tables, *update_tables, *table_being_updated;
THD *thd;
@@ -1474,7 +1492,6 @@ public:
List<Item> *values, enum_duplicates handle_duplicates);
~multi_update();
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
- bool send_fields(List<Item> &list, uint flag) { return 0; }
bool send_data(List<Item> &items);
bool initialize_tables (JOIN *join);
void send_error(uint errcode,const char *err);
@@ -1483,7 +1500,7 @@ public:
};
-class select_dumpvar :public select_result {
+class select_dumpvar :public select_result_interceptor {
ha_rows row_count;
public:
List<LEX_STRING> var_list;
@@ -1491,7 +1508,6 @@ public:
select_dumpvar(void) { var_list.empty(); vars.empty(); row_count=0;}
~select_dumpvar() {}
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
- bool send_fields(List<Item> &list, uint flag) {return 0;}
bool send_data(List<Item> &items);
bool send_eof();
void cleanup();
diff --git a/sql/sql_help.cc b/sql/sql_help.cc
index eabe66d33bf..ffaaafc26e6 100644
--- a/sql/sql_help.cc
+++ b/sql/sql_help.cc
@@ -746,7 +746,7 @@ int mysqld_help(THD *thd, const char *mask)
select,&subcategories_list);
delete select;
String *cat= categories_list.head();
- if (send_header_2(protocol, true) ||
+ if (send_header_2(protocol, TRUE) ||
send_variant_2_list(mem_root,protocol,&topics_list, "N",cat) ||
send_variant_2_list(mem_root,protocol,&subcategories_list,"Y",cat))
goto end;
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 856742d13bc..679ffb2140e 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -477,7 +477,6 @@ inline static uint int_token(const char *str,uint length)
int yylex(void *arg, void *yythd)
{
reg1 uchar c;
- bool space_ignored;
int tokval, result_state;
uint length;
enum my_lex_states state;
@@ -560,6 +559,7 @@ int yylex(void *arg, void *yythd)
/* Fall through */
case MY_LEX_IDENT_OR_BIN: // TODO: Add binary string handling
case MY_LEX_IDENT:
+ uchar *start;
#if defined(USE_MB) && defined(USE_MB_IDENT)
if (use_mb(cs))
{
@@ -596,12 +596,16 @@ int yylex(void *arg, void *yythd)
result_state= result_state & 0x80 ? IDENT_QUOTED : IDENT;
}
length= (uint) (lex->ptr - lex->tok_start)-1;
- space_ignored= FALSE;
+ start= lex->ptr;
if (lex->ignore_space)
{
- for (; state_map[c] == MY_LEX_SKIP ; space_ignored= TRUE, c= yyGet());
+ /*
+ If we find a space then this can't be an identifier. We notice this
+ below by checking start != lex->ptr.
+ */
+ for (; state_map[c] == MY_LEX_SKIP ; c= yyGet());
}
- if (! space_ignored && c == '.' && ident_map[yyPeek()])
+ if (start == lex->ptr && c == '.' && ident_map[yyPeek()])
lex->next_state=MY_LEX_IDENT_SEP;
else
{ // '(' must follow directly if function
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index e7a013e19ea..8279e32c8de 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -501,12 +501,17 @@ void free_max_user_conn(void)
/*
Mark all commands that somehow changes a table
This is used to check number of updates / hour
+
+ sql_command is actually set to SQLCOM_END sometimes
+ so we need the +1 to include it in the array.
*/
-char uc_update_queries[SQLCOM_END];
+char uc_update_queries[SQLCOM_END+1];
void init_update_queries(void)
{
+ bzero((gptr) &uc_update_queries, sizeof(uc_update_queries));
+
uc_update_queries[SQLCOM_CREATE_TABLE]=1;
uc_update_queries[SQLCOM_CREATE_INDEX]=1;
uc_update_queries[SQLCOM_ALTER_TABLE]=1;
@@ -531,6 +536,7 @@ void init_update_queries(void)
bool is_update_query(enum enum_sql_command command)
{
+ DBUG_ASSERT(command >= 0 && command <= SQLCOM_END);
return uc_update_queries[command];
}
@@ -894,7 +900,7 @@ static int check_connection(THD *thd)
x_free(thd->user);
if (!(thd->user= my_strdup(user, MYF(0))))
return (ER_OUT_OF_RESOURCES);
- return check_user(thd, COM_CONNECT, passwd, passwd_len, db, true);
+ return check_user(thd, COM_CONNECT, passwd, passwd_len, db, TRUE);
}
@@ -2682,12 +2688,11 @@ unsent_create_error:
case SQLCOM_REPLACE:
case SQLCOM_INSERT:
{
- my_bool update= (lex->value_list.elements ? UPDATE_ACL : 0);
- if ((res= insert_precheck(thd, tables, update)))
+ if ((res= insert_precheck(thd, tables)))
break;
res = mysql_insert(thd,tables,lex->field_list,lex->many_values,
select_lex->item_list, lex->value_list,
- (update ? DUP_UPDATE : lex->duplicates));
+ lex->duplicates);
if (thd->net.report_error)
res= -1;
break;
@@ -4767,7 +4772,7 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
acl_reload(thd);
grant_reload(thd);
if (mqh_used)
- reset_mqh(thd,(LEX_USER *) NULL,true);
+ reset_mqh(thd,(LEX_USER *) NULL,TRUE);
}
#endif
if (options & REFRESH_LOG)
@@ -5366,13 +5371,14 @@ int delete_precheck(THD *thd, TABLE_LIST *tables)
-1 error (message is not sent to user)
*/
-int insert_precheck(THD *thd, TABLE_LIST *tables, bool update)
+int insert_precheck(THD *thd, TABLE_LIST *tables)
{
LEX *lex= thd->lex;
DBUG_ENTER("insert_precheck");
- ulong privilege= (lex->duplicates == DUP_REPLACE ?
- INSERT_ACL | DELETE_ACL : INSERT_ACL | update);
+ ulong privilege= INSERT_ACL |
+ (lex->duplicates == DUP_REPLACE ? DELETE_ACL : 0) |
+ (lex->duplicates == DUP_UPDATE ? UPDATE_ACL : 0);
if (check_one_table_access(thd, privilege, tables))
DBUG_RETURN(1);
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 27d98fdfeba..12f526c5566 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -895,10 +895,9 @@ static int mysql_test_insert(Prepared_statement *stmt,
int res= -1;
TABLE_LIST *insert_table_list=
(TABLE_LIST*) lex->select_lex.table_list.first;
- my_bool update= (lex->value_list.elements ? UPDATE_ACL : 0);
DBUG_ENTER("mysql_test_insert");
- if ((res= insert_precheck(thd, table_list, update)))
+ if ((res= insert_precheck(thd, table_list)))
DBUG_RETURN(res);
/*
@@ -1065,6 +1064,12 @@ static int mysql_test_select(Prepared_statement *stmt,
DBUG_RETURN(1);
#endif
+ if (!lex->result && !(lex->result= new (&stmt->mem_root) select_send))
+ {
+ send_error(thd);
+ goto err;
+ }
+
if (open_and_lock_tables(thd, tables))
{
send_error(thd);
@@ -1088,8 +1093,13 @@ static int mysql_test_select(Prepared_statement *stmt,
}
else
{
- if (send_prep_stmt(stmt, lex->select_lex.item_list.elements) ||
- thd->protocol_simple.send_fields(&lex->select_lex.item_list, 0)
+ List<Item> &fields= lex->select_lex.item_list;
+ /*
+ We can use lex->result as it should've been
+ prepared in unit->prepare call above.
+ */
+ if (send_prep_stmt(stmt, lex->result->field_count(fields)) ||
+ lex->result->send_fields(fields, 0)
#ifndef EMBEDDED_LIBRARY
|| net_flush(&thd->net)
#endif
@@ -1388,8 +1398,7 @@ static int send_prepare_results(Prepared_statement *stmt, bool text_protocol)
res= mysql_test_insert(stmt, tables, lex->field_list,
lex->many_values,
select_lex->item_list, lex->value_list,
- (lex->value_list.elements ?
- DUP_UPDATE : lex->duplicates));
+ lex->duplicates);
break;
case SQLCOM_UPDATE:
@@ -1781,7 +1790,7 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length)
goto set_params_data_err;
#endif
thd->protocol= &thd->protocol_prep; // Switch to binary protocol
- execute_stmt(thd, stmt, &expanded_query, true);
+ execute_stmt(thd, stmt, &expanded_query, TRUE);
thd->protocol= &thd->protocol_simple; // Use normal protocol
DBUG_VOID_RETURN;
@@ -1834,7 +1843,7 @@ void mysql_sql_stmt_execute(THD *thd, LEX_STRING *stmt_name)
my_error(ER_WRONG_ARGUMENTS, MYF(0), "EXECUTE");
send_error(thd);
}
- execute_stmt(thd, stmt, &expanded_query, false);
+ execute_stmt(thd, stmt, &expanded_query, FALSE);
DBUG_VOID_RETURN;
}
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 638ed229a70..df74a946b5c 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -6911,10 +6911,23 @@ part_of_refkey(TABLE *table,Field *field)
/*****************************************************************************
Test if one can use the key to resolve ORDER BY
- Returns: 1 if key is ok.
- 0 if key can't be used
- -1 if reverse key can be used
- used_key_parts is set to key parts used if length != 0
+
+ SYNOPSIS
+ test_if_order_by_key()
+ order Sort order
+ table Table to sort
+ idx Index to check
+ used_key_parts Return value for used key parts.
+
+
+ NOTES
+ used_key_parts is set to correct key parts used if return value != 0
+ (On other cases, used_key_part may be changed)
+
+ RETURN
+ 1 key is ok.
+ 0 Key can't be used
+ -1 Reverse key can be used
*****************************************************************************/
static int test_if_order_by_key(ORDER *order, TABLE *table, uint idx,
@@ -6943,16 +6956,17 @@ static int test_if_order_by_key(ORDER *order, TABLE *table, uint idx,
DBUG_RETURN(0);
/* set flag to 1 if we can use read-next on key, else to -1 */
- flag= ((order->asc == !(key_part->key_part_flag & HA_REVERSE_SORT)) ? 1 : -1);
+ flag= ((order->asc == !(key_part->key_part_flag & HA_REVERSE_SORT)) ?
+ 1 : -1);
if (reverse && flag != reverse)
DBUG_RETURN(0);
reverse=flag; // Remember if reverse
key_part++;
}
- uint tmp= (uint) (key_part - table->key_info[idx].key_part);
- if (reverse == -1 && !(table->file->index_flags(idx,tmp-1, 1) & HA_READ_PREV))
- DBUG_RETURN(0);
- *used_key_parts= tmp;
+ *used_key_parts= (uint) (key_part - table->key_info[idx].key_part);
+ if (reverse == -1 && !(table->file->index_flags(idx, *used_key_parts-1, 1) &
+ HA_READ_PREV))
+ reverse= 0; // Index can't be used
DBUG_RETURN(reverse);
}
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index c5cd2860e03..e030db2caf7 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -1136,7 +1136,7 @@ static const char *require_quotes(const char *name, uint name_length)
for ( ; name < end ; name++)
{
uchar chr= (uchar) *name;
- length= my_mbcharlen(system_charset_info, (uchar) chr);
+ length= my_mbcharlen(system_charset_info, chr);
if (length == 1 && !system_charset_info->ident_map[chr])
return name;
}
@@ -1148,25 +1148,29 @@ void
append_identifier(THD *thd, String *packet, const char *name, uint length)
{
const char *name_end;
+ char quote_char;
int q= get_quote_char_for_identifier(thd, name, length);
- if (q == EOF) {
+ if (q == EOF)
+ {
packet->append(name, length, system_charset_info);
return;
}
- char quote_char= q;
-
- /* The identifier must be quoted as it includes a quote character */
+ /*
+ The identifier must be quoted as it includes a quote character or
+ it's a keyword
+ */
packet->reserve(length*2 + 2);
+ quote_char= (char) q;
packet->append(&quote_char, 1, system_charset_info);
for (name_end= name+length ; name < name_end ; name+= length)
{
- char chr= *name;
- length= my_mbcharlen(system_charset_info, (uchar) chr);
- if (length == 1 && chr == quote_char)
+ uchar chr= (uchar) *name;
+ length= my_mbcharlen(system_charset_info, chr);
+ if (length == 1 && chr == (uchar) quote_char)
packet->append(&quote_char, 1, system_charset_info);
packet->append(name, length, packet->charset());
}
@@ -1174,8 +1178,25 @@ append_identifier(THD *thd, String *packet, const char *name, uint length)
}
-/* Get the quote character for displaying an identifier.
- If no quote character is needed, return EOF. */
+/*
+ Get the quote character for displaying an identifier.
+
+ SYNOPSIS
+ get_quote_char_for_identifier()
+ thd Thread handler
+ name name to quote
+ length length of name
+
+ IMPLEMENTATION
+ If name is a keyword or includes a special character, then force
+ quoting.
+ Otherwise identifier is quoted only if the option OPTION_QUOTE_SHOW_CREATE
+ is set.
+
+ RETURN
+ EOF No quote character is needed
+ # Quote character
+*/
int get_quote_char_for_identifier(THD *thd, const char *name, uint length)
{
@@ -1183,10 +1204,9 @@ int get_quote_char_for_identifier(THD *thd, const char *name, uint length)
!require_quotes(name, length) &&
!(thd->options & OPTION_QUOTE_SHOW_CREATE))
return EOF;
- else if (thd->variables.sql_mode & MODE_ANSI_QUOTES)
+ if (thd->variables.sql_mode & MODE_ANSI_QUOTES)
return '"';
- else
- return '`';
+ return '`';
}
@@ -1195,10 +1215,9 @@ int get_quote_char_for_identifier(THD *thd, const char *name, uint length)
static void append_directory(THD *thd, String *packet, const char *dir_type,
const char *filename)
{
- uint length;
if (filename && !(thd->variables.sql_mode & MODE_NO_DIR_IN_CREATE))
{
- length= dirname_length(filename);
+ uint length= dirname_length(filename);
packet->append(' ');
packet->append(dir_type);
packet->append(" DIRECTORY='", 12);
diff --git a/sql/sql_string.cc b/sql/sql_string.cc
index 1ec0faafa8f..1044dc4e58e 100644
--- a/sql/sql_string.cc
+++ b/sql/sql_string.cc
@@ -537,7 +537,8 @@ uint32 String::numchars()
int String::charpos(int i,uint32 offset)
{
- if (i<0) return i;
+ if (i <= 0)
+ return i;
return str_charset->cset->charpos(str_charset,Ptr+offset,Ptr+str_length,i);
}
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 65e23c7ba1d..d2de24b0d2a 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -223,7 +223,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
(void) unpack_filename(path,path);
}
if (drop_temporary ||
- (access(path,F_OK) && ha_create_table_from_engine(thd,db,alias,true)))
+ (access(path,F_OK) && ha_create_table_from_engine(thd,db,alias,TRUE)))
{
if (if_exists)
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index b46cfc05538..44004e1238d 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -264,9 +264,27 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
}
}
- // it is not single select
if (first_select->next_select())
{
+ /* This is not a single select */
+
+ /*
+ Check that it was possible to aggregate
+ all collations together for UNION.
+ */
+ List_iterator_fast<Item> tp(types);
+ Item_arena *arena= thd->current_arena;
+ Item *type;
+ while ((type= tp++))
+ {
+ if (type->result_type() == STRING_RESULT &&
+ type->collation.derivation == DERIVATION_NONE)
+ {
+ my_error(ER_CANT_AGGREGATE_NCOLLATIONS, MYF(0), "UNION");
+ goto err;
+ }
+ }
+
union_result->tmp_table_param.field_count= types.elements;
if (!(table= create_tmp_table(thd_arg,
&union_result->tmp_table_param, types,
@@ -287,7 +305,11 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
thd_arg->lex->current_select= lex_select_save;
if (!item_list.elements)
{
- Item_arena *arena= thd->current_arena, backup;
+ /*
+ We're in statement prepare or in execution
+ of a conventional statement.
+ */
+ Item_arena backup;
if (arena->is_stmt_prepare())
thd->set_n_backup_item_arena(arena, &backup);
Field **field;
@@ -327,6 +349,20 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
fake_select_lex->table_list.empty();
}
}
+ else if (arena->is_stmt_execute())
+ {
+ /*
+ We're in execution of a prepared statement: reset field items
+ to point at fields from the created temporary table.
+ */
+ List_iterator_fast<Item> it(item_list);
+ for (Field **field= table->field; *field; field++)
+ {
+ Item_field *item_field= (Item_field*) it++;
+ DBUG_ASSERT(item_field);
+ item_field->reset_field(*field);
+ }
+ }
}
else
first_select->braces= 0; // remove our changes
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index c1513dd55e2..426f6d4d057 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -843,14 +843,14 @@ prepare_src:
THD *thd=YYTHD;
LEX *lex= thd->lex;
lex->prepared_stmt_code= $1;
- lex->prepared_stmt_code_is_varref= false;
+ lex->prepared_stmt_code_is_varref= FALSE;
}
| '@' ident_or_text
{
THD *thd=YYTHD;
LEX *lex= thd->lex;
lex->prepared_stmt_code= $2;
- lex->prepared_stmt_code_is_varref= true;
+ lex->prepared_stmt_code_is_varref= TRUE;
};
execute:
@@ -4136,14 +4136,18 @@ expr_or_default:
opt_insert_update:
/* empty */
| ON DUPLICATE_SYM
- { /* for simplisity, let's forget about
- INSERT ... SELECT ... UPDATE
- for a moment */
- if (Lex->sql_command != SQLCOM_INSERT)
+ {
+ LEX *lex= Lex;
+ /*
+ For simplicity, let's forget about INSERT ... SELECT ... UPDATE
+ for a moment.
+ */
+ if (lex->sql_command != SQLCOM_INSERT)
{
yyerror(ER(ER_SYNTAX_ERROR));
YYABORT;
}
+ lex->duplicates= DUP_UPDATE;
}
KEY_SYM UPDATE_SYM update_list
;
diff --git a/sql/table.h b/sql/table.h
index f25b172a0d9..2eb854f553d 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -164,6 +164,7 @@ struct st_table {
MEM_ROOT mem_root;
GRANT_INFO grant;
+ /* A pair "database_name\0table_name\0", widely used as simply a db name */
char *table_cache_key;
char *table_name,*real_name,*path;
uint key_length; /* Length of key */
diff --git a/sql/time.cc b/sql/time.cc
index 4421b6aa00f..e76b169b336 100644
--- a/sql/time.cc
+++ b/sql/time.cc
@@ -747,13 +747,7 @@ const char *get_date_time_format_str(KNOWN_DATE_TIME_FORMAT *format,
void make_time(const DATE_TIME_FORMAT *format __attribute__((unused)),
const TIME *l_time, String *str)
{
- long length= my_sprintf((char*) str->ptr(),
- ((char*) str->ptr(),
- "%s%02d:%02d:%02d",
- (l_time->neg ? "-" : ""),
- l_time->hour,
- l_time->minute,
- l_time->second));
+ uint length= (uint) my_time_to_str(l_time, (char*) str->ptr());
str->length(length);
str->set_charset(&my_charset_bin);
}
@@ -762,12 +756,7 @@ void make_time(const DATE_TIME_FORMAT *format __attribute__((unused)),
void make_date(const DATE_TIME_FORMAT *format __attribute__((unused)),
const TIME *l_time, String *str)
{
- long length= my_sprintf((char*) str->ptr(),
- ((char*) str->ptr(),
- "%04d-%02d-%02d",
- l_time->year,
- l_time->month,
- l_time->day));
+ uint length= (uint) my_date_to_str(l_time, (char*) str->ptr());
str->length(length);
str->set_charset(&my_charset_bin);
}
@@ -776,15 +765,7 @@ void make_date(const DATE_TIME_FORMAT *format __attribute__((unused)),
void make_datetime(const DATE_TIME_FORMAT *format __attribute__((unused)),
const TIME *l_time, String *str)
{
- long length= my_sprintf((char*) str->ptr(),
- ((char*) str->ptr(),
- "%04d-%02d-%02d %02d:%02d:%02d",
- l_time->year,
- l_time->month,
- l_time->day,
- l_time->hour,
- l_time->minute,
- l_time->second));
+ uint length= (uint) my_datetime_to_str(l_time, (char*) str->ptr());
str->length(length);
str->set_charset(&my_charset_bin);
}
@@ -894,38 +875,4 @@ ulonglong TIME_to_ulonglong(const TIME *time)
return 0;
}
-
-/*
- Convert struct DATE/TIME/DATETIME value to string using built-in
- MySQL time conversion formats.
-
- SYNOPSIS
- TIME_to_string()
-
- NOTE
- The string must have at least MAX_DATE_REP_LENGTH bytes reserved.
-*/
-
-void TIME_to_string(const TIME *time, String *str)
-{
- switch (time->time_type) {
- case MYSQL_TIMESTAMP_DATETIME:
- make_datetime((DATE_TIME_FORMAT*) 0, time, str);
- break;
- case MYSQL_TIMESTAMP_DATE:
- make_date((DATE_TIME_FORMAT*) 0, time, str);
- break;
- case MYSQL_TIMESTAMP_TIME:
- make_time((DATE_TIME_FORMAT*) 0, time, str);
- break;
- case MYSQL_TIMESTAMP_NONE:
- case MYSQL_TIMESTAMP_ERROR:
- str->length(0);
- str->set_charset(&my_charset_bin);
- break;
- default:
- DBUG_ASSERT(0);
- }
-}
-
#endif
diff --git a/strings/CHARSET_INFO.txt b/strings/CHARSET_INFO.txt
new file mode 100644
index 00000000000..f7a10f95880
--- /dev/null
+++ b/strings/CHARSET_INFO.txt
@@ -0,0 +1,230 @@
+
+CHARSET_INFO
+============
+A structure containing data for charset+collation pair implementation.
+
+Virtual functions which use this data are collected
+into separate structures MY_CHARSET_HANDLER and
+MY_COLLATION_HANDLER.
+
+
+typedef struct charset_info_st
+{
+ uint number;
+ uint primary_number;
+ uint binary_number;
+ uint state;
+
+ const char *csname;
+ const char *name;
+ const char *comment;
+
+ uchar *ctype;
+ uchar *to_lower;
+ uchar *to_upper;
+ uchar *sort_order;
+
+ uint16 *tab_to_uni;
+ MY_UNI_IDX *tab_from_uni;
+
+ uchar state_map[256];
+ uchar ident_map[256];
+
+ uint strxfrm_multiply;
+ uint mbminlen;
+ uint mbmaxlen;
+ char max_sort_char; /* For LIKE optimization */
+
+ MY_CHARSET_HANDLER *cset;
+ MY_COLLATION_HANDLER *coll;
+
+} CHARSET_INFO;
+
+
+CHARSET_INFO fields description:
+===============================
+
+
+Numbers (identifiers)
+---------------------
+
+number - an ID uniquely identifying this charset+collation pair.
+
+primary_number - ID of a charset+collation pair, which consists
+of the same character set and the default collation of this
+character set. Not really used now. Intended to optimize some
+parts of the code where we need to find the default collation
+using its non-default counterpart for the given character set.
+
+binary_numner - ID of a charset+collation pair, which consists
+of the same character set and the binary collation of this
+character set. Not really used now.
+
+Names
+-----
+
+ csname - name of the character set for this charset+collation pair.
+ name - name of the collation for this charset+collation pair.
+ comment - a text comment, dysplayed in "Description" column of
+ SHOW CHARACTER SET output.
+
+Conversion tables
+-----------------
+
+ ctype - pointer to array[257] of "type of characters"
+ bit mask for each chatacter, e.g. if a
+ character is a digit or a letter or a separator, etc.
+
+ Monty 2004-10-21:
+ If you look at the macros, we use ctype[(char)+1].
+ ctype[0] is traditionally in most ctype libraries
+ reserved for EOF (-1). The idea is that you can use
+ the result from fgetc() directly with ctype[]. As
+ we have to be compatible with external ctype[] versions,
+ it's better to do it the same way as they do...
+
+ to_lower - pointer to array[256] used in LCASE()
+ to_upper - pointer to array[256] used in UCASE()
+ sort_order - pointer to array[256] used for strings comparison
+
+
+
+Unicode conversion data
+-----------------------
+For 8bit character sets:
+
+tab_to_uni : array[256] of charset->Unicode translation
+tab_from_uni: a structure for Unicode->charset translation
+
+Non-8 bit charsets have their own structures per charset
+hidden in correspondent ctype-xxx.c file and don't use
+tab_to_uni and tab_from_uni tables.
+
+
+Parser maps
+-----------
+state_map[]
+ident_map[]
+
+ These maps are to quickly identify if a character is
+an identificator part, a digit, a special character,
+or a part of other SQL language lexical item.
+
+Probably can be combined with ctype array in the future.
+But for some reasons these two arrays are used in the parser,
+while a separate ctype[] array is used in the other part of the
+code, like fulltext, etc.
+
+
+Misc fields
+-----------
+
+ strxfrm_multiply - how many times a sort key (i.e. a string
+ which can be passed into memcmp() for comparison)
+ can be longer than the original string.
+ Usually it is 1. For some complex
+ collations it can be bigger. For example
+ in latin1_german2_ci, a sort key is up to
+ twice longer than the original string.
+ e.g. Letter 'A' with two dots above is
+ substituted with 'AE'.
+ mbminlen - mininum multibyte sequence length.
+ Now always 1 except ucs2. For ucs2
+ it is 2.
+ mbmaxlen - maximum multibyte sequence length.
+ 1 for 8bit charsets. Can be also 2 or 3.
+
+
+
+MY_CHARSET_HANDLER
+==================
+
+MY_CHARSET_HANDLER is a collection of character-set
+related routines. Defined in m_ctype.h. Have the
+following set of functions:
+
+Multibyte routines
+------------------
+ismbchar() - detects if the given string is a multibyte sequence
+mbcharlen() - returns length of multibyte sequence starting with
+ the given character
+numchars() - returns number of characters in the given string, e.g.
+ in SQL function CHAR_LENGTH().
+charpos() - calculates the offset of the given position in the string.
+ Used in SQL functions LEFT(), RIGHT(), SUBSTRING(),
+ INSERT()
+
+well_formed_length()
+ - finds the length of correctly formed multybyte beginning.
+ Used in INSERTs to cut a beginning of the given string
+ which is
+ a) "well formed" according to the given character set.
+ b) can fit into the given data type
+ Terminates the string in the good position, taking in account
+ multibyte character boundaries.
+
+lengthsp() - returns the length of the given string without traling spaces.
+
+
+Unicode conversion routines
+---------------------------
+mb_wc - converts the left multibyte sequence into it Unicode code.
+mc_mb - converts the given Unicode code into multibyte sequence.
+
+
+Case and sort convertion
+------------------------
+caseup_str - converts the given 0-terminated string into the upper case
+casedn_str - converts the given 0-terminated string into the lower case
+caseup - converts the given string into the lower case using length
+casedn - converts the given string into the lower case using length
+
+Number-to-string conversion routines
+------------------------------------
+snprintf()
+long10_to_str()
+longlong10_to_str()
+
+The names are pretty self-descripting.
+
+String padding routines
+-----------------------
+fill() - writes the given Unicode value into the given string
+ with the given length. Used to pad the string, usually
+ with space character, according to the given charset.
+
+String-to-numner conversion routines
+------------------------------------
+strntol()
+strntoul()
+strntoll()
+strntoull()
+strntod()
+
+These functions are almost for the same thing with their
+STDLIB counterparts, but also:
+ - accept length instead of 0-terminator
+ - and are character set dependant
+
+Simple scanner routines
+-----------------------
+scan() - to skip leading spaces in the given string.
+ Used when a string value is inserted into a numeric field.
+
+
+
+MY_COLLATION_HANDLER
+====================
+strnncoll() - compares two strings according to the given collation
+strnncollsp() - like the above but ignores trailing spaces
+strnxfrm() - makes a sort key suitable for memcmp() corresponding
+ to the given string
+like_range() - creates a LIKE range, for optimizer
+wildcmp() - wildcard comparison, for LIKE
+strcasecmp() - 0-terminated string comparison
+instr() - finds the first substring appearence in the string
+hash_sort() - calculates hash value taking in account
+ the collation rules, e.g. case-insensitivity,
+ accent sensitivity, etc.
+
+ \ No newline at end of file
diff --git a/strings/Makefile.am b/strings/Makefile.am
index be51e48ef8d..d17a4f598a6 100644
--- a/strings/Makefile.am
+++ b/strings/Makefile.am
@@ -57,7 +57,7 @@ EXTRA_DIST = ctype-big5.c ctype-czech.c ctype-euc_kr.c ctype-win1250ch.c \
t_ctype.h
libmystrings_a_LIBADD=
-conf_to_src_SOURCES = conf_to_src.c xml.c ctype.c
+conf_to_src_SOURCES = conf_to_src.c xml.c ctype.c bcmp.c
conf_to_src_LDADD=
#force static linking of conf_to_src - essential when linking against
#custom installation of libc
diff --git a/strings/ctype-mb.c b/strings/ctype-mb.c
index a41449d5e50..e7527b418f5 100644
--- a/strings/ctype-mb.c
+++ b/strings/ctype-mb.c
@@ -123,8 +123,7 @@ int my_strcasecmp_mb(CHARSET_INFO * cs,const char *s, const char *t)
** 1 if matched with wildcard
*/
-#define INC_PTR(cs,A,B) A+=((use_mb_flag && \
- my_ismbchar(cs,A,B)) ? my_ismbchar(cs,A,B) : 1)
+#define INC_PTR(cs,A,B) A+=(my_ismbchar(cs,A,B) ? my_ismbchar(cs,A,B) : 1)
#define likeconv(s,A) (uchar) (s)->sort_order[(uchar) (A)]
@@ -135,8 +134,6 @@ int my_wildcmp_mb(CHARSET_INFO *cs,
{
int result= -1; /* Not found, using wildcards */
- bool use_mb_flag=use_mb(cs);
-
while (wildstr != wildend)
{
while (*wildstr != w_many && *wildstr != w_one)
@@ -144,8 +141,7 @@ int my_wildcmp_mb(CHARSET_INFO *cs,
int l;
if (*wildstr == escape && wildstr+1 != wildend)
wildstr++;
- if (use_mb_flag &&
- (l = my_ismbchar(cs, wildstr, wildend)))
+ if ((l = my_ismbchar(cs, wildstr, wildend)))
{
if (str+l > str_end || memcmp(str, wildstr, l) != 0)
return 1;
@@ -200,41 +196,30 @@ int my_wildcmp_mb(CHARSET_INFO *cs,
cmp= *++wildstr;
mb=wildstr;
- LINT_INIT(mblen);
- if (use_mb_flag)
- mblen = my_ismbchar(cs, wildstr, wildend);
+ mblen= my_ismbchar(cs, wildstr, wildend);
INC_PTR(cs,wildstr,wildend); /* This is compared trough cmp */
cmp=likeconv(cs,cmp);
do
{
- if (use_mb_flag)
- {
- for (;;)
+ for (;;)
+ {
+ if (str >= str_end)
+ return -1;
+ if (mblen)
{
- if (str >= str_end)
- return -1;
- if (mblen)
- {
- if (str+mblen <= str_end && memcmp(str, mb, mblen) == 0)
- {
- str += mblen;
- break;
- }
- }
- else if (!my_ismbchar(cs, str, str_end) &&
- likeconv(cs,*str) == cmp)
+ if (str+mblen <= str_end && memcmp(str, mb, mblen) == 0)
{
- str++;
+ str += mblen;
break;
}
- INC_PTR(cs,str, str_end);
}
- }
- else
- {
- while (str != str_end && likeconv(cs,*str) != cmp)
+ else if (!my_ismbchar(cs, str, str_end) &&
+ likeconv(cs,*str) == cmp)
+ {
str++;
- if (str++ == str_end) return (-1);
+ break;
+ }
+ INC_PTR(cs,str, str_end);
}
{
int tmp=my_wildcmp_mb(cs,str,str_end,wildstr,wildend,escape,w_one,
@@ -555,8 +540,6 @@ static int my_wildcmp_mb_bin(CHARSET_INFO *cs,
{
int result= -1; /* Not found, using wildcards */
- bool use_mb_flag=use_mb(cs);
-
while (wildstr != wildend)
{
while (*wildstr != w_many && *wildstr != w_one)
@@ -564,8 +547,7 @@ static int my_wildcmp_mb_bin(CHARSET_INFO *cs,
int l;
if (*wildstr == escape && wildstr+1 != wildend)
wildstr++;
- if (use_mb_flag &&
- (l = my_ismbchar(cs, wildstr, wildend)))
+ if ((l = my_ismbchar(cs, wildstr, wildend)))
{
if (str+l > str_end || memcmp(str, wildstr, l) != 0)
return 1;
@@ -620,39 +602,28 @@ static int my_wildcmp_mb_bin(CHARSET_INFO *cs,
cmp= *++wildstr;
mb=wildstr;
- LINT_INIT(mblen);
- if (use_mb_flag)
- mblen = my_ismbchar(cs, wildstr, wildend);
+ mblen= my_ismbchar(cs, wildstr, wildend);
INC_PTR(cs,wildstr,wildend); /* This is compared trough cmp */
do
{
- if (use_mb_flag)
- {
- for (;;)
+ for (;;)
+ {
+ if (str >= str_end)
+ return -1;
+ if (mblen)
{
- if (str >= str_end)
- return -1;
- if (mblen)
- {
- if (str+mblen <= str_end && memcmp(str, mb, mblen) == 0)
- {
- str += mblen;
- break;
- }
- }
- else if (!my_ismbchar(cs, str, str_end) && *str == cmp)
+ if (str+mblen <= str_end && memcmp(str, mb, mblen) == 0)
{
- str++;
+ str += mblen;
break;
}
- INC_PTR(cs,str, str_end);
}
- }
- else
- {
- while (str != str_end && *str != cmp)
+ else if (!my_ismbchar(cs, str, str_end) && *str == cmp)
+ {
str++;
- if (str++ == str_end) return (-1);
+ break;
+ }
+ INC_PTR(cs,str, str_end);
}
{
int tmp=my_wildcmp_mb_bin(cs,str,str_end,wildstr,wildend,escape,w_one,w_many);
diff --git a/strings/ctype-sjis.c b/strings/ctype-sjis.c
index 55ff8ac28fe..4176ff2e538 100644
--- a/strings/ctype-sjis.c
+++ b/strings/ctype-sjis.c
@@ -4563,6 +4563,40 @@ uint my_numcells_sjis(CHARSET_INFO *cs __attribute__((unused)),
return clen;
}
+/*
+ Returns a well formed length of a SJIS string.
+ CP932 additional characters are also accepted.
+*/
+static
+uint my_well_formed_len_sjis(CHARSET_INFO *cs __attribute__((unused)),
+ const char *b, const char *e, uint pos)
+{
+ const char *b0= b;
+ while (pos && b < e)
+ {
+ /*
+ Cast to int8 for extra safety.
+ "char" can be unsigned by default
+ on some platforms.
+ */
+ if (((int8)b[0]) >= 0)
+ {
+ /* Single byte character */
+ b+= 1;
+ }
+ else if (issjishead((uchar)*b) && (e-b)>1 && issjistail((uchar)b[1]))
+ {
+ /* Double byte character */
+ b+= 2;
+ }
+ else
+ {
+ /* Wrong byte sequence */
+ break;
+ }
+ }
+ return b - b0;
+}
static MY_COLLATION_HANDLER my_collation_ci_handler =
@@ -4586,7 +4620,7 @@ static MY_CHARSET_HANDLER my_charset_handler=
mbcharlen_sjis,
my_numchars_mb,
my_charpos_mb,
- my_well_formed_len_mb,
+ my_well_formed_len_sjis,
my_lengthsp_8bit,
my_numcells_sjis,
my_mb_wc_sjis, /* mb_wc */
diff --git a/strings/ctype-uca.c b/strings/ctype-uca.c
index 446fc821337..91af7af0c54 100644
--- a/strings/ctype-uca.c
+++ b/strings/ctype-uca.c
@@ -7052,6 +7052,28 @@ static int my_strnncoll_uca(CHARSET_INFO *cs,
NOTES:
Works exactly the same with my_strnncoll_uca(),
but ignores trailing spaces.
+
+ In the while() comparison these situations are possible:
+ 1. (s_res>0) and (t_res>0) and (s_res == t_res)
+ Weights are the same so far, continue comparison
+ 2. (s_res>0) and (t_res>0) and (s_res!=t_res)
+ A difference has been found, return.
+ 3. (s_res>0) and (t_res<0)
+ We have reached the end of the second string, or found
+ an illegal multibyte sequence in the second string.
+ Compare the first string to an infinite array of
+ space characters until difference is found, or until
+ the end of the first string.
+ 4. (s_res<0) and (t_res>0)
+ We have reached the end of the first string, or found
+ an illegal multibyte sequence in the first string.
+ Compare the second string to an infinite array of
+ space characters until difference is found or until
+ the end of the second steing.
+ 5. (s_res<0) and (t_res<0)
+ Both scanners returned -1. It means we have riched
+ the end-of-string of illegal-sequence in both strings
+ at the same time. Return 0, strings are equal.
RETURN
Difference between two strings, according to the collation:
@@ -7070,9 +7092,6 @@ static int my_strnncollsp_uca(CHARSET_INFO *cs,
int s_res;
int t_res;
- slen= cs->cset->lengthsp(cs, (char*) s, slen);
- tlen= cs->cset->lengthsp(cs, (char*) t, tlen);
-
scanner_handler->init(&sscanner, cs, s, slen);
scanner_handler->init(&tscanner, cs, t, tlen);
@@ -7081,6 +7100,36 @@ static int my_strnncollsp_uca(CHARSET_INFO *cs,
s_res= scanner_handler->next(&sscanner);
t_res= scanner_handler->next(&tscanner);
} while ( s_res == t_res && s_res >0);
+
+ if (s_res > 0 && t_res < 0)
+ {
+ /* Calculate weight for SPACE character */
+ t_res= cs->sort_order_big[0][0x20 * cs->sort_order[0]];
+
+ /* compare the first string to spaces */
+ do
+ {
+ if (s_res != t_res)
+ return (s_res - t_res);
+ s_res= scanner_handler->next(&sscanner);
+ } while (s_res > 0);
+ return 0;
+ }
+
+ if (s_res < 0 && t_res > 0)
+ {
+ /* Calculate weight for SPACE character */
+ s_res= cs->sort_order_big[0][0x20 * cs->sort_order[0]];
+
+ /* compare the second string to spaces */
+ do
+ {
+ if (s_res != t_res)
+ return (s_res - t_res);
+ t_res= scanner_handler->next(&tscanner);
+ } while (t_res > 0);
+ return 0;
+ }
return ( s_res - t_res );
}
diff --git a/strings/ctype-ucs2.c b/strings/ctype-ucs2.c
index 3247e1d7424..851c2044f47 100644
--- a/strings/ctype-ucs2.c
+++ b/strings/ctype-ucs2.c
@@ -1231,172 +1231,14 @@ uint my_lengthsp_ucs2(CHARSET_INFO *cs __attribute__((unused)),
}
-/*
-** Compare string against string with wildcard
-** 0 if matched
-** -1 if not matched with wildcard
-** 1 if matched with wildcard
-*/
-
-static
-int my_wildcmp_ucs2(CHARSET_INFO *cs,
- const char *str,const char *str_end,
- const char *wildstr,const char *wildend,
- int escape, int w_one, int w_many,
- MY_UNICASE_INFO **weights)
-{
- int result= -1; /* Not found, using wildcards */
- my_wc_t s_wc, w_wc;
- int scan, plane;
-
- while (wildstr != wildend)
- {
-
- while (1)
- {
- scan= my_ucs2_uni(cs,&w_wc, (const uchar*)wildstr,
- (const uchar*)wildend);
- if (scan <= 0)
- return 1;
-
- if (w_wc == (my_wc_t)escape)
- {
- wildstr+= scan;
- scan= my_ucs2_uni(cs,&w_wc, (const uchar*)wildstr,
- (const uchar*)wildend);
- if (scan <= 0)
- return 1;
- }
-
- if (w_wc == (my_wc_t)w_many)
- {
- result= 1; /* Found an anchor char */
- break;
- }
-
- wildstr+= scan;
- scan= my_ucs2_uni(cs, &s_wc, (const uchar*)str, (const uchar*)str_end);
- if (scan <=0)
- return 1;
- str+= scan;
-
- if (w_wc == (my_wc_t)w_one)
- {
- result= 1; /* Found an anchor char */
- }
- else
- {
- if (weights)
- {
- plane=(s_wc>>8) & 0xFF;
- s_wc = weights[plane] ? weights[plane][s_wc & 0xFF].sort : s_wc;
- plane=(w_wc>>8) & 0xFF;
- w_wc = weights[plane] ? weights[plane][w_wc & 0xFF].sort : w_wc;
- }
- if (s_wc != w_wc)
- return 1; /* No match */
- }
- if (wildstr == wildend)
- return (str != str_end); /* Match if both are at end */
- }
-
-
- if (w_wc == (my_wc_t)w_many)
- { /* Found w_many */
-
- /* Remove any '%' and '_' from the wild search string */
- for ( ; wildstr != wildend ; )
- {
- scan= my_ucs2_uni(cs,&w_wc, (const uchar*)wildstr,
- (const uchar*)wildend);
- if (scan <= 0)
- return 1;
-
- if (w_wc == (my_wc_t)w_many)
- {
- wildstr+= scan;
- continue;
- }
-
- if (w_wc == (my_wc_t)w_one)
- {
- wildstr+= scan;
- scan= my_ucs2_uni(cs, &s_wc, (const uchar*)str,
- (const uchar*)str_end);
- if (scan <=0)
- return 1;
- str+= scan;
- continue;
- }
- break; /* Not a wild character */
- }
-
- if (wildstr == wildend)
- return 0; /* Ok if w_many is last */
-
- if (str == str_end)
- return -1;
-
- scan= my_ucs2_uni(cs,&w_wc, (const uchar*)wildstr,
- (const uchar*)wildend);
- if (scan <= 0)
- return 1;
-
- if (w_wc == (my_wc_t)escape)
- {
- wildstr+= scan;
- scan= my_ucs2_uni(cs,&w_wc, (const uchar*)wildstr,
- (const uchar*)wildend);
- if (scan <= 0)
- return 1;
- }
-
- while (1)
- {
- /* Skip until the first character from wildstr is found */
- while (str != str_end)
- {
- scan= my_ucs2_uni(cs,&s_wc, (const uchar*)str,
- (const uchar*)str_end);
- if (scan <= 0)
- return 1;
- if (weights)
- {
- plane=(s_wc>>8) & 0xFF;
- s_wc = weights[plane] ? weights[plane][s_wc & 0xFF].sort : s_wc;
- plane=(w_wc>>8) & 0xFF;
- w_wc = weights[plane] ? weights[plane][w_wc & 0xFF].sort : w_wc;
- }
-
- if (s_wc == w_wc)
- break;
- str+= scan;
- }
- if (str == str_end)
- return -1;
-
- result= my_wildcmp_ucs2(cs,str,str_end,wildstr,wildend,escape,
- w_one,w_many,weights);
-
- if (result <= 0)
- return result;
-
- str+= scan;
- }
- }
- }
- return (str != str_end ? 1 : 0);
-}
-
-
static
int my_wildcmp_ucs2_ci(CHARSET_INFO *cs,
const char *str,const char *str_end,
const char *wildstr,const char *wildend,
int escape, int w_one, int w_many)
{
- return my_wildcmp_ucs2(cs,str,str_end,wildstr,wildend,
- escape,w_one,w_many,uni_plane);
+ return my_wildcmp_unicode(cs,str,str_end,wildstr,wildend,
+ escape,w_one,w_many,uni_plane);
}
@@ -1406,8 +1248,8 @@ int my_wildcmp_ucs2_bin(CHARSET_INFO *cs,
const char *wildstr,const char *wildend,
int escape, int w_one, int w_many)
{
- return my_wildcmp_ucs2(cs,str,str_end,wildstr,wildend,
- escape,w_one,w_many,NULL);
+ return my_wildcmp_unicode(cs,str,str_end,wildstr,wildend,
+ escape,w_one,w_many,NULL);
}
diff --git a/strings/ctype-utf8.c b/strings/ctype-utf8.c
index fd6610b72b1..3ca6c5d279f 100644
--- a/strings/ctype-utf8.c
+++ b/strings/ctype-utf8.c
@@ -1518,6 +1518,161 @@ MY_UNICASE_INFO *uni_plane[256]={
};
+
+/*
+** Compare string against string with wildcard
+** This function is used in UTF8 and UCS2
+**
+** 0 if matched
+** -1 if not matched with wildcard
+** 1 if matched with wildcard
+*/
+
+int my_wildcmp_unicode(CHARSET_INFO *cs,
+ const char *str,const char *str_end,
+ const char *wildstr,const char *wildend,
+ int escape, int w_one, int w_many,
+ MY_UNICASE_INFO **weights)
+{
+ int result= -1; /* Not found, using wildcards */
+ my_wc_t s_wc, w_wc;
+ int scan, plane;
+ int (*mb_wc)(struct charset_info_st *cs, my_wc_t *wc,
+ const unsigned char *s,const unsigned char *e);
+ mb_wc= cs->cset->mb_wc;
+
+ while (wildstr != wildend)
+ {
+ while (1)
+ {
+ if ((scan= mb_wc(cs, &w_wc, (const uchar*)wildstr,
+ (const uchar*)wildend)) <= 0)
+ return 1;
+
+ if (w_wc == (my_wc_t)escape)
+ {
+ wildstr+= scan;
+ if ((scan= mb_wc(cs,&w_wc, (const uchar*)wildstr,
+ (const uchar*)wildend)) <= 0)
+ return 1;
+ }
+
+ if (w_wc == (my_wc_t)w_many)
+ {
+ result= 1; /* Found an anchor char */
+ break;
+ }
+
+ wildstr+= scan;
+ if ((scan= mb_wc(cs, &s_wc, (const uchar*)str,
+ (const uchar*)str_end)) <=0)
+ return 1;
+ str+= scan;
+
+ if (w_wc == (my_wc_t)w_one)
+ {
+ result= 1; /* Found an anchor char */
+ }
+ else
+ {
+ if (weights)
+ {
+ plane=(s_wc>>8) & 0xFF;
+ s_wc = weights[plane] ? weights[plane][s_wc & 0xFF].sort : s_wc;
+ plane=(w_wc>>8) & 0xFF;
+ w_wc = weights[plane] ? weights[plane][w_wc & 0xFF].sort : w_wc;
+ }
+ if (s_wc != w_wc)
+ return 1; /* No match */
+ }
+ if (wildstr == wildend)
+ return (str != str_end); /* Match if both are at end */
+ }
+
+
+ if (w_wc == (my_wc_t)w_many)
+ { /* Found w_many */
+
+ /* Remove any '%' and '_' from the wild search string */
+ for ( ; wildstr != wildend ; )
+ {
+ if ((scan= mb_wc(cs, &w_wc, (const uchar*)wildstr,
+ (const uchar*)wildend)) <= 0)
+ return 1;
+
+ if (w_wc == (my_wc_t)w_many)
+ {
+ wildstr+= scan;
+ continue;
+ }
+
+ if (w_wc == (my_wc_t)w_one)
+ {
+ wildstr+= scan;
+ if ((scan= mb_wc(cs, &s_wc, (const uchar*)str,
+ (const uchar*)str_end)) <=0)
+ return 1;
+ str+= scan;
+ continue;
+ }
+ break; /* Not a wild character */
+ }
+
+ if (wildstr == wildend)
+ return 0; /* Ok if w_many is last */
+
+ if (str == str_end)
+ return -1;
+
+ if ((scan= mb_wc(cs, &w_wc, (const uchar*)wildstr,
+ (const uchar*)wildend)) <=0)
+ return 1;
+
+ if (w_wc == (my_wc_t)escape)
+ {
+ wildstr+= scan;
+ if ((scan= mb_wc(cs, &w_wc, (const uchar*)wildstr,
+ (const uchar*)wildend)) <=0)
+ return 1;
+ }
+
+ while (1)
+ {
+ /* Skip until the first character from wildstr is found */
+ while (str != str_end)
+ {
+ if ((scan= mb_wc(cs, &s_wc, (const uchar*)str,
+ (const uchar*)str_end)) <=0)
+ return 1;
+ if (weights)
+ {
+ plane=(s_wc>>8) & 0xFF;
+ s_wc = weights[plane] ? weights[plane][s_wc & 0xFF].sort : s_wc;
+ plane=(w_wc>>8) & 0xFF;
+ w_wc = weights[plane] ? weights[plane][w_wc & 0xFF].sort : w_wc;
+ }
+
+ if (s_wc == w_wc)
+ break;
+ str+= scan;
+ }
+ if (str == str_end)
+ return -1;
+
+ result= my_wildcmp_unicode(cs, str, str_end, wildstr, wildend,
+ escape, w_one, w_many,
+ weights);
+
+ if (result <= 0)
+ return result;
+
+ str+= scan;
+ }
+ }
+ }
+ return (str != str_end ? 1 : 0);
+}
+
#endif
@@ -1948,50 +2103,120 @@ static int my_strnncollsp_utf8(CHARSET_INFO *cs,
}
-static int my_strncasecmp_utf8(CHARSET_INFO *cs,
- const char *s, const char *t, uint len)
-{
- int s_res,t_res;
- my_wc_t s_wc,t_wc;
- const char *se=s+len;
- const char *te=t+len;
+/*
+ Compare 0-terminated UTF8 strings.
- while ( s < se && t < te )
- {
- int plane;
+ SYNOPSIS
+ my_strcasecmp_utf8()
+ cs character set handler
+ s First 0-terminated string to compare
+ t Second 0-terminated string to compare
- s_res=my_utf8_uni(cs,&s_wc, (const uchar*)s, (const uchar*)se);
- t_res=my_utf8_uni(cs,&t_wc, (const uchar*)t, (const uchar*)te);
+ IMPLEMENTATION
- if ( s_res <= 0 || t_res <= 0 )
+ RETURN
+ - negative number if s < t
+ - positive number if s > t
+ - 0 is the strings are equal
+*/
+
+static
+int my_strcasecmp_utf8(CHARSET_INFO *cs, const char *s, const char *t)
+{
+ while (s[0] && t[0])
+ {
+ my_wc_t s_wc,t_wc;
+
+ /*
+ Cast to int8 for extra safety.
+ char can be unsigned by default
+ on some platforms.
+ */
+ if (((int8)s[0]) >= 0)
{
- /* Incorrect string, compare byte by byte value */
- return bincmp(s, se, t, te);
+ /*
+ s[0] is between 0 and 127.
+ It represents a single byte character.
+ Convert it into weight according to collation.
+ */
+ s_wc= plane00[(uchar) s[0]].tolower;
+ s++;
}
-
- plane=(s_wc>>8) & 0xFF;
- s_wc = uni_plane[plane] ? uni_plane[plane][s_wc & 0xFF].tolower : s_wc;
-
- plane=(t_wc>>8) & 0xFF;
- t_wc = uni_plane[plane] ? uni_plane[plane][t_wc & 0xFF].tolower : t_wc;
-
+ else
+ {
+ int plane, res;
+
+ /*
+ Scan a multibyte character.
+
+ In the future it is worth to write a special version of my_utf8_uni()
+ for 0-terminated strings which will not take in account length. Now
+ we call the regular version of my_utf8_uni() with s+3 in the
+ last argument. s+3 is enough to scan any multibyte sequence.
+
+ Calling the regular version of my_utf8_uni is safe for 0-terminated
+ strings: we will never lose the end of the string:
+ If we have 0 character in the middle of a multibyte sequence,
+ then my_utf8_uni will always return a negative number, so the
+ loop with finish.
+ */
+
+ res= my_utf8_uni(cs,&s_wc, (const uchar*)s, (const uchar*) s + 3);
+
+ /*
+ In the case of wrong multibyte sequence we will
+ call strcmp() for byte-to-byte comparison.
+ */
+ if (res <= 0)
+ return strcmp(s, t);
+ s+= res;
+
+ /* Convert Unicode code into weight according to collation */
+ plane=(s_wc>>8) & 0xFF;
+ s_wc = uni_plane[plane] ? uni_plane[plane][s_wc & 0xFF].tolower : s_wc;
+ }
+
+
+ /* Do the same for the second string */
+
+ if (t[0] >= 0)
+ {
+ /* Convert single byte character into weight */
+ t_wc= plane00[(uchar) t[0]].tolower;
+ t++;
+ }
+ else
+ {
+ int plane;
+ int res=my_utf8_uni(cs,&t_wc, (const uchar*)t, (const uchar*) t + 3);
+ if (res <= 0)
+ return strcmp(s, t);
+ t+= res;
+
+ /* Convert code into weight */
+ plane=(t_wc>>8) & 0xFF;
+ t_wc = uni_plane[plane] ? uni_plane[plane][t_wc & 0xFF].tolower : t_wc;
+ }
+
+ /* Now we have two weights, let's compare them */
if ( s_wc != t_wc )
return ((int) s_wc) - ((int) t_wc);
-
- s+=s_res;
- t+=t_res;
}
- return ( (se-s) - (te-t) );
+ return ((int)(uchar)s[0]) - ((int) (uchar) t[0]);
}
-static int my_strcasecmp_utf8(CHARSET_INFO *cs, const char *s, const char *t)
+
+static
+int my_wildcmp_utf8(CHARSET_INFO *cs,
+ const char *str,const char *str_end,
+ const char *wildstr,const char *wildend,
+ int escape, int w_one, int w_many)
{
- uint s_len=strlen(s);
- uint t_len=strlen(t);
- uint len = (s_len > t_len) ? s_len : t_len;
- return my_strncasecmp_utf8(cs, s, t, len);
+ return my_wildcmp_unicode(cs,str,str_end,wildstr,wildend,
+ escape,w_one,w_many,uni_plane);
}
+
static int my_strnxfrm_utf8(CHARSET_INFO *cs,
uchar *dst, uint dstlen,
const uchar *src, uint srclen)
@@ -2060,7 +2285,7 @@ static MY_COLLATION_HANDLER my_collation_ci_handler =
my_strnncollsp_utf8,
my_strnxfrm_utf8,
my_like_range_mb,
- my_wildcmp_mb,
+ my_wildcmp_utf8,
my_strcasecmp_utf8,
my_instr_mb,
my_hash_sort_utf8
diff --git a/strings/xml.c b/strings/xml.c
index 7d7839e1603..6ba52ea41a8 100644
--- a/strings/xml.c
+++ b/strings/xml.c
@@ -81,10 +81,11 @@ static int my_xml_scan(MY_XML_PARSER *p,MY_XML_ATTR *a)
a->beg=p->cur;
a->end=p->cur;
- if (!memcmp(p->cur,"<!--",4))
+ if (!bcmp(p->cur,"<!--",4))
{
- for( ; (p->cur < p->end) && memcmp(p->cur, "-->", 3); p->cur++);
- if(!memcmp(p->cur, "-->", 3))
+ for( ; (p->cur < p->end) && bcmp(p->cur, "-->", 3); p->cur++)
+ {}
+ if (!bcmp(p->cur, "-->", 3))
p->cur+=3;
a->end=p->cur;
lex=MY_XML_COMMENT;
diff --git a/tests/client_test.c b/tests/client_test.c
index 0b30cc3386d..130e0bc3b4f 100644
--- a/tests/client_test.c
+++ b/tests/client_test.c
@@ -26,14 +26,6 @@
#include <mysql.h>
#include <my_getopt.h>
#include <m_string.h>
-#ifdef HAVE_SYS_PARAM_H
-/* Include to get MAXPATHLEN */
-#include <sys/param.h>
-#endif
-
-#ifndef MAXPATHLEN
-#define MAXPATHLEN 256
-#endif
#define MAX_TEST_QUERY_LENGTH 300 /* MAX QUERY BUFFER LENGTH */
@@ -3439,7 +3431,7 @@ static void test_fetch_date()
MYSQL_STMT *stmt;
uint i;
int rc, year;
- char date[25], time[25], ts[25], ts_4[15], ts_6[20], dt[20];
+ char date[25], time[25], ts[25], ts_4[25], ts_6[20], dt[20];
ulong d_length, t_length, ts_length, ts4_length, ts6_length,
dt_length, y_length;
MYSQL_BIND bind[8];
@@ -3549,8 +3541,8 @@ static void test_fetch_date()
DIE_UNLESS(strcmp(dt, "2010-07-10 00:00:00") == 0);
DIE_UNLESS(dt_length == 19);
- DIE_UNLESS(ts_4[0] == '\0');
- DIE_UNLESS(ts4_length == 0);
+ DIE_UNLESS(strcmp(ts_4, "0000-00-00 00:00:00") == 0);
+ DIE_UNLESS(ts4_length == strlen("0000-00-00 00:00:00"));
DIE_UNLESS(strcmp(ts_6, "1999-12-29 00:00:00") == 0);
DIE_UNLESS(ts6_length == 19);
@@ -6652,8 +6644,8 @@ static void test_frm_bug()
MYSQL_RES *result;
MYSQL_ROW row;
FILE *test_file;
- char data_dir[MAXPATHLEN];
- char test_frm[MAXPATHLEN];
+ char data_dir[FN_REFLEN];
+ char test_frm[FN_REFLEN];
int rc;
myheader("test_frm_bug");
@@ -6674,7 +6666,7 @@ static void test_frm_bug()
bind[0].buffer_type= MYSQL_TYPE_STRING;
bind[0].buffer= data_dir;
- bind[0].buffer_length= MAXPATHLEN;
+ bind[0].buffer_length= FN_REFLEN;
bind[0].is_null= 0;
bind[0].length= 0;
bind[1]= bind[0];
@@ -10541,6 +10533,163 @@ static void test_bug5315()
}
+static void test_bug6049()
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND bind[1];
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ const char *stmt_text;
+ char buffer[30];
+ ulong length;
+ int rc;
+
+ myheader("test_bug6049");
+
+ stmt_text= "SELECT MAKETIME(-25, 12, 12)";
+
+ rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
+ myquery(rc);
+ res= mysql_store_result(mysql);
+ row= mysql_fetch_row(res);
+
+ stmt= mysql_stmt_init(mysql);
+ rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
+ check_execute(stmt, rc);
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
+
+ bzero(bind, sizeof(bind));
+ bind[0].buffer_type = MYSQL_TYPE_STRING;
+ bind[0].buffer = &buffer;
+ bind[0].buffer_length = sizeof(buffer);
+ bind[0].length = &length;
+
+ mysql_stmt_bind_result(stmt, bind);
+ rc= mysql_stmt_fetch(stmt);
+ DIE_UNLESS(rc == 0);
+
+ printf("Result from query: %s\n", row[0]);
+ printf("Result from prepared statement: %s\n", (char*) buffer);
+
+ DIE_UNLESS(strcmp(row[0], (char*) buffer) == 0);
+
+ mysql_free_result(res);
+ mysql_stmt_close(stmt);
+}
+
+
+static void test_bug6058()
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND bind[1];
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ const char *stmt_text;
+ char buffer[30];
+ ulong length;
+ int rc;
+
+ myheader("test_bug6058");
+
+ stmt_text= "SELECT CAST('0000-00-00' AS DATE)";
+
+ rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
+ myquery(rc);
+ res= mysql_store_result(mysql);
+ row= mysql_fetch_row(res);
+
+ stmt= mysql_stmt_init(mysql);
+ rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
+ check_execute(stmt, rc);
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
+
+ bzero(bind, sizeof(bind));
+ bind[0].buffer_type = MYSQL_TYPE_STRING;
+ bind[0].buffer = &buffer;
+ bind[0].buffer_length = sizeof(buffer);
+ bind[0].length = &length;
+
+ mysql_stmt_bind_result(stmt, bind);
+ rc= mysql_stmt_fetch(stmt);
+ DIE_UNLESS(rc == 0);
+
+ printf("Result from query: %s\n", row[0]);
+ printf("Result from prepared statement: %s\n", buffer);
+
+ DIE_UNLESS(strcmp(row[0], buffer) == 0);
+
+ mysql_free_result(res);
+ mysql_stmt_close(stmt);
+}
+
+
+static void test_bug6059()
+{
+ MYSQL_STMT *stmt;
+ const char *stmt_text;
+ int rc;
+
+ myheader("test_bug6059");
+
+ stmt_text= "SELECT 'foo' INTO OUTFILE 'x.3'";
+
+ stmt= mysql_stmt_init(mysql);
+ rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
+ DIE_UNLESS(mysql_stmt_field_count(stmt) == 0);
+ mysql_stmt_close(stmt);
+}
+
+
+static void test_bug6046()
+{
+ MYSQL_STMT *stmt;
+ const char *stmt_text;
+ int rc;
+ short b= 1;
+ MYSQL_BIND bind[1];
+
+ myheader("test_bug6046");
+
+ stmt_text= "DROP TABLE IF EXISTS t1";
+ rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
+ myquery(rc);
+ stmt_text= "CREATE TABLE a1 (a int, b int)";
+ rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
+ myquery(rc);
+ stmt_text= "INSERT INTO a1 VALUES (1,1),(2,2),(3,1),(4,2)";
+ rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
+ myquery(rc);
+
+ stmt= mysql_stmt_init(mysql);
+
+ stmt_text= "SELECT a1.a FROM a1 NATURAL JOIN a1 as X1 "
+ "WHERE a1.b > ? ORDER BY a1.a";
+
+ rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
+ check_execute(stmt, rc);
+
+ b= 1;
+ bzero(bind, sizeof(bind));
+ bind[0].buffer= &b;
+ bind[0].buffer_type= MYSQL_TYPE_SHORT;
+
+ mysql_stmt_bind_param(stmt, bind);
+
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
+ mysql_stmt_store_result(stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
+
+ mysql_stmt_close(stmt);
+}
+
+
+
+
/*
Read and parse arguments and MySQL options from my.cnf
*/
@@ -10851,6 +11000,10 @@ int main(int argc, char **argv)
test_bug5194(); /* bulk inserts in prepared mode */
test_bug5315(); /* check that mysql_change_user closes all
prepared statements */
+ test_bug6049(); /* check support for negative TIME values */
+ test_bug6058(); /* check support for 0000-00-00 dates */
+ test_bug6059(); /* correct metadata for SELECT ... INTO OUTFILE */
+ test_bug6046(); /* NATURAL JOIN transformation works in PS */
/*
XXX: PLEASE RUN THIS PROGRAM UNDER VALGRIND AND VERIFY THAT YOUR TEST
DOESN'T CONTAIN WARNINGS/ERRORS BEFORE YOU PUSH.