summaryrefslogtreecommitdiff
path: root/ndb
diff options
context:
space:
mode:
Diffstat (limited to 'ndb')
-rw-r--r--ndb/include/Makefile.am1
-rw-r--r--ndb/include/debugger/EventLogger.hpp7
-rw-r--r--ndb/include/kernel/GlobalSignalNumbers.h11
-rw-r--r--ndb/include/kernel/Interpreter.hpp6
-rw-r--r--ndb/include/kernel/NodeInfo.hpp9
-rw-r--r--ndb/include/kernel/NodeState.hpp21
-rw-r--r--ndb/include/kernel/kernel_config_parameters.h5
-rw-r--r--ndb/include/kernel/ndb_limits.h2
-rw-r--r--ndb/include/kernel/signaldata/CreateFragmentation.hpp2
-rw-r--r--ndb/include/kernel/signaldata/DictTabInfo.hpp6
-rw-r--r--ndb/include/kernel/signaldata/DropTab.hpp3
-rw-r--r--ndb/include/kernel/signaldata/DumpStateOrd.hpp1
-rw-r--r--ndb/include/kernel/signaldata/KeyInfo.hpp1
-rw-r--r--ndb/include/kernel/signaldata/PrepDropTab.hpp6
-rw-r--r--ndb/include/kernel/signaldata/ScanTab.hpp155
-rw-r--r--ndb/include/kernel/signaldata/SignalData.hpp16
-rw-r--r--ndb/include/kernel/signaldata/StartInfo.hpp2
-rw-r--r--ndb/include/kernel/signaldata/TcCommit.hpp1
-rw-r--r--ndb/include/kernel/signaldata/TcKeyReq.hpp1
-rw-r--r--ndb/include/kernel/signaldata/TupAccess.hpp174
-rw-r--r--ndb/include/mgmapi/mgmapi.h15
-rw-r--r--ndb/include/mgmapi/mgmapi_config_parameters.h3
-rw-r--r--ndb/include/mgmapi/mgmapi_debug.h25
-rw-r--r--ndb/include/mgmcommon/ConfigRetriever.hpp45
-rw-r--r--ndb/include/mgmcommon/LocalConfig.hpp (renamed from ndb/src/common/mgmcommon/LocalConfig.hpp)34
-rw-r--r--ndb/include/mgmcommon/MgmtErrorReporter.hpp6
-rw-r--r--ndb/include/mgmcommon/NdbConfig.h13
-rw-r--r--ndb/include/ndb_global.h12
-rw-r--r--ndb/include/ndbapi/Ndb.hpp42
-rw-r--r--ndb/include/ndbapi/NdbApi.hpp2
-rw-r--r--ndb/include/ndbapi/NdbBlob.hpp86
-rw-r--r--ndb/include/ndbapi/NdbConnection.hpp193
-rw-r--r--ndb/include/ndbapi/NdbCursorOperation.hpp73
-rw-r--r--ndb/include/ndbapi/NdbDictionary.hpp13
-rw-r--r--ndb/include/ndbapi/NdbIndexOperation.hpp2
-rw-r--r--ndb/include/ndbapi/NdbIndexScanOperation.hpp140
-rw-r--r--ndb/include/ndbapi/NdbOperation.hpp246
-rw-r--r--ndb/include/ndbapi/NdbRecAttr.hpp50
-rw-r--r--ndb/include/ndbapi/NdbReceiver.hpp67
-rw-r--r--ndb/include/ndbapi/NdbResultSet.hpp54
-rw-r--r--ndb/include/ndbapi/NdbScanOperation.hpp231
-rw-r--r--ndb/include/portlib/NdbTCP.h2
-rw-r--r--ndb/include/transporter/TransporterDefinitions.hpp1
-rw-r--r--ndb/include/transporter/TransporterRegistry.hpp83
-rw-r--r--ndb/include/util/BaseString.hpp2
-rw-r--r--ndb/include/util/Bitmask.hpp171
-rw-r--r--ndb/include/util/ConfigValues.hpp6
-rw-r--r--ndb/include/util/NdbSqlUtil.hpp126
-rw-r--r--ndb/include/util/Properties.hpp2
-rw-r--r--ndb/include/util/SocketAuthenticator.hpp39
-rw-r--r--ndb/include/util/SocketClient.hpp38
-rw-r--r--ndb/src/common/debugger/DebuggerNames.cpp15
-rw-r--r--ndb/src/common/debugger/EventLogger.cpp16
-rw-r--r--ndb/src/common/debugger/SignalLoggerManager.cpp25
-rw-r--r--ndb/src/common/debugger/signaldata/DictTabInfo.cpp2
-rw-r--r--ndb/src/common/debugger/signaldata/LCP.cpp3
-rw-r--r--ndb/src/common/debugger/signaldata/Makefile.am3
-rw-r--r--ndb/src/common/debugger/signaldata/ScanTab.cpp111
-rw-r--r--ndb/src/common/debugger/signaldata/SignalDataPrint.cpp12
-rw-r--r--ndb/src/common/debugger/signaldata/SignalNames.cpp4
-rw-r--r--ndb/src/common/debugger/signaldata/TupAccess.cpp131
-rw-r--r--ndb/src/common/logger/FileLogHandler.cpp4
-rw-r--r--ndb/src/common/logger/Logger.cpp1
-rw-r--r--ndb/src/common/mgmcommon/ConfigInfo.cpp994
-rw-r--r--ndb/src/common/mgmcommon/ConfigInfo.hpp7
-rw-r--r--ndb/src/common/mgmcommon/ConfigRetriever.cpp302
-rw-r--r--ndb/src/common/mgmcommon/IPCConfig.cpp19
-rw-r--r--ndb/src/common/mgmcommon/InitConfigFileParser.cpp45
-rw-r--r--ndb/src/common/mgmcommon/LocalConfig.cpp130
-rw-r--r--ndb/src/common/mgmcommon/NdbConfig.c112
-rw-r--r--ndb/src/common/portlib/Makefile.am2
-rw-r--r--ndb/src/common/portlib/NdbTCP.cpp (renamed from ndb/src/common/portlib/NdbTCP.c)5
-rw-r--r--ndb/src/common/transporter/Packer.cpp14
-rw-r--r--ndb/src/common/transporter/SHM_Transporter.cpp162
-rw-r--r--ndb/src/common/transporter/SHM_Transporter.hpp30
-rw-r--r--ndb/src/common/transporter/SHM_Transporter.unix.cpp124
-rw-r--r--ndb/src/common/transporter/TCP_Transporter.cpp250
-rw-r--r--ndb/src/common/transporter/TCP_Transporter.hpp83
-rw-r--r--ndb/src/common/transporter/Transporter.cpp188
-rw-r--r--ndb/src/common/transporter/Transporter.hpp109
-rw-r--r--ndb/src/common/transporter/TransporterRegistry.cpp450
-rw-r--r--ndb/src/common/util/BaseString.cpp3
-rw-r--r--ndb/src/common/util/ConfigValues.cpp26
-rw-r--r--ndb/src/common/util/Makefile.am3
-rw-r--r--ndb/src/common/util/NdbSqlUtil.cpp22
-rw-r--r--ndb/src/common/util/Parser.cpp1
-rw-r--r--ndb/src/common/util/Properties.cpp39
-rw-r--r--ndb/src/common/util/SocketAuthenticator.cpp91
-rw-r--r--ndb/src/common/util/SocketClient.cpp92
-rw-r--r--ndb/src/common/util/SocketServer.cpp16
-rw-r--r--ndb/src/common/util/socket_io.cpp4
-rw-r--r--ndb/src/cw/cpcd/APIService.cpp2
-rw-r--r--ndb/src/cw/cpcd/CPCD.cpp7
-rw-r--r--ndb/src/cw/cpcd/Makefile.am2
-rw-r--r--ndb/src/cw/cpcd/Monitor.cpp2
-rw-r--r--ndb/src/cw/cpcd/Process.cpp88
-rw-r--r--ndb/src/cw/cpcd/main.cpp1
-rw-r--r--ndb/src/kernel/Makefile.am2
-rw-r--r--ndb/src/kernel/blocks/ERROR_codes.txt6
-rw-r--r--ndb/src/kernel/blocks/backup/Backup.cpp5
-rw-r--r--ndb/src/kernel/blocks/backup/Backup.hpp3
-rw-r--r--ndb/src/kernel/blocks/backup/BackupInit.cpp3
-rw-r--r--ndb/src/kernel/blocks/backup/restore/Restore.cpp20
-rw-r--r--ndb/src/kernel/blocks/backup/restore/Restore.hpp5
-rw-r--r--ndb/src/kernel/blocks/backup/restore/main.cpp9
-rw-r--r--ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp102
-rw-r--r--ndb/src/kernel/blocks/dbacc/Dbacc.hpp5
-rw-r--r--ndb/src/kernel/blocks/dbacc/DbaccInit.cpp6
-rw-r--r--ndb/src/kernel/blocks/dbacc/DbaccMain.cpp203
-rw-r--r--ndb/src/kernel/blocks/dbdict/Dbdict.cpp99
-rw-r--r--ndb/src/kernel/blocks/dbdict/Dbdict.hpp2
-rw-r--r--ndb/src/kernel/blocks/dbdih/Dbdih.hpp4
-rw-r--r--ndb/src/kernel/blocks/dbdih/DbdihInit.cpp8
-rw-r--r--ndb/src/kernel/blocks/dbdih/DbdihMain.cpp251
-rw-r--r--ndb/src/kernel/blocks/dblqh/Dblqh.hpp13
-rw-r--r--ndb/src/kernel/blocks/dblqh/DblqhInit.cpp29
-rw-r--r--ndb/src/kernel/blocks/dblqh/DblqhMain.cpp552
-rw-r--r--ndb/src/kernel/blocks/dbtc/Dbtc.hpp282
-rw-r--r--ndb/src/kernel/blocks/dbtc/DbtcInit.cpp57
-rw-r--r--ndb/src/kernel/blocks/dbtc/DbtcMain.cpp2279
-rw-r--r--ndb/src/kernel/blocks/dbtup/Dbtup.hpp27
-rw-r--r--ndb/src/kernel/blocks/dbtup/DbtupBuffer.cpp292
-rw-r--r--ndb/src/kernel/blocks/dbtup/DbtupDebug.cpp12
-rw-r--r--ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp196
-rw-r--r--ndb/src/kernel/blocks/dbtup/DbtupGen.cpp14
-rw-r--r--ndb/src/kernel/blocks/dbtup/DbtupIndex.cpp286
-rw-r--r--ndb/src/kernel/blocks/dbtup/DbtupLCP.cpp2
-rw-r--r--ndb/src/kernel/blocks/dbtup/DbtupPagMan.cpp16
-rw-r--r--ndb/src/kernel/blocks/dbtup/DbtupSystemRestart.cpp38
-rw-r--r--ndb/src/kernel/blocks/dbtux/Dbtux.hpp164
-rw-r--r--ndb/src/kernel/blocks/dbtux/DbtuxCmp.cpp256
-rw-r--r--ndb/src/kernel/blocks/dbtux/DbtuxDebug.cpp95
-rw-r--r--ndb/src/kernel/blocks/dbtux/DbtuxGen.cpp46
-rw-r--r--ndb/src/kernel/blocks/dbtux/DbtuxMaint.cpp112
-rw-r--r--ndb/src/kernel/blocks/dbtux/DbtuxMeta.cpp7
-rw-r--r--ndb/src/kernel/blocks/dbtux/DbtuxNode.cpp35
-rw-r--r--ndb/src/kernel/blocks/dbtux/DbtuxScan.cpp201
-rw-r--r--ndb/src/kernel/blocks/dbtux/DbtuxSearch.cpp333
-rw-r--r--ndb/src/kernel/blocks/dbtux/DbtuxTree.cpp111
-rw-r--r--ndb/src/kernel/blocks/dbtux/Makefile.am1
-rw-r--r--ndb/src/kernel/blocks/dbtux/Times.txt47
-rw-r--r--ndb/src/kernel/blocks/dbutil/DbUtil.cpp2
-rw-r--r--ndb/src/kernel/blocks/grep/Grep.cpp7
-rw-r--r--ndb/src/kernel/blocks/grep/Grep.hpp15
-rw-r--r--ndb/src/kernel/blocks/grep/GrepInit.cpp2
-rw-r--r--ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp33
-rw-r--r--ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp6
-rw-r--r--ndb/src/kernel/blocks/ndbfs/AsyncFile.hpp2
-rw-r--r--ndb/src/kernel/blocks/ndbfs/Filename.cpp11
-rw-r--r--ndb/src/kernel/blocks/ndbfs/Filename.hpp2
-rw-r--r--ndb/src/kernel/blocks/ndbfs/MemoryChannel.hpp3
-rw-r--r--ndb/src/kernel/blocks/ndbfs/Ndbfs.cpp6
-rw-r--r--ndb/src/kernel/blocks/ndbfs/Pool.hpp1
-rw-r--r--ndb/src/kernel/blocks/qmgr/QmgrMain.cpp22
-rw-r--r--ndb/src/kernel/blocks/suma/Suma.cpp93
-rw-r--r--ndb/src/kernel/blocks/trix/Trix.cpp6
-rw-r--r--ndb/src/kernel/error/ErrorReporter.cpp39
-rw-r--r--ndb/src/kernel/error/ErrorReporter.hpp31
-rw-r--r--ndb/src/kernel/main.cpp (renamed from ndb/src/kernel/Main.cpp)194
-rw-r--r--ndb/src/kernel/vm/ArrayPool.hpp18
-rw-r--r--ndb/src/kernel/vm/Configuration.cpp152
-rw-r--r--ndb/src/kernel/vm/Configuration.hpp6
-rw-r--r--ndb/src/kernel/vm/DataBuffer.hpp2
-rw-r--r--ndb/src/kernel/vm/Emulator.cpp4
-rw-r--r--ndb/src/kernel/vm/MetaData.cpp2
-rw-r--r--ndb/src/kernel/vm/SimulatedBlock.cpp103
-rw-r--r--ndb/src/kernel/vm/SimulatedBlock.hpp28
-rw-r--r--ndb/src/kernel/vm/ThreadConfig.cpp2
-rw-r--r--ndb/src/kernel/vm/TransporterCallback.cpp25
-rw-r--r--ndb/src/mgmapi/Makefile.am2
-rw-r--r--ndb/src/mgmapi/mgmapi.cpp232
-rw-r--r--ndb/src/mgmclient/CommandInterpreter.cpp76
-rw-r--r--ndb/src/mgmclient/CpcClient.cpp8
-rw-r--r--ndb/src/mgmclient/main.cpp13
-rw-r--r--ndb/src/mgmsrv/CommandInterpreter.cpp12
-rw-r--r--ndb/src/mgmsrv/MgmtSrvr.cpp383
-rw-r--r--ndb/src/mgmsrv/MgmtSrvr.hpp33
-rw-r--r--ndb/src/mgmsrv/MgmtSrvrConfig.cpp7
-rw-r--r--ndb/src/mgmsrv/Services.cpp163
-rw-r--r--ndb/src/mgmsrv/Services.hpp5
-rw-r--r--ndb/src/mgmsrv/main.cpp196
-rw-r--r--ndb/src/ndbapi/ClusterMgr.cpp2
-rw-r--r--ndb/src/ndbapi/DictCache.cpp11
-rw-r--r--ndb/src/ndbapi/Makefile.am4
-rw-r--r--ndb/src/ndbapi/Makefile_old13
-rw-r--r--ndb/src/ndbapi/Ndb.cpp196
-rw-r--r--ndb/src/ndbapi/NdbApiSignal.cpp26
-rw-r--r--ndb/src/ndbapi/NdbBlob.cpp291
-rw-r--r--ndb/src/ndbapi/NdbConnection.cpp717
-rw-r--r--ndb/src/ndbapi/NdbConnectionScan.cpp545
-rw-r--r--ndb/src/ndbapi/NdbCursorOperation.cpp6
-rw-r--r--ndb/src/ndbapi/NdbDictionary.cpp99
-rw-r--r--ndb/src/ndbapi/NdbDictionaryImpl.cpp111
-rw-r--r--ndb/src/ndbapi/NdbDictionaryImpl.hpp13
-rw-r--r--ndb/src/ndbapi/NdbEventOperation.cpp2
-rw-r--r--ndb/src/ndbapi/NdbEventOperationImpl.cpp38
-rw-r--r--ndb/src/ndbapi/NdbImpl.hpp11
-rw-r--r--ndb/src/ndbapi/NdbIndexOperation.cpp19
-rw-r--r--ndb/src/ndbapi/NdbLinHash.hpp12
-rw-r--r--ndb/src/ndbapi/NdbOperation.cpp75
-rw-r--r--ndb/src/ndbapi/NdbOperationDefine.cpp121
-rw-r--r--ndb/src/ndbapi/NdbOperationExec.cpp392
-rw-r--r--ndb/src/ndbapi/NdbOperationInt.cpp46
-rw-r--r--ndb/src/ndbapi/NdbOperationScan.cpp587
-rw-r--r--ndb/src/ndbapi/NdbRecAttr.cpp84
-rw-r--r--ndb/src/ndbapi/NdbReceiver.cpp185
-rw-r--r--ndb/src/ndbapi/NdbResultSet.cpp59
-rw-r--r--ndb/src/ndbapi/NdbScanFilter.cpp10
-rw-r--r--ndb/src/ndbapi/NdbScanOperation.cpp1752
-rw-r--r--ndb/src/ndbapi/Ndbif.cpp425
-rw-r--r--ndb/src/ndbapi/Ndbinit.cpp7
-rw-r--r--ndb/src/ndbapi/Ndblist.cpp42
-rw-r--r--ndb/src/ndbapi/ObjectMap.hpp41
-rw-r--r--ndb/src/ndbapi/ScanOperation.txt46
-rw-r--r--ndb/src/ndbapi/TransporterFacade.cpp144
-rw-r--r--ndb/src/ndbapi/TransporterFacade.hpp9
-rw-r--r--ndb/src/ndbapi/ndberror.c7
-rw-r--r--ndb/test/include/HugoOperations.hpp54
-rw-r--r--ndb/test/include/HugoTransactions.hpp33
-rw-r--r--ndb/test/include/NDBT_Table.hpp8
-rw-r--r--ndb/test/include/NDBT_Tables.hpp3
-rw-r--r--ndb/test/include/NDBT_Test.hpp15
-rw-r--r--ndb/test/include/NdbRestarter.hpp5
-rw-r--r--ndb/test/include/UtilTransactions.hpp14
-rw-r--r--ndb/test/ndbapi/Makefile.am7
-rw-r--r--ndb/test/ndbapi/Makefile_old4
-rw-r--r--ndb/test/ndbapi/ScanFunctions.hpp143
-rw-r--r--ndb/test/ndbapi/ScanInterpretTest.hpp52
-rw-r--r--ndb/test/ndbapi/bank/Bank.cpp102
-rw-r--r--ndb/test/ndbapi/bank/BankLoad.cpp12
-rw-r--r--ndb/test/ndbapi/create_tab.cpp5
-rw-r--r--ndb/test/ndbapi/flexAsynch.cpp14
-rw-r--r--ndb/test/ndbapi/flexBench.cpp20
-rw-r--r--ndb/test/ndbapi/flexTT.cpp6
-rw-r--r--ndb/test/ndbapi/old_dirs/testBackup/Makefile1
-rw-r--r--ndb/test/ndbapi/old_dirs/testGrep/Makefile1
-rw-r--r--ndb/test/ndbapi/old_dirs/testGrep/verify/Makefile1
-rw-r--r--ndb/test/ndbapi/testBackup.cpp8
-rw-r--r--ndb/test/ndbapi/testBasic.cpp48
-rw-r--r--ndb/test/ndbapi/testBlobs.cpp636
-rw-r--r--ndb/test/ndbapi/testDataBuffers.cpp10
-rw-r--r--ndb/test/ndbapi/testDeadlock.cpp514
-rw-r--r--ndb/test/ndbapi/testDict.cpp1
-rw-r--r--ndb/test/ndbapi/testGrep.cpp7
-rw-r--r--ndb/test/ndbapi/testIndex.cpp51
-rw-r--r--ndb/test/ndbapi/testNdbApi.cpp3
-rw-r--r--ndb/test/ndbapi/testNodeRestart.cpp2
-rw-r--r--ndb/test/ndbapi/testOIBasic.cpp1023
-rw-r--r--ndb/test/ndbapi/testRestartGci.cpp2
-rw-r--r--ndb/test/ndbapi/testScan.cpp193
-rw-r--r--ndb/test/ndbapi/testScanPerf.cpp (renamed from ndb/test/ndbapi/testScanPerf/testScanPerf.cpp)0
-rw-r--r--ndb/test/ndbapi/testScanPerf/Makefile9
-rw-r--r--ndb/test/ndbapi/testTimeout.cpp235
-rw-r--r--ndb/test/ndbapi/testTransactions.cpp16
-rw-r--r--ndb/test/run-test/Makefile.am16
-rw-r--r--ndb/test/run-test/daily-basic-tests.txt1008
-rw-r--r--ndb/test/run-test/daily-devel-tests.txt204
-rw-r--r--ndb/test/run-test/main.cpp74
-rw-r--r--ndb/test/src/HugoAsynchTransactions.cpp34
-rw-r--r--ndb/test/src/HugoCalculator.cpp10
-rw-r--r--ndb/test/src/HugoOperations.cpp269
-rw-r--r--ndb/test/src/HugoTransactions.cpp327
-rw-r--r--ndb/test/src/NDBT_Table.cpp29
-rw-r--r--ndb/test/src/NDBT_Tables.cpp176
-rw-r--r--ndb/test/src/NDBT_Test.cpp69
-rw-r--r--ndb/test/src/NdbBackup.cpp53
-rw-r--r--ndb/test/src/NdbRestarter.cpp32
-rw-r--r--ndb/test/src/NdbRestarts.cpp12
-rw-r--r--ndb/test/src/UtilTransactions.cpp282
-rw-r--r--ndb/test/tools/cpcc.cpp8
-rw-r--r--ndb/test/tools/create_index.cpp20
-rw-r--r--ndb/test/tools/hugoPkReadRecord.cpp9
-rw-r--r--ndb/tools/delete_all.cpp2
-rw-r--r--ndb/tools/desc.cpp5
-rw-r--r--ndb/tools/select_all.cpp64
-rw-r--r--ndb/tools/select_count.cpp27
-rw-r--r--ndb/tools/waiter.cpp34
277 files changed, 14573 insertions, 11784 deletions
diff --git a/ndb/include/Makefile.am b/ndb/include/Makefile.am
index 2565a78238b..b1b7951f216 100644
--- a/ndb/include/Makefile.am
+++ b/ndb/include/Makefile.am
@@ -23,6 +23,7 @@ ndbapi/NdbReceiver.hpp \
ndbapi/NdbResultSet.hpp \
ndbapi/NdbScanFilter.hpp \
ndbapi/NdbScanOperation.hpp \
+ndbapi/NdbIndexScanOperation.hpp \
ndbapi/ndberror.h
mgmapiinclude_HEADERS = \
diff --git a/ndb/include/debugger/EventLogger.hpp b/ndb/include/debugger/EventLogger.hpp
index c49bd176ee8..6cd6a83e68d 100644
--- a/ndb/include/debugger/EventLogger.hpp
+++ b/ndb/include/debugger/EventLogger.hpp
@@ -73,13 +73,6 @@ public:
~EventLogger();
/**
- * Open/create the eventlog, the default name is 'cluster.log'.
- *
- * @return true if successful.
- */
- bool open();
-
- /**
* Opens/creates the eventlog with the specified filename.
*
* @param aFileName the eventlog filename.
diff --git a/ndb/include/kernel/GlobalSignalNumbers.h b/ndb/include/kernel/GlobalSignalNumbers.h
index 7b70f4c3ac0..8941fa6b381 100644
--- a/ndb/include/kernel/GlobalSignalNumbers.h
+++ b/ndb/include/kernel/GlobalSignalNumbers.h
@@ -84,7 +84,7 @@ extern const GlobalSignalNumber NO_OF_SIGNAL_NAMES;
#define GSN_SCAN_NEXTREQ 28
#define GSN_SCAN_TABCONF 29
-#define GSN_SCAN_TABINFO 30
+// 30 unused
#define GSN_SCAN_TABREF 31
#define GSN_SCAN_TABREQ 32
#define GSN_KEYINFO20 33
@@ -897,12 +897,9 @@ extern const GlobalSignalNumber NO_OF_SIGNAL_NAMES;
#define GSN_TUX_MAINT_CONF 678
#define GSN_TUX_MAINT_REF 679
-/*
- * TUP access
- */
-#define GSN_TUP_READ_ATTRS 680
-#define GSN_TUP_QUERY_TH 712
-#define GSN_TUP_STORE_TH 681
+// not used 680
+// not used 712
+// not used 681
/**
* from mgmtsrvr to NDBCNTR
diff --git a/ndb/include/kernel/Interpreter.hpp b/ndb/include/kernel/Interpreter.hpp
index 2c282be361c..74399f5732e 100644
--- a/ndb/include/kernel/Interpreter.hpp
+++ b/ndb/include/kernel/Interpreter.hpp
@@ -83,7 +83,7 @@ public:
static Uint32 LoadConst64(Uint32 Register); // Value in next 2 words
static Uint32 Add(Uint32 DstReg, Uint32 SrcReg1, Uint32 SrcReg2);
static Uint32 Sub(Uint32 DstReg, Uint32 SrcReg1, Uint32 SrcReg2);
- static Uint32 Branch(Uint32 Inst, Uint32 R1, Uint32 R2);
+ static Uint32 Branch(Uint32 Inst, Uint32 Reg1, Uint32 Reg2);
static Uint32 ExitOK();
/**
@@ -184,8 +184,8 @@ Interpreter::Sub(Uint32 Dcoleg, Uint32 SrcReg1, Uint32 SrcReg2){
inline
Uint32
-Interpreter::Branch(Uint32 Inst, Uint32 R1, Uint32 R2){
- return (R1 << 9) + (R2 << 6) + Inst;
+Interpreter::Branch(Uint32 Inst, Uint32 Reg1, Uint32 Reg2){
+ return (Reg1 << 9) + (Reg2 << 6) + Inst;
}
inline
diff --git a/ndb/include/kernel/NodeInfo.hpp b/ndb/include/kernel/NodeInfo.hpp
index 86aca7d6883..5377f001949 100644
--- a/ndb/include/kernel/NodeInfo.hpp
+++ b/ndb/include/kernel/NodeInfo.hpp
@@ -18,6 +18,7 @@
#define NODE_INFO_HPP
#include <NdbOut.hpp>
+#include <mgmapi_config_parameters.h>
class NodeInfo {
public:
@@ -27,10 +28,10 @@ public:
* NodeType
*/
enum NodeType {
- DB = 0, ///< Database node
- API = 1, ///< NDB API node
- MGM = 2, ///< Management node (incl. NDB API)
- REP = 3, ///< Replication node (incl. NDB API)
+ DB = NODE_TYPE_DB, ///< Database node
+ API = NODE_TYPE_API, ///< NDB API node
+ MGM = NODE_TYPE_MGM, ///< Management node (incl. NDB API)
+ REP = NODE_TYPE_REP, ///< Replication node (incl. NDB API)
INVALID = 255 ///< Invalid type
};
NodeType getType() const;
diff --git a/ndb/include/kernel/NodeState.hpp b/ndb/include/kernel/NodeState.hpp
index 1bc7806876d..185e3ea8ea4 100644
--- a/ndb/include/kernel/NodeState.hpp
+++ b/ndb/include/kernel/NodeState.hpp
@@ -18,6 +18,7 @@
#define NODE_STATE_HPP
#include <NdbOut.hpp>
+#include <NodeBitmask.hpp>
class NodeState {
public:
@@ -99,7 +100,7 @@ public:
/**
* Length in 32-bit words
*/
- static const Uint32 DataLength = 8;
+ static const Uint32 DataLength = 8 + NdbNodeBitmask::Size;
/**
* Constructor(s)
@@ -108,7 +109,8 @@ public:
NodeState(StartLevel);
NodeState(StartLevel, bool systemShutdown);
NodeState(StartLevel, Uint32 startPhase, StartType);
-
+ void init();
+
/**
* Current start level
*/
@@ -146,6 +148,8 @@ public:
Uint32 singleUserMode;
Uint32 singleUserApi; //the single user node
+ BitmaskPOD<NdbNodeBitmask::Size> m_connected_nodes;
+
void setDynamicId(Uint32 dynamic);
void setNodeGroup(Uint32 group);
void setSingleUser(Uint32 s);
@@ -177,16 +181,23 @@ public:
inline
NodeState::NodeState(){
+ init();
+}
+
+inline
+void
+NodeState::init(){
startLevel = SL_CMVMI;
nodeGroup = 0xFFFFFFFF;
dynamicId = 0xFFFFFFFF;
singleUserMode = 0;
singleUserApi = 0xFFFFFFFF;
+ m_connected_nodes.clear();
}
inline
NodeState::NodeState(StartLevel sl){
- NodeState::NodeState();
+ init();
startLevel = sl;
singleUserMode = 0;
singleUserApi = 0xFFFFFFFF;
@@ -194,7 +205,7 @@ NodeState::NodeState(StartLevel sl){
inline
NodeState::NodeState(StartLevel sl, Uint32 sp, StartType typeOfStart){
- NodeState::NodeState();
+ init();
startLevel = sl;
starting.startPhase = sp;
starting.restartType = typeOfStart;
@@ -204,7 +215,7 @@ NodeState::NodeState(StartLevel sl, Uint32 sp, StartType typeOfStart){
inline
NodeState::NodeState(StartLevel sl, bool sys){
- NodeState::NodeState();
+ init();
startLevel = sl;
stopping.systemShutdown = sys;
singleUserMode = 0;
diff --git a/ndb/include/kernel/kernel_config_parameters.h b/ndb/include/kernel/kernel_config_parameters.h
index 2f63efa4b6c..bb7c6ebd42c 100644
--- a/ndb/include/kernel/kernel_config_parameters.h
+++ b/ndb/include/kernel/kernel_config_parameters.h
@@ -14,10 +14,7 @@
#define CFG_ACC_SCAN (PRIVATE_BASE + 9)
#define CFG_DICT_ATTRIBUTE (PRIVATE_BASE + 10)
-#define CFG_DICT_CONNECT (PRIVATE_BASE + 11)
-#define CFG_DICT_FRAG_CONNECT (PRIVATE_BASE + 12)
#define CFG_DICT_TABLE (PRIVATE_BASE + 13)
-#define CFG_DICT_TC_CONNECT (PRIVATE_BASE + 14)
#define CFG_DIH_API_CONNECT (PRIVATE_BASE + 15)
#define CFG_DIH_CONNECT (PRIVATE_BASE + 16)
@@ -27,10 +24,8 @@
#define CFG_DIH_TABLE (PRIVATE_BASE + 20)
#define CFG_LQH_FRAG (PRIVATE_BASE + 21)
-#define CFG_LQH_CONNECT (PRIVATE_BASE + 22)
#define CFG_LQH_TABLE (PRIVATE_BASE + 23)
#define CFG_LQH_TC_CONNECT (PRIVATE_BASE + 24)
-#define CFG_LQH_REPLICAS (PRIVATE_BASE + 25)
#define CFG_LQH_LOG_FILES (PRIVATE_BASE + 26)
#define CFG_LQH_SCAN (PRIVATE_BASE + 27)
diff --git a/ndb/include/kernel/ndb_limits.h b/ndb/include/kernel/ndb_limits.h
index 68ffe310328..f35cc617e86 100644
--- a/ndb/include/kernel/ndb_limits.h
+++ b/ndb/include/kernel/ndb_limits.h
@@ -88,7 +88,7 @@
* 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/max prefix each
+#define MAX_TTREE_PREF_SIZE 4 // words in min prefix
#define MAX_TTREE_NODE_SLACK 3 // diff between max and min occupancy
/*
diff --git a/ndb/include/kernel/signaldata/CreateFragmentation.hpp b/ndb/include/kernel/signaldata/CreateFragmentation.hpp
index a2f45a9580d..7d53dd91154 100644
--- a/ndb/include/kernel/signaldata/CreateFragmentation.hpp
+++ b/ndb/include/kernel/signaldata/CreateFragmentation.hpp
@@ -88,7 +88,7 @@ class CreateFragmentationConf {
friend bool printCREATE_FRAGMENTATION_CONF(FILE *,
const Uint32 *, Uint32, Uint16);
public:
- STATIC_CONST( SignalLength = 3 );
+ STATIC_CONST( SignalLength = 4 );
SECTION( FRAGMENTS = 0 );
private:
diff --git a/ndb/include/kernel/signaldata/DictTabInfo.hpp b/ndb/include/kernel/signaldata/DictTabInfo.hpp
index 67610f9d2be..dec7145c897 100644
--- a/ndb/include/kernel/signaldata/DictTabInfo.hpp
+++ b/ndb/include/kernel/signaldata/DictTabInfo.hpp
@@ -100,6 +100,7 @@ public:
CustomTriggerId = 25,
FrmLen = 26,
FrmData = 27,
+ FragmentCount = 128, // No of fragments in table (!fragment replicas)
TableEnd = 999,
AttributeName = 1000, // String, Mandatory
@@ -277,6 +278,7 @@ public:
Uint32 CustomTriggerId;
Uint32 FrmLen;
char FrmData[MAX_FRM_DATA_SIZE];
+ Uint32 FragmentCount;
void init();
};
@@ -309,7 +311,7 @@ public:
ExtDatetime = NdbSqlUtil::Type::Datetime,
ExtTimespec = NdbSqlUtil::Type::Timespec,
ExtBlob = NdbSqlUtil::Type::Blob,
- ExtClob = NdbSqlUtil::Type::Clob
+ ExtText = NdbSqlUtil::Type::Text
};
// Attribute data interpretation
@@ -433,7 +435,7 @@ public:
AttributeArraySize = 12 * AttributeExtLength;
return true;
case DictTabInfo::ExtBlob:
- case DictTabInfo::ExtClob:
+ case DictTabInfo::ExtText:
AttributeType = DictTabInfo::StringType;
AttributeSize = DictTabInfo::an8Bit;
// head + inline part [ attr precision ]
diff --git a/ndb/include/kernel/signaldata/DropTab.hpp b/ndb/include/kernel/signaldata/DropTab.hpp
index 906f952d852..dd3946d8cc0 100644
--- a/ndb/include/kernel/signaldata/DropTab.hpp
+++ b/ndb/include/kernel/signaldata/DropTab.hpp
@@ -101,7 +101,8 @@ public:
NoSuchTable = 1,
DropWoPrep = 2, // Calling Drop with first calling PrepDrop
PrepDropInProgress = 3,
- DropInProgress = 4
+ DropInProgress = 4,
+ NF_FakeErrorREF = 5
};
private:
diff --git a/ndb/include/kernel/signaldata/DumpStateOrd.hpp b/ndb/include/kernel/signaldata/DumpStateOrd.hpp
index 6403a52926f..1e349fad55a 100644
--- a/ndb/include/kernel/signaldata/DumpStateOrd.hpp
+++ b/ndb/include/kernel/signaldata/DumpStateOrd.hpp
@@ -94,6 +94,7 @@ public:
TcDumpOneApiConnectRec = 2505,
TcDumpAllApiConnectRec = 2506,
TcSetTransactionTimeout = 2507,
+ TcSetApplTransactionTimeout = 2508,
CmvmiDumpConnections = 2600,
CmvmiDumpLongSignalMemory = 2601,
CmvmiSetRestartOnErrorInsert = 2602,
diff --git a/ndb/include/kernel/signaldata/KeyInfo.hpp b/ndb/include/kernel/signaldata/KeyInfo.hpp
index b839a2c2035..a4c698f89b2 100644
--- a/ndb/include/kernel/signaldata/KeyInfo.hpp
+++ b/ndb/include/kernel/signaldata/KeyInfo.hpp
@@ -25,6 +25,7 @@ class KeyInfo {
*/
friend class DbUtil;
friend class NdbOperation;
+ friend class NdbScanOperation;
/**
* Reciver(s)
diff --git a/ndb/include/kernel/signaldata/PrepDropTab.hpp b/ndb/include/kernel/signaldata/PrepDropTab.hpp
index e9cc28fed0c..c54b2474aa3 100644
--- a/ndb/include/kernel/signaldata/PrepDropTab.hpp
+++ b/ndb/include/kernel/signaldata/PrepDropTab.hpp
@@ -88,7 +88,8 @@ public:
NoSuchTable = 1,
PrepDropInProgress = 2,
DropInProgress = 3,
- InvalidTableState = 4
+ InvalidTableState = 4,
+ NF_FakeErrorREF = 5
};
private:
@@ -137,7 +138,8 @@ public:
enum ErrorCode {
NoSuchTable = 1,
IllegalTableState = 2,
- DropInProgress = 3
+ DropInProgress = 3,
+ NF_FakeErrorREF = 4
};
Uint32 tableId;
diff --git a/ndb/include/kernel/signaldata/ScanTab.hpp b/ndb/include/kernel/signaldata/ScanTab.hpp
index efd8a4918ab..ab2978e48da 100644
--- a/ndb/include/kernel/signaldata/ScanTab.hpp
+++ b/ndb/include/kernel/signaldata/ScanTab.hpp
@@ -33,8 +33,8 @@ class ScanTabReq {
/**
* Sender(s)
*/
- friend class NdbOperation;
friend class NdbConnection;
+ friend class NdbScanOperation;
/**
* For printing
@@ -73,6 +73,7 @@ private:
static Uint8 getHoldLockFlag(const UintR & requestInfo);
static Uint8 getReadCommittedFlag(const UintR & requestInfo);
static Uint8 getRangeScanFlag(const UintR & requestInfo);
+ static Uint8 getScanBatch(const UintR & requestInfo);
/**
* Set:ers for requestInfo
@@ -83,7 +84,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 setScanBatch(Uint32& requestInfo, Uint32 sz);
};
/**
@@ -94,10 +95,11 @@ private:
h = Hold lock mode - 1 Bit 10
c = Read Committed - 1 Bit 11
x = Range Scan (TUX) - 1 Bit 15
+ b = Scan batch - 5 Bit 16-19 (max 15)
1111111111222222222233
01234567890123456789012345678901
- ppppppppl hc x
+ ppppppppl hc xbbbbb
*/
#define PARALLELL_SHIFT (0)
@@ -115,6 +117,9 @@ private:
#define RANGE_SCAN_SHIFT (15)
#define RANGE_SCAN_MASK (1)
+#define SCAN_BATCH_SHIFT (16)
+#define SCAN_BATCH_MASK (31)
+
inline
Uint8
ScanTabReq::getParallelism(const UintR & requestInfo){
@@ -146,6 +151,12 @@ ScanTabReq::getRangeScanFlag(const UintR & requestInfo){
}
inline
+Uint8
+ScanTabReq::getScanBatch(const Uint32 & requestInfo){
+ return (Uint8)((requestInfo >> SCAN_BATCH_SHIFT) & SCAN_BATCH_MASK);
+}
+
+inline
void
ScanTabReq::clearRequestInfo(UintR & requestInfo){
requestInfo = 0;
@@ -186,6 +197,12 @@ ScanTabReq::setRangeScanFlag(UintR & requestInfo, Uint32 flag){
requestInfo |= (flag << RANGE_SCAN_SHIFT);
}
+inline
+void
+ScanTabReq::setScanBatch(Uint32 & requestInfo, Uint32 flag){
+ ASSERT_MAX(flag, SCAN_BATCH_MASK, "ScanTabReq::setScanBatch");
+ requestInfo |= (flag << SCAN_BATCH_SHIFT);
+}
/**
*
@@ -213,7 +230,8 @@ public:
* Length of signal
*/
STATIC_CONST( SignalLength = 4 );
-
+ static const Uint32 EndOfData = (1 << 31);
+
private:
// Type definitions
@@ -225,29 +243,15 @@ private:
UintR requestInfo; // DATA 1
UintR transId1; // DATA 2
UintR transId2; // DATA 3
-#if 0
- UintR operLenAndIdx[16]; // DATA 4-19
-
- /**
- * Get:ers for operLenAndIdx
- */
- static Uint32 getLen(const UintR & operLenAndIdx);
- static Uint8 getIdx(const UintR & operLenAndIdx);
-#endif
-
- /**
- * Get:ers for requestInfo
- */
- static Uint8 getOperations(const UintR & reqInfo);
- static Uint8 getScanStatus(const UintR & reqInfo);
-
- /**
- * Set:ers for requestInfo
- */
- static void setOperations(UintR & reqInfo, Uint32 ops);
- static void setScanStatus(UintR & reqInfo, Uint32 stat);
+ struct OpData {
+ Uint32 apiPtrI;
+ Uint32 tcPtrI;
+ Uint32 info;
+ };
+ static Uint32 getLength(Uint32 opDataInfo) { return opDataInfo >> 5; };
+ static Uint32 getRows(Uint32 opDataInfo) { return opDataInfo & 31;}
};
/**
@@ -267,103 +271,6 @@ private:
#define STATUS_SHIFT (8)
#define STATUS_MASK (0xFF)
-inline
-Uint8
-ScanTabConf::getOperations(const UintR & reqInfo){
- return (Uint8)((reqInfo >> OPERATIONS_SHIFT) & OPERATIONS_MASK);
-}
-
-inline
-void
-ScanTabConf::setOperations(UintR & requestInfo, Uint32 ops){
- ASSERT_MAX(ops, OPERATIONS_MASK, "ScanTabConf::setOperations");
- requestInfo |= (ops << OPERATIONS_SHIFT);
-}
-
-inline
-Uint8
-ScanTabConf::getScanStatus(const UintR & reqInfo){
- return (Uint8)((reqInfo >> STATUS_SHIFT) & STATUS_MASK);
-}
-
-inline
-void
-ScanTabConf::setScanStatus(UintR & requestInfo, Uint32 stat){
- ASSERT_MAX(stat, STATUS_MASK, "ScanTabConf::setScanStatus");
- requestInfo |= (stat << STATUS_SHIFT);
-}
-
-
-/**
- *
- * SENDER: Dbtc, API
- * RECIVER: API, Dbtc
- */
-class ScanTabInfo {
- /**
- * Reciver(s) and Sender(s)
- */
- friend class NdbConnection;
- friend class Dbtc;
-
- /**
- * For printing
- */
- friend bool printSCANTABINFO(FILE * output, const Uint32 * theData, Uint32 len, Uint16 receiverBlockNo);
-
-public:
- /**
- * Length of signal
- */
- STATIC_CONST( SignalLength = 17 );
-
-private:
-
- // Type definitions
-
- /**
- * DATA VARIABLES
- */
- UintR apiConnectPtr; // DATA 0
- UintR operLenAndIdx[16]; // DATA 1-16
-
- /**
- * Get:ers for operLenAndIdx
- */
- static Uint32 getLen(const UintR & operLenAndIdx);
- static Uint8 getIdx(const UintR & operLenAndIdx);
-
-};
-
-
-/**
- * Operation length and index
- *
- l = Length of operation - 24 Bits -> Max 16777215 (Bit 0-24)
- i = Index of operation - 7 Bits -> Max 255 (Bit 25-32)
-
- 1111111111222222222233
- 01234567890123456789012345678901
- llllllllllllllllllllllllliiiiiii
-*/
-
-#define LENGTH_SHIFT (0)
-#define LENGTH_MASK (0xFFFFFF)
-
-#define INDEX_SHIFT (24)
-#define INDEX_MASK (0xFF)
-
-inline
-Uint32
-ScanTabInfo::getLen(const UintR & operLenAndIdx){
- return (Uint32)((operLenAndIdx >> LENGTH_SHIFT) & LENGTH_MASK);
-}
-
-inline
-Uint8
-ScanTabInfo::getIdx(const UintR & operLenAndIdx){
- return (Uint8)((operLenAndIdx >> INDEX_SHIFT) & INDEX_MASK);
-}
/**
*
@@ -390,7 +297,7 @@ public:
/**
* Length of signal
*/
- STATIC_CONST( SignalLength = 4 );
+ STATIC_CONST( SignalLength = 5 );
private:
@@ -403,7 +310,7 @@ private:
UintR transId1; // DATA 1
UintR transId2; // DATA 2
UintR errorCode; // DATA 3
- // UintR sendScanNextReqWithClose; // DATA 4
+ UintR closeNeeded; // DATA 4
};
diff --git a/ndb/include/kernel/signaldata/SignalData.hpp b/ndb/include/kernel/signaldata/SignalData.hpp
index 511e7d30c21..6e5748217b2 100644
--- a/ndb/include/kernel/signaldata/SignalData.hpp
+++ b/ndb/include/kernel/signaldata/SignalData.hpp
@@ -21,20 +21,10 @@
#include <ndb_limits.h>
#include <kernel_types.h>
-#ifndef NDB_ASSERT
-#ifdef VM_TRACE
-#define NDB_ASSERT(test, message) { if(!(test)) { printf(message); exit(-1); }}
-#else
-#define NDB_ASSERT(test, message)
-#endif
-#endif
-
-// Useful ASSERT macros...
-#define ASSERT_BOOL(flag, message) NDB_ASSERT( (flag<=1), (message) )
+#define ASSERT_BOOL(flag, message) assert(flag<=1)
#define ASSERT_RANGE(value, min, max, message) \
- NDB_ASSERT((value) >= (min) && (value) <= (max), (message))
-#define ASSERT_MAX(value, max, message) \
- NDB_ASSERT((value) <= (max), (message))
+ assert((value) >= (min) && (value) <= (max))
+#define ASSERT_MAX(value, max, message) assert((value) <= (max))
#define SECTION(x) STATIC_CONST(x)
diff --git a/ndb/include/kernel/signaldata/StartInfo.hpp b/ndb/include/kernel/signaldata/StartInfo.hpp
index da032adba8a..d0850b13ef4 100644
--- a/ndb/include/kernel/signaldata/StartInfo.hpp
+++ b/ndb/include/kernel/signaldata/StartInfo.hpp
@@ -78,7 +78,7 @@ class StartInfoRef {
Uint32 errorCode;
public:
- STATIC_CONST( SignalLength = 2 );
+ STATIC_CONST( SignalLength = 3 );
};
#endif
diff --git a/ndb/include/kernel/signaldata/TcCommit.hpp b/ndb/include/kernel/signaldata/TcCommit.hpp
index 43eb7be1c39..b7f3fbbb361 100644
--- a/ndb/include/kernel/signaldata/TcCommit.hpp
+++ b/ndb/include/kernel/signaldata/TcCommit.hpp
@@ -33,6 +33,7 @@ class TcCommitConf {
* Reciver(s)
*/
friend class Ndb;
+ friend class NdbConnection;
public:
STATIC_CONST( SignalLength = 3 );
diff --git a/ndb/include/kernel/signaldata/TcKeyReq.hpp b/ndb/include/kernel/signaldata/TcKeyReq.hpp
index df0a00da3e0..f7d3c2e3282 100644
--- a/ndb/include/kernel/signaldata/TcKeyReq.hpp
+++ b/ndb/include/kernel/signaldata/TcKeyReq.hpp
@@ -38,6 +38,7 @@ class TcKeyReq {
friend class Ndbcntr;
friend class NdbOperation;
friend class NdbIndexOperation;
+ friend class NdbScanOperation;
friend class DbUtil;
/**
diff --git a/ndb/include/kernel/signaldata/TupAccess.hpp b/ndb/include/kernel/signaldata/TupAccess.hpp
deleted file mode 100644
index ab56a73322c..00000000000
--- a/ndb/include/kernel/signaldata/TupAccess.hpp
+++ /dev/null
@@ -1,174 +0,0 @@
-/* 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 TUP_ACCESS_HPP
-#define TUP_ACCESS_HPP
-
-#include "SignalData.hpp"
-
-/*
- * Direct signals used by ACC and TUX to access the TUP block in the
- * same thread.
- *
- * NOTE: Caller must set errorCode to RNIL. Signal printer uses this to
- * distinguish between input and output (no better way exists).
- */
-
-/*
- * Read attributes from any table.
- */
-class TupReadAttrs {
- friend class Dbtup;
- friend class Dbacc;
- friend class Dbtux;
- friend bool printTUP_READ_ATTRS(FILE*, const Uint32*, Uint32, Uint16);
-public:
- enum Flag {
- /*
- * Read primary key attributes. No input attribute ids are
- * specified. Instead TUP fills in both input and output sections.
- * Tuple version is not used.
- */
- ReadKeys = (1 << 0)
- };
- STATIC_CONST( SignalLength = 10 );
-private:
- /*
- * Error code set by TUP. Zero means no error.
- */
- Uint32 errorCode;
- /*
- * Request info contains flags (see Flags above).
- */
- Uint32 requestInfo;
- /*
- * Table i-value.
- */
- Uint32 tableId;
- /*
- * Fragment is given by logical id within the table or by direct
- * i-value (faster). Unknown values are given as RNIL. On return TUP
- * fills in both values.
- */
- Uint32 fragId;
- Uint32 fragPtrI;
- /*
- * Logical address ("local key") of "original" tuple (the latest
- * version) consisting of logical fragment page id and tuple index
- * within the page (shifted left by 1).
- */
- Uint32 tupAddr;
- /*
- * Version of the tuple to read. Not used if ReadKeys.
- */
- Uint32 tupVersion;
- /*
- * Real page id and offset of the "original" tuple. Unknown page is
- * given as RNIL. On return TUP fills in these.
- */
- Uint32 pageId;
- Uint32 pageOffset;
- /*
- * Shared buffer id. Currently must be 0 which means to use rest of
- * signal data.
- */
- Uint32 bufferId;
- /*
- * Shared buffer 0 starts after signal class. Input is number of
- * attributes and list of attribute ids in AttributeHeader format.
- * Output is placed after the input and consists of a list of entries
- * where each entry has an AttributeHeader followed by words of data.
- */
-};
-
-/*
- * Query status of tuple version. Used by TUX to decide if a tuple
- * version found in index tree is visible to the transaction.
- */
-class TupQueryTh {
- friend class Dbtup;
- friend class Dbtux;
- friend bool printTUP_QUERY_TH(FILE*, const Uint32*, Uint32, Uint16);
-public:
- enum Flag {
- };
- STATIC_CONST( SignalLength = 7 );
-private:
- /*
- TUX wants to check if tuple is visible to the scan query.
- Input data is tuple address (tableId, fragId, tupAddr, tupVersion),
- and transaction data so that TUP knows how to deduct if tuple is
- visible (transId1, transId2, savePointId).
- returnCode is set in return signal to indicate whether tuple is visible.
- */
- union {
- Uint32 returnCode; // 1 if tuple visible
- Uint32 tableId;
- };
- Uint32 fragId;
- Uint32 tupAddr;
- Uint32 tupVersion;
- Uint32 transId1;
- Uint32 transId2;
- Uint32 savePointId;
-};
-
-/*
- * Operate on entire tuple. Used by TUX where the table has a single
- * Uint32 array attribute representing an index tree node.
- *
- * XXX this signal is no longer used by TUX and can be removed
- */
-class TupStoreTh {
- friend class Dbtup;
- friend class Dbtux;
- friend bool printTUP_STORE_TH(FILE*, const Uint32*, Uint32, Uint16);
-public:
- enum OpCode {
- OpUndefined = 0,
- OpRead = 1,
- OpInsert = 2,
- OpUpdate = 3,
- OpDelete = 4
- };
- STATIC_CONST( SignalLength = 12 );
-private:
- /*
- * These are as in TupReadAttrs (except opCode). Version must be
- * zero. Ordered index tuple (tree node) has only current version.
- */
- Uint32 errorCode;
- Uint32 opCode;
- Uint32 tableId;
- Uint32 fragId;
- Uint32 fragPtrI;
- Uint32 tupAddr;
- Uint32 tupVersion;
- Uint32 pageId;
- Uint32 pageOffset;
- Uint32 bufferId;
- /*
- * Data offset and size in words. Applies to both the buffer and the
- * tuple. Used e.g. to read only node header.
- */
- Uint32 dataOffset;
- Uint32 dataSize;
- /*
- * Shared buffer 0 starts after signal class.
- */
-};
-
-#endif
diff --git a/ndb/include/mgmapi/mgmapi.h b/ndb/include/mgmapi/mgmapi.h
index 7b2f728bda8..123297b0d71 100644
--- a/ndb/include/mgmapi/mgmapi.h
+++ b/ndb/include/mgmapi/mgmapi.h
@@ -49,6 +49,8 @@
* @{
*/
+#include "mgmapi_config_parameters.h"
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -81,10 +83,10 @@ extern "C" {
*/
enum ndb_mgm_node_type {
NDB_MGM_NODE_TYPE_UNKNOWN = -1, /*/< Node type not known*/
- NDB_MGM_NODE_TYPE_API = 0, /*/< An application node (API)*/
- NDB_MGM_NODE_TYPE_NDB = 1, /*/< A database node (DB)*/
- NDB_MGM_NODE_TYPE_MGM = 2, /*/< A management server node (MGM)*/
- NDB_MGM_NODE_TYPE_REP = 3, ///< A replication node
+ 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*/
@@ -666,6 +668,11 @@ extern "C" {
*/
struct ndb_mgm_configuration * ndb_mgm_get_configuration(NdbMgmHandle handle,
unsigned version);
+
+ int ndb_mgm_alloc_nodeid(NdbMgmHandle handle,
+ unsigned version,
+ unsigned *pnodeid,
+ int nodetype);
/**
* Config iterator
*/
diff --git a/ndb/include/mgmapi/mgmapi_config_parameters.h b/ndb/include/mgmapi/mgmapi_config_parameters.h
index d3bb44c1523..3eca49055fe 100644
--- a/ndb/include/mgmapi/mgmapi_config_parameters.h
+++ b/ndb/include/mgmapi/mgmapi_config_parameters.h
@@ -6,6 +6,7 @@
#define CFG_SYS_PRIMARY_MGM_NODE 1
#define CFG_SYS_CONFIG_GENERATION 2
#define CFG_SYS_REPLICATION_ROLE 7
+#define CFG_SYS_PORT_BASE 8
#define CFG_NODE_ID 3
#define CFG_NODE_BYTE_ORDER 4
@@ -87,11 +88,11 @@
#define CFG_CONNECTION_CHECKSUM 403
#define CFG_CONNECTION_NODE_1_SYSTEM 404
#define CFG_CONNECTION_NODE_2_SYSTEM 405
+#define CFG_CONNECTION_SERVER_PORT 406
#define CFG_TCP_HOSTNAME_1 450
#define CFG_TCP_HOSTNAME_2 451
#define CFG_TCP_SERVER 452
-#define CFG_TCP_SERVER_PORT 453
#define CFG_TCP_SEND_BUFFER_SIZE 454
#define CFG_TCP_RECEIVE_BUFFER_SIZE 455
#define CFG_TCP_PROXY 456
diff --git a/ndb/include/mgmapi/mgmapi_debug.h b/ndb/include/mgmapi/mgmapi_debug.h
index 2723263e7a7..1c562cd164f 100644
--- a/ndb/include/mgmapi/mgmapi_debug.h
+++ b/ndb/include/mgmapi/mgmapi_debug.h
@@ -106,6 +106,31 @@ extern "C" {
struct ndb_mgm_reply* reply);
+ /**
+ *
+ * @param handle the NDB management handle.
+ * @param nodeId the node id. 0 = all db nodes
+ * @param errrorCode the errorCode.
+ * @param reply the reply message.
+ * @return 0 if successful or an error code.
+ */
+ int ndb_mgm_set_int_parameter(NdbMgmHandle handle,
+ int node,
+ int param,
+ unsigned value,
+ struct ndb_mgm_reply* reply);
+
+ int ndb_mgm_set_int64_parameter(NdbMgmHandle handle,
+ int node,
+ int param,
+ unsigned long long value,
+ struct ndb_mgm_reply* reply);
+
+ int ndb_mgm_set_string_parameter(NdbMgmHandle handle,
+ int node,
+ int param,
+ const char * value,
+ struct ndb_mgm_reply* reply);
#ifdef __cplusplus
}
#endif
diff --git a/ndb/include/mgmcommon/ConfigRetriever.hpp b/ndb/include/mgmcommon/ConfigRetriever.hpp
index 50d333b54dd..396ce24308c 100644
--- a/ndb/include/mgmcommon/ConfigRetriever.hpp
+++ b/ndb/include/mgmcommon/ConfigRetriever.hpp
@@ -19,6 +19,8 @@
#include <ndb_types.h>
#include <mgmapi.h>
+#include <BaseString.hpp>
+#include <LocalConfig.hpp>
/**
* @class ConfigRetriever
@@ -26,15 +28,16 @@
*/
class ConfigRetriever {
public:
- ConfigRetriever();
- ConfigRetriever(const int id, const char* remoteHost, const int port);
+ ConfigRetriever(Uint32 version, Uint32 nodeType);
~ConfigRetriever();
/**
* Read local config
* @return Own node id, -1 means fail
*/
- int init(bool onlyNodeId = false);
+ int init();
+
+ int do_connect();
/**
* Get configuration for current (nodeId given in local config file) node.
@@ -47,7 +50,7 @@ public:
* @return ndb_mgm_configuration object if succeeded,
* NULL if erroneous local config file or configuration error.
*/
- struct ndb_mgm_configuration * getConfig(int versionId, int nodeType);
+ struct ndb_mgm_configuration * getConfig();
const char * getErrorString();
@@ -62,28 +65,21 @@ public:
void setLocalConfigFileName(const char * connectString);
/**
- * Sets connectstring which can be used instead of local config file
- * environment variables and Ndb.cfg has precidence over this
- */
- void setDefaultConnectString(const char * defaultConnectString);
-
- /**
* @return Node id of this node (as stated in local config or connectString)
*/
- inline Uint32 getOwnNodeId() { return _ownNodeId; }
-
+ Uint32 allocNodeId();
/**
* Get config using socket
*/
- struct ndb_mgm_configuration * getConfig(const char * mgmhost, short port,
- int versionId);
+ struct ndb_mgm_configuration * getConfig(NdbMgmHandle handle);
+
/**
* Get config from file
*/
- struct ndb_mgm_configuration * getConfig(const char * file, int versionId);
+ struct ndb_mgm_configuration * getConfig(const char * file);
private:
- char * errorString;
+ BaseString errorString;
enum ErrorType {
CR_ERROR = 0,
CR_RETRY = 1
@@ -91,18 +87,21 @@ private:
ErrorType latestErrorType;
void setError(ErrorType, const char * errorMsg);
-
- char * _localConfigFileName;
- struct LocalConfig * _localConfig;
+
+ BaseString _localConfigFileName;
+ struct LocalConfig _localConfig;
int _ownNodeId;
-
- char * m_connectString;
- char * m_defaultConnectString;
+ BaseString m_connectString;
+
+ Uint32 m_version;
+ Uint32 m_node_type;
+ NdbMgmHandle m_handle;
+
/**
* Verify config
*/
- bool verifyConfig(const struct ndb_mgm_configuration *, int type);
+ bool verifyConfig(const struct ndb_mgm_configuration *);
};
#endif
diff --git a/ndb/src/common/mgmcommon/LocalConfig.hpp b/ndb/include/mgmcommon/LocalConfig.hpp
index eb676bf9bed..c741b35f482 100644
--- a/ndb/src/common/mgmcommon/LocalConfig.hpp
+++ b/ndb/include/mgmcommon/LocalConfig.hpp
@@ -32,49 +32,35 @@ enum MgmtSrvrId_Type {
struct MgmtSrvrId {
MgmtSrvrId_Type type;
- union {
- struct {
- char * remoteHost;
- unsigned int port;
- } tcp;
- struct {
- char * filename;
- } file;
- } data;
+ BaseString name;
+ unsigned int port;
};
struct LocalConfig {
int _ownNodeId;
-
- int size;
- int items;
- MgmtSrvrId ** ids;
-
+ Vector<MgmtSrvrId> ids;
+
int error_line;
char error_msg[256];
LocalConfig();
~LocalConfig();
- bool init(bool onlyNodeId = false,
- const char *connectString = 0,
- const char *fileName = 0,
- const char *defaultConnectString = 0);
-
- void add(MgmtSrvrId *i);
+ bool init(const char *connectString = 0,
+ const char *fileName = 0);
void printError() const;
void printUsage() const;
void setError(int lineNumber, const char * _msg);
- bool readConnectString(const char * connectString, bool onlyNodeId = false);
- bool readFile(const char * filename, bool &fopenError, bool onlyNodeId = false);
+ bool readConnectString(const char *);
+ 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, bool onlyNodeId, char *line);
+ bool parseString(const char *buf, char *line);
};
#endif // LocalConfig_H
diff --git a/ndb/include/mgmcommon/MgmtErrorReporter.hpp b/ndb/include/mgmcommon/MgmtErrorReporter.hpp
index 925d9e6407a..0d980aa7245 100644
--- a/ndb/include/mgmcommon/MgmtErrorReporter.hpp
+++ b/ndb/include/mgmcommon/MgmtErrorReporter.hpp
@@ -63,12 +63,6 @@
// Returns: -
//****************************************************************************
-#ifndef NDB_ASSERT
-#define NDB_ASSERT(trueToContinue, message) \
- if ( !(trueToContinue) ) { \
-ndbout << "ASSERT FAILED. FILE: " << __FILE__ << ", LINE: " << __LINE__ << ", MSG: " << message << endl;exit(-1);}
-#endif
-
#define MGM_REQUIRE(x) \
if (!(x)) { ndbout << __FILE__ << " " << __LINE__ \
<< ": Warning! Requirement failed" << endl; }
diff --git a/ndb/include/mgmcommon/NdbConfig.h b/ndb/include/mgmcommon/NdbConfig.h
index d9b484edcc5..5c83a348df2 100644
--- a/ndb/include/mgmcommon/NdbConfig.h
+++ b/ndb/include/mgmcommon/NdbConfig.h
@@ -21,11 +21,14 @@
extern "C" {
#endif
-const char* NdbConfig_HomePath(char* buf, int buflen);
-
-const char* NdbConfig_NdbCfgName(char* buf, int buflen, int with_ndb_home);
-const char* NdbConfig_ErrorFileName(char* buf, int buflen);
-const char* NdbConfig_ClusterLogFileName(char* buf, int buflen);
+char* NdbConfig_NdbCfgName(int with_ndb_home);
+char* NdbConfig_ErrorFileName(int node_id);
+char* NdbConfig_ClusterLogFileName(int node_id);
+char* NdbConfig_SignalLogFileName(int node_id);
+char* NdbConfig_TraceFileName(int node_id, int file_no);
+char* NdbConfig_NextTraceFileName(int node_id);
+char* NdbConfig_PidFileName(int node_id);
+char* NdbConfig_StdoutFileName(int node_id);
#ifdef __cplusplus
}
diff --git a/ndb/include/ndb_global.h b/ndb/include/ndb_global.h
index f871acbc075..b8fcca6dbb1 100644
--- a/ndb/include/ndb_global.h
+++ b/ndb/include/ndb_global.h
@@ -3,6 +3,10 @@
#define NDBGLOBAL_H
#include <my_global.h>
+#define NDB_BASE_PORT 2200
+
+/** signal & SIG_PIPE */
+#include <my_alarm.h>
#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32)
#define NDB_WIN32
@@ -90,6 +94,14 @@ extern int strcasecmp(const char *s1, const char *s2);
extern int strncasecmp(const char *s1, const char *s2, size_t n);
#endif
+#ifdef SCO
+
+#ifndef PATH_MAX
+#define PATH_MAX 1024
+#endif
+
+#endif /* SCO */
+
#ifdef __cplusplus
}
#endif
diff --git a/ndb/include/ndbapi/Ndb.hpp b/ndb/include/ndbapi/Ndb.hpp
index 27da5c3fa39..7904ecef305 100644
--- a/ndb/include/ndbapi/Ndb.hpp
+++ b/ndb/include/ndbapi/Ndb.hpp
@@ -867,6 +867,7 @@ class NdbObjectIdMap;
class NdbOperation;
class NdbEventOperationImpl;
class NdbScanOperation;
+class NdbIndexScanOperation;
class NdbIndexOperation;
class NdbConnection;
class NdbApiSignal;
@@ -875,7 +876,6 @@ class NdbLabel;
class NdbBranch;
class NdbSubroutine;
class NdbCall;
-class NdbScanReceiver;
class Table;
class BaseString;
class NdbEventOperation;
@@ -961,8 +961,9 @@ class Ndb
friend class NdbConnection;
friend class Table;
friend class NdbApiSignal;
- friend class NdbScanReceiver;
friend class NdbIndexOperation;
+ friend class NdbScanOperation;
+ friend class NdbIndexScanOperation;
friend class NdbDictionaryImpl;
friend class NdbDictInterface;
friend class NdbBlob;
@@ -1413,12 +1414,24 @@ public:
*
* @return tuple id or 0 on error
*/
- Uint64 getAutoIncrementValue(const char* aTableName, Uint32 cacheSize = 1);
- bool setAutoIncrementValue(const char* aTableName, Uint64 val);
- Uint64 getTupleIdFromNdb(const char* aTableName, Uint32 cacheSize = 1000 );
- Uint64 getTupleIdFromNdb(Uint32 aTableId, Uint32 cacheSize = 1000 );
- bool setTupleIdInNdb(const char* aTableName, Uint64 val);
- bool setTupleIdInNdb(Uint32 aTableId, Uint64 val);
+ Uint64 getAutoIncrementValue(const char* aTableName,
+ Uint32 cacheSize = 1);
+ Uint64 getAutoIncrementValue(NdbDictionary::Table * aTable,
+ Uint32 cacheSize = 1);
+ Uint64 readAutoIncrementValue(const char* aTableName);
+ Uint64 readAutoIncrementValue(NdbDictionary::Table * aTable);
+ bool setAutoIncrementValue(const char* aTableName, Uint64 val,
+ bool increase = false);
+ bool setAutoIncrementValue(NdbDictionary::Table * aTable, Uint64 val,
+ bool increase = false);
+ Uint64 getTupleIdFromNdb(const char* aTableName,
+ Uint32 cacheSize = 1000);
+ Uint64 getTupleIdFromNdb(Uint32 aTableId,
+ Uint32 cacheSize = 1000);
+ Uint64 readTupleIdFromNdb(Uint32 aTableId);
+ bool setTupleIdInNdb(const char* aTableName, Uint64 val,
+ bool increase);
+ bool setTupleIdInNdb(Uint32 aTableId, Uint64 val, bool increase);
Uint64 opTupleIdOnNdb(Uint32 aTableId, Uint64 opValue, Uint32 op);
#endif
@@ -1441,7 +1454,7 @@ private:
NdbConnection* doConnect(Uint32 nodeId);
void doDisconnect();
- NdbScanReceiver* getNdbScanRec();// Get a NdbScanReceiver from idle list
+ NdbReceiver* getNdbScanRec();// Get a NdbScanReceiver from idle list
NdbLabel* getNdbLabel(); // Get a NdbLabel from idle list
NdbBranch* getNdbBranch(); // Get a NdbBranch from idle list
NdbSubroutine* getNdbSubroutine();// Get a NdbSubroutine from idle
@@ -1450,7 +1463,7 @@ private:
NdbRecAttr* getRecAttr(); // Get a receeive attribute object from
// idle list of the Ndb object.
NdbOperation* getOperation(); // Get an operation from idle list
- NdbScanOperation* getScanOperation(); // Get a scan operation from idle
+ NdbIndexScanOperation* getScanOperation(); // Get a scan operation from idle
NdbIndexOperation* getIndexOperation();// Get an index operation from idle
class NdbGlobalEventBufferHandle* getGlobalEventBufferHandle();
@@ -1458,14 +1471,14 @@ private:
void releaseSignal(NdbApiSignal* anApiSignal);
void releaseSignalsInList(NdbApiSignal** pList);
- void releaseNdbScanRec(NdbScanReceiver* aNdbScanRec);
+ void releaseNdbScanRec(NdbReceiver* aNdbScanRec);
void releaseNdbLabel(NdbLabel* anNdbLabel);
void releaseNdbBranch(NdbBranch* anNdbBranch);
void releaseNdbSubroutine(NdbSubroutine* anNdbSubroutine);
void releaseNdbCall(NdbCall* anNdbCall);
void releaseRecAttr (NdbRecAttr* aRecAttr);
void releaseOperation(NdbOperation* anOperation);
- void releaseScanOperation(NdbScanOperation* aScanOperation);
+ void releaseScanOperation(NdbIndexScanOperation*);
void releaseNdbBlob(NdbBlob* aBlob);
void check_send_timeout();
@@ -1565,7 +1578,6 @@ private:
void* int2void (Uint32 val);
NdbReceiver* void2rec (void* val);
NdbConnection* void2con (void* val);
- NdbScanReceiver* void2rec_srec(void* val);
NdbOperation* void2rec_op (void* val);
NdbIndexOperation* void2rec_iop (void* val);
@@ -1607,7 +1619,7 @@ private:
NdbOperation* theOpIdleList; // First operation in the idle list.
- NdbScanOperation* theScanOpIdleList; // First scan operation in the idle list.
+ NdbIndexScanOperation* theScanOpIdleList; // First scan operation in the idle list.
NdbIndexOperation* theIndexOpIdleList; // First index operation in the idle list.
NdbConnection* theTransactionList;
NdbConnection** theConnectionArray;
@@ -1617,7 +1629,7 @@ private:
NdbBranch* theBranchList; // First branch descriptor in list
NdbSubroutine* theSubroutineList; // First subroutine descriptor in
NdbCall* theCallList; // First call descriptor in list
- NdbScanReceiver* theScanList;
+ NdbReceiver* theScanList;
NdbBlob* theNdbBlobIdleList;
Uint32 theMyRef; // My block reference
diff --git a/ndb/include/ndbapi/NdbApi.hpp b/ndb/include/ndbapi/NdbApi.hpp
index 515f39433e4..add733cccd7 100644
--- a/ndb/include/ndbapi/NdbApi.hpp
+++ b/ndb/include/ndbapi/NdbApi.hpp
@@ -23,6 +23,8 @@
#include "NdbOperation.hpp"
#include "NdbScanOperation.hpp"
#include "NdbIndexOperation.hpp"
+#include "NdbIndexScanOperation.hpp"
+#include "NdbScanFilter.hpp"
#include "NdbRecAttr.hpp"
#include "NdbResultSet.hpp"
#include "NdbDictionary.hpp"
diff --git a/ndb/include/ndbapi/NdbBlob.hpp b/ndb/include/ndbapi/NdbBlob.hpp
index 9398f77c474..dc47115d16f 100644
--- a/ndb/include/ndbapi/NdbBlob.hpp
+++ b/ndb/include/ndbapi/NdbBlob.hpp
@@ -50,24 +50,33 @@ class NdbColumnImpl;
* - closed: after transaction commit
* - invalid: after rollback or transaction close
*
- * NdbBlob supports 2 styles of data access:
+ * NdbBlob supports 3 styles of data access:
*
* - in prepare phase, NdbBlob methods getValue and setValue are used to
- * prepare a read or write of a single blob value of known size
+ * prepare a read or write of a blob value of known size
*
- * - in active phase, NdbBlob methods readData and writeData are used to
- * read or write blob data of undetermined size
+ * - in prepare phase, setActiveHook is used to define a routine which
+ * is invoked as soon as the handle becomes active
+ *
+ * - in active phase, readData and writeData are used to read or write
+ * blob data of arbitrary size
+ *
+ * The styles can be applied in combination (in above order).
+ *
+ * Blob operations take effect at next transaction execute. In some
+ * cases NdbBlob is forced to do implicit executes. To avoid this,
+ * operate on complete blob parts.
+ *
+ * Use NdbConnection::executePendingBlobOps to flush your reads and
+ * writes. It avoids execute penalty if nothing is pending. It is not
+ * needed after execute (obviously) or after next scan result.
*
* NdbBlob methods return -1 on error and 0 on success, and use output
* parameters when necessary.
*
* Notes:
* - table and its blob part tables are not created atomically
- * - blob data operations take effect at next transaction execute
- * - NdbBlob may need to do implicit executes on the transaction
- * - read and write of complete parts is much more efficient
* - scan must use the "new" interface NdbScanOperation
- * - scan with blobs applies hold-read-lock (at minimum)
* - to update a blob in a read op requires exclusive tuple lock
* - update op in scan must do its own getBlobHandle
* - delete creates implicit, not-accessible blob handles
@@ -78,12 +87,16 @@ class NdbColumnImpl;
* - scan must use exclusive locking for now
*
* Todo:
- * - add scan method hold-read-lock-until-next + return-keyinfo
- * - better check of keyinfo length when setting keys
- * - better check of allowed blob op vs locking mode
+ * - add scan method hold-read-lock + return-keyinfo
+ * - check keyinfo length when setting keys
+ * - check allowed blob ops vs locking mode
+ * - overload control (too many pending ops)
*/
class NdbBlob {
public:
+ /**
+ * State.
+ */
enum State {
Idle = 0,
Prepared = 1,
@@ -93,8 +106,14 @@ public:
};
State getState();
/**
+ * Inline blob header.
+ */
+ struct Head {
+ Uint64 length;
+ };
+ /**
* Prepare to read blob value. The value is available after execute.
- * Use isNull to check for NULL and getLength to get the real length
+ * Use getNull to check for NULL and getLength to get the real length
* and to check for truncation. Sets current read/write position to
* after the data read.
*/
@@ -107,6 +126,20 @@ public:
*/
int setValue(const void* data, Uint32 bytes);
/**
+ * Callback for setActiveHook. Invoked immediately when the prepared
+ * operation has been executed (but not committed). Any getValue or
+ * setValue is done first. The blob handle is active so readData or
+ * writeData etc can be used to manipulate blob value. A user-defined
+ * argument is passed along. Returns non-zero on error.
+ */
+ typedef int ActiveHook(NdbBlob* me, void* arg);
+ /**
+ * Define callback for blob handle activation. The queue of prepared
+ * operations will be executed in no commit mode up to this point and
+ * then the callback is invoked.
+ */
+ int setActiveHook(ActiveHook* activeHook, void* arg);
+ /**
* Check if blob is null.
*/
int getNull(bool& isNull);
@@ -115,7 +148,7 @@ public:
*/
int setNull();
/**
- * Get current length in bytes. Use isNull to distinguish between
+ * Get current length in bytes. Use getNull to distinguish between
* length 0 blob and NULL blob.
*/
int getLength(Uint64& length);
@@ -180,6 +213,13 @@ public:
static const int ErrAbort = 4268;
// "Unknown blob error"
static const int ErrUnknown = 4269;
+ /**
+ * Return info about all blobs in this operation.
+ */
+ // Get first blob in list
+ NdbBlob* blobsFirstBlob();
+ // Get next blob in list after this one
+ NdbBlob* blobsNextBlob();
private:
friend class Ndb;
@@ -187,20 +227,20 @@ private:
friend class NdbOperation;
friend class NdbScanOperation;
friend class NdbDictionaryImpl;
+ friend class NdbResultSet; // atNextResult
// state
State theState;
void setState(State newState);
// define blob table
static void getBlobTableName(char* btname, const NdbTableImpl* t, const NdbColumnImpl* c);
static void getBlobTable(NdbTableImpl& bt, const NdbTableImpl* t, const NdbColumnImpl* c);
- // table name
- char theBlobTableName[BlobTableNameSize];
// ndb api stuff
Ndb* theNdb;
NdbConnection* theNdbCon;
NdbOperation* theNdbOp;
NdbTableImpl* theTable;
NdbTableImpl* theAccessTable;
+ NdbTableImpl* theBlobTable;
const NdbColumnImpl* theColumn;
char theFillChar;
// sizes
@@ -213,10 +253,11 @@ private:
bool theSetFlag;
const char* theSetBuf;
Uint32 theGetSetBytes;
- // head
- struct Head {
- Uint64 length;
- };
+ // pending ops
+ Uint8 thePendingBlobOps;
+ // activation callback
+ ActiveHook* theActiveHook;
+ void* theActiveHookArg;
// buffers
struct Buf {
char* data;
@@ -234,7 +275,6 @@ private:
char* theInlineData;
NdbRecAttr* theHeadInlineRecAttr;
bool theHeadInlineUpdateFlag;
- bool theNewPartFlag;
// length and read/write position
int theNullFlag;
Uint64 theLength;
@@ -275,6 +315,11 @@ private:
int insertParts(const char* buf, Uint32 part, Uint32 count);
int updateParts(const char* buf, Uint32 part, Uint32 count);
int deleteParts(Uint32 part, Uint32 count);
+ // pending ops
+ int executePendingBlobReads();
+ int executePendingBlobWrites();
+ // callbacks
+ int invokeActiveHook();
// blob handle maintenance
int atPrepare(NdbConnection* aCon, NdbOperation* anOp, const NdbColumnImpl* aColumn);
int preExecute(ExecType anExecType, bool& batch);
@@ -286,6 +331,7 @@ private:
void setErrorCode(NdbOperation* anOp, bool invalidFlag = true);
void setErrorCode(NdbConnection* aCon, bool invalidFlag = true);
#ifdef VM_TRACE
+ int getOperationType() const;
friend class NdbOut& operator<<(NdbOut&, const NdbBlob&);
#endif
};
diff --git a/ndb/include/ndbapi/NdbConnection.hpp b/ndb/include/ndbapi/NdbConnection.hpp
index c620578cabd..c268f9aab04 100644
--- a/ndb/include/ndbapi/NdbConnection.hpp
+++ b/ndb/include/ndbapi/NdbConnection.hpp
@@ -19,15 +19,15 @@
#include <ndb_types.h>
#include <NdbError.hpp>
+#include <NdbDictionary.hpp>
class NdbConnection;
class NdbOperation;
-class NdbCursorOperation;
class NdbScanOperation;
+class NdbIndexScanOperation;
class NdbIndexOperation;
class NdbApiSignal;
class Ndb;
-class NdbScanReceiver;
class NdbBlob;
@@ -160,7 +160,7 @@ class NdbConnection
friend class NdbOperation;
friend class NdbScanOperation;
friend class NdbIndexOperation;
- friend class NdbScanReceiver;
+ friend class NdbIndexScanOperation;
friend class NdbBlob;
public:
@@ -178,56 +178,31 @@ public:
NdbOperation* getNdbOperation(const char* aTableName);
/**
- * Get an NdbOperation for index scan of a table.
- * Note that the operation has to be defined before it is executed.
- *
- * @note All operations within the same transaction need to
- * be initialized with this method.
- *
- * @param anIndexName The index name.
- * @param aTableName The table name.
- * @return Pointer to an NdbOperation object if successful, otherwise NULL.
- */
- NdbOperation* getNdbOperation(const char* anIndexName,
- const char* aTableName);
-
-#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
- /**
* Get an operation from NdbScanOperation idlelist and
* get the NdbConnection object which
* was fetched by startTransaction pointing to this operation.
- * This operation will set the theTableId
- * in the NdbOperation object.synchronous.
*
* @param aTableName a table name.
* @return pointer to an NdbOperation object if successful, otherwise NULL
*/
NdbScanOperation* getNdbScanOperation(const char* aTableName);
-#endif
-#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
/**
* Get an operation from NdbScanOperation idlelist and
* get the NdbConnection object which
* was fetched by startTransaction pointing to this operation.
- * This operation will set the theTableId
- * in the NdbOperation object.synchronous.
*
* @param anIndexName The index name.
* @param aTableName a table name.
* @return pointer to an NdbOperation object if successful, otherwise NULL
*/
- NdbScanOperation* getNdbScanOperation(const char* anIndexName,
- const char* aTableName);
-#endif
-
-
+ NdbIndexScanOperation* getNdbIndexScanOperation(const char* anIndexName,
+ const char* aTableName);
+
/**
* Get an operation from NdbIndexOperation idlelist and
* get the NdbConnection object that
* was fetched by startTransaction pointing to this operation.
- * This operation will set the theTableId
- * in the NdbOperation object. Synchronous.
*
* @param indexName An index name (as created by createIndex).
* @param tableName A table name.
@@ -337,76 +312,17 @@ public:
*/
void close();
- /** @} *********************************************************************/
-
- /**
- * @name Scan Transactions
- * @{
- */
-
/**
- * Execute a scan transaction. This will define
- * and start the scan transaction in the NDB kernel.
- *
- * @return 0 if successful otherwise -1.
- */
- int executeScan();
-
- /**
- * Get the next tuple in a scan transaction.
- *
- * After each call to NdbConnection::nextScanResult
- * the buffers and NdbRecAttr objects defined in
- * NdbOperation::getValue are updated with values
- * from the scanned tuple.
- *
- * @param fetchAllowed If set to false, then fetching is disabled
- *
- * The NDB API will contact the NDB Kernel for more tuples
- * when necessary to do so unless you set the fetchAllowed
- * to false.
- * This will force NDB to process any records it
- * already has in it's caches. When there are no more cached
- * records it will return 2. You must then call nextScanResult
- * with fetchAllowed = true in order to contact NDB for more
- * records.
- *
- * fetchAllowed = false is useful when you want to update or
- * delete all the records fetched in one transaction(This will save a
- * lot of round trip time and make updates or deletes of scanned
- * records a lot faster).
- * While nextScanResult(false)
- * returns 0 take over the record to another transaction. When
- * nextScanResult(false) returns 2 you must execute and commit the other
- * transaction. This will cause the locks to be transferred to the
- * other transaction, updates or deletes will be made and then the
- * locks will be released.
- * After that, call nextScanResult(true) which will fetch new records and
- * cache them in the NdbApi.
- *
- * @note If you don't take over the records to another transaction the
- * locks on those records will be released the next time NDB Kernel
- * is contacted for more records.
+ * Restart transaction
*
- * @note Please contact for examples of efficient scan
- * updates and deletes.
+ * Once a transaction has been completed successfully
+ * it can be started again wo/ calling closeTransaction/startTransaction
*
- * @return
- * - -1: if unsuccessful,<br>
- * - 0: if another tuple was received, and<br>
- * - 1: if there are no more tuples to scan.
- * - 2: if there are no more cached records in NdbApi
+ * Note this method also releases completed operations
*/
- int nextScanResult(bool fetchAllowed = true);
+ int restart();
- /**
- * Stops the scan. Used if no more tuples are wanted.
- * The transaction should still be closed with
- * Ndb::closeTransaction.
- *
- * @return 0 if successful otherwise -1.
- */
- int stopScan();
+ /** @} *********************************************************************/
/**
* @name Meta Information
@@ -514,15 +430,30 @@ public:
*/
const NdbOperation * getNextCompletedOperation(const NdbOperation * op)const;
+ /** @} *********************************************************************/
+
/**
- * Release completed operations
+ * Execute the transaction in NoCommit mode if there are any not-yet
+ * executed blob part operations of given types. Otherwise do
+ * nothing. The flags argument is bitwise OR of (1 << optype) where
+ * optype comes from NdbOperation::OperationType. Only the basic PK
+ * ops are used (read, insert, update, delete).
*/
- void releaseCompletedOperations();
+ int executePendingBlobOps(Uint8 flags = 0xFF);
-
- /** @} *********************************************************************/
+ // Fast path calls for MySQL ha_ndbcluster
+ NdbOperation* getNdbOperation(NdbDictionary::Table * table);
+ NdbIndexOperation* getNdbIndexOperation(NdbDictionary::Index * index,
+ NdbDictionary::Table * table);
+ NdbScanOperation* getNdbScanOperation(NdbDictionary::Table * table);
+ NdbIndexScanOperation* getNdbIndexScanOperation(NdbDictionary::Index * index,
+ NdbDictionary::Table * table);
private:
+ /**
+ * Release completed operations
+ */
+ void releaseCompletedOperations();
typedef Uint64 TimeMillis_t;
/**************************************************************************
@@ -587,13 +518,7 @@ private:
int receiveTCINDXCONF(const class TcIndxConf *, Uint32 aDataLength);
int receiveTCINDXREF(NdbApiSignal*);
int receiveSCAN_TABREF(NdbApiSignal*);
- int receiveSCAN_TABCONF(NdbApiSignal*);
- int receiveSCAN_TABINFO(NdbApiSignal*);
-
- int checkNextScanResultComplete();
- int sendScanStart();
- int sendScanNext(bool stopScanFlag);
- int fetchNextScanResult();
+ int receiveSCAN_TABCONF(NdbApiSignal*, const Uint32*, Uint32 len);
int doSend(); // Send all operations
int sendROLLBACK(); // Send of an ROLLBACK
@@ -616,7 +541,7 @@ private:
// Release all cursor operations in connection
void releaseOps(NdbOperation*);
- void releaseCursorOperations(NdbCursorOperation*);
+ void releaseScanOperations(NdbIndexScanOperation*);
// Set the transaction identity of the transaction
void setTransactionId(Uint64 aTransactionId);
@@ -633,10 +558,12 @@ private:
int checkMagicNumber(); // Verify correct object
NdbOperation* getNdbOperation(class NdbTableImpl* aTable,
NdbOperation* aNextOp = 0);
- NdbScanOperation* getNdbScanOperation(class NdbTableImpl* aTable);
+ NdbIndexScanOperation* getNdbScanOperation(class NdbTableImpl* aTable);
NdbIndexOperation* getNdbIndexOperation(class NdbIndexImpl* anIndex,
class NdbTableImpl* aTable,
NdbOperation* aNextOp = 0);
+ NdbIndexScanOperation* getNdbIndexScanOperation(NdbIndexImpl* index,
+ NdbTableImpl* table);
void handleExecuteCompletion();
@@ -687,7 +614,6 @@ private:
Uint32 theNoOfOpSent; // How many operations have been sent
Uint32 theNoOfOpCompleted; // How many operations have completed
Uint32 theNoOfOpFetched; // How many operations was actually fetched
- Uint32 theNoOfSCANTABCONFRecv; // How many SCAN_TABCONF have been received
Uint32 theMyRef; // Our block reference
Uint32 theTCConPtr; // Transaction Co-ordinator connection pointer.
Uint64 theTransactionId; // theTransactionId of the transaction
@@ -723,23 +649,20 @@ private:
Uint32 theNodeSequence; // The sequence no of the db node
bool theReleaseOnClose;
- // Cursor operations
+ // Scan operations
bool m_waitForReply;
- NdbCursorOperation* m_theFirstCursorOperation;
- NdbCursorOperation* m_theLastCursorOperation;
+ NdbIndexScanOperation* m_theFirstScanOperation;
+ NdbIndexScanOperation* m_theLastScanOperation;
- NdbCursorOperation* m_firstExecutedCursorOp;
- // Scan operations
- bool theScanFinished;
+ NdbIndexScanOperation* m_firstExecutedScanOp;
- NdbScanReceiver* theCurrentScanRec; // The current operation to
- // distribute to the app.
- NdbScanReceiver* thePreviousScanRec; // The previous operation read by
- // nextScanResult.
- NdbOperation* theScanningOp; // The operation actually performing the scan
+ // Scan operations
+ // The operation actually performing the scan
+ NdbScanOperation* theScanningOp;
Uint32 theBuddyConPtr;
// optim: any blobs
bool theBlobFlag;
+ Uint8 thePendingBlobOps;
static void sendTC_COMMIT_ACK(NdbApiSignal *,
Uint32 transId1, Uint32 transId2,
@@ -749,6 +672,7 @@ private:
#ifdef VM_TRACE
void printState();
#endif
+ bool checkState_TransId(const Uint32 * transId) const;
};
inline
@@ -783,6 +707,16 @@ NdbConnection::checkMagicNumber()
}
}
+inline
+bool
+NdbConnection::checkState_TransId(const Uint32 * transId) const {
+ const Uint32 tTmp1 = transId[0];
+ const Uint32 tTmp2 = transId[1];
+ Uint64 tRecTransId = (Uint64)tTmp1 + ((Uint64)tTmp2 << 32);
+ bool b = theStatus == Connected && theTransactionId == tRecTransId;
+ return b;
+}
+
/************************************************************************************************
void setTransactionId(Uint64 aTransactionId);
@@ -956,6 +890,21 @@ NdbConnection::OpSent()
theNoOfOpSent++;
}
+/******************************************************************************
+void executePendingBlobOps();
+******************************************************************************/
+#include <stdlib.h>
+inline
+int
+NdbConnection::executePendingBlobOps(Uint8 flags)
+{
+ if (thePendingBlobOps & flags) {
+ // not executeNoBlobs because there can be new ops with blobs
+ return execute(NoCommit);
+ }
+ return 0;
+}
+
inline
Uint32
NdbConnection::ptr2int(){
@@ -963,5 +912,3 @@ NdbConnection::ptr2int(){
}
#endif
-
-
diff --git a/ndb/include/ndbapi/NdbCursorOperation.hpp b/ndb/include/ndbapi/NdbCursorOperation.hpp
index cd76b045ea2..e7eeb54ba2d 100644
--- a/ndb/include/ndbapi/NdbCursorOperation.hpp
+++ b/ndb/include/ndbapi/NdbCursorOperation.hpp
@@ -17,77 +17,4 @@
#ifndef NdbCursorOperation_H
#define NdbCursorOperation_H
-#include <NdbOperation.hpp>
-
-class NdbResultSet;
-
-/**
- * @class NdbCursorOperation
- * @brief Operation using cursors
- */
-class NdbCursorOperation : public NdbOperation
-{
- friend class NdbResultSet;
- friend class NdbConnection;
-
-public:
- /**
- * Type of cursor
- */
- enum CursorType {
- NoCursor = 0,
- ScanCursor = 1,
- IndexCursor = 2
- };
-
- /**
- * Lock when performing scan
- */
- enum LockMode {
- LM_Read = 0,
- LM_Exclusive = 1,
- LM_CommittedRead = 2,
-#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
- LM_Dirty = 2
-#endif
- };
-
- virtual CursorType cursorType() = 0;
-
- /**
- * readTuples returns a NdbResultSet where tuples are stored.
- * Tuples are not stored in NdbResultSet until execute(NoCommit)
- * has been executed and nextResult has been called.
- *
- * @param parallel Scan parallelism
- * @param LockMode Scan lock handling
- * @returns NdbResultSet.
- */
- virtual NdbResultSet* readTuples(unsigned parallel = 0,
- LockMode = LM_Read ) = 0;
-
- inline NdbResultSet* readTuplesExclusive(int parallell = 0){
- return readTuples(parallell, LM_Exclusive);
- }
-
-protected:
- NdbCursorOperation(Ndb* aNdb);
-
- ~NdbCursorOperation();
-
- void cursInit();
-
- virtual int executeCursor(int ProcessorId) = 0;
-
- NdbResultSet* getResultSet();
- NdbResultSet* m_resultSet;
-
-private:
-
- virtual int nextResult(bool fetchAllowed) = 0;
-
- virtual void closeScan() = 0;
-};
-
-
#endif
diff --git a/ndb/include/ndbapi/NdbDictionary.hpp b/ndb/include/ndbapi/NdbDictionary.hpp
index 3b38e33ec91..b5c3985c6cb 100644
--- a/ndb/include/ndbapi/NdbDictionary.hpp
+++ b/ndb/include/ndbapi/NdbDictionary.hpp
@@ -144,6 +144,8 @@ public:
FragAllLarge = 4 ///< Eight fragments per node group.
};
};
+
+ class Table; // forward declaration
/**
* @class Column
@@ -183,7 +185,7 @@ public:
Datetime, ///< Precision down to 1 sec (sizeof(Datetime) == 8 bytes )
Timespec, ///< Precision down to 1 nsec(sizeof(Datetime) == 12 bytes )
Blob, ///< Binary large object (see NdbBlob)
- Clob ///< Text blob
+ Text ///< Text blob
};
/**
@@ -309,7 +311,8 @@ public:
/**
* For blob, set or get "part size" i.e. number of bytes to store in
- * each tuple of the "blob table". Must be less than 64k.
+ * each tuple of the "blob table". Can be set to zero to omit parts
+ * and to allow only inline bytes ("tinyblob").
*/
void setPartSize(int size) { setScale(size); }
int getPartSize() const { return getScale(); }
@@ -324,7 +327,7 @@ public:
/**
* Get size of element
*/
- int Column::getSize() const;
+ int getSize() const;
/**
* Set distribution key
@@ -364,6 +367,8 @@ public:
void setIndexOnlyStorage(bool);
bool getIndexOnlyStorage() const;
+ const Table * getBlobTable() const;
+
/**
* @name ODBC Specific methods
* @{
@@ -1060,6 +1065,6 @@ public:
};
};
-class NdbOut& operator <<(class NdbOut& ndbout, const NdbDictionary::Column::Type type);
+class NdbOut& operator <<(class NdbOut& out, const NdbDictionary::Column& col);
#endif
diff --git a/ndb/include/ndbapi/NdbIndexOperation.hpp b/ndb/include/ndbapi/NdbIndexOperation.hpp
index baf31dca0ee..2d873c52e56 100644
--- a/ndb/include/ndbapi/NdbIndexOperation.hpp
+++ b/ndb/include/ndbapi/NdbIndexOperation.hpp
@@ -29,7 +29,7 @@
#ifndef NdbIndexOperation_H
#define NdbIndexOperation_H
-#include <NdbCursorOperation.hpp>
+#include "NdbOperation.hpp"
class Index;
class NdbResultSet;
diff --git a/ndb/include/ndbapi/NdbIndexScanOperation.hpp b/ndb/include/ndbapi/NdbIndexScanOperation.hpp
new file mode 100644
index 00000000000..82aed04a9fc
--- /dev/null
+++ b/ndb/include/ndbapi/NdbIndexScanOperation.hpp
@@ -0,0 +1,140 @@
+/* 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 NdbIndexScanOperation_H
+#define NdbIndexScanOperation_H
+
+#include <NdbScanOperation.hpp>
+
+/**
+ * @class NdbIndexScanOperation
+ * @brief Class of scan operations for use to scan ordered index
+ */
+class NdbIndexScanOperation : public NdbScanOperation {
+ friend class Ndb;
+ friend class NdbConnection;
+ friend class NdbResultSet;
+ friend class NdbOperation;
+ friend class NdbScanOperation;
+public:
+ /**
+ * readTuples returns a NdbResultSet where tuples are stored.
+ * Tuples are not stored in NdbResultSet until execute(NoCommit)
+ * has been executed and nextResult has been called.
+ *
+ * @param parallel Scan parallelism
+ * @param batch No of rows to fetch from each fragment at a time
+ * @param LockMode Scan lock handling
+ * @param order_by Order result set in index order
+ * @returns NdbResultSet.
+ * @see NdbScanOperation::readTuples
+ */
+ NdbResultSet* readTuples(LockMode = LM_Read,
+ Uint32 batch = 0,
+ Uint32 parallel = 0,
+ bool order_by = false);
+
+ inline NdbResultSet* readTuples(int parallell){
+ return readTuples(LM_Read, 0, parallell, false);
+ }
+
+ inline NdbResultSet* readTuplesExclusive(int parallell = 0){
+ return readTuples(LM_Exclusive, 0, parallell, false);
+ }
+
+ /**
+ * @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,
+ BoundLT = 1, ///< lower bound, strict
+ BoundGE = 2, ///< upper bound
+ BoundGT = 3, ///< upper bound, strict
+ BoundEQ = 4 ///< equality
+ };
+
+ /**
+ * 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.
+ *
+ * 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.
+ *
+ * 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
+ * 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.
+ *
+ * @param attrName Attribute name, alternatively:
+ * @param anAttrId Index column id (starting from 0)
+ * @param type Type of bound
+ * @param value Pointer to bound value, 0 for NULL
+ * @param len Value length in bytes.
+ * Fixed per datatype and can be omitted
+ * @return 0 if successful otherwise -1
+ */
+ int setBound(const char* attr, int type, const void* aValue, Uint32 len = 0);
+
+ /**
+ * Define bound on index key in range scan using index column id.
+ * See the other setBound() method for details.
+ */
+ int setBound(Uint32 anAttrId, int type, const void* aValue, Uint32 len = 0);
+
+ /** @} *********************************************************************/
+
+private:
+ NdbIndexScanOperation(Ndb* aNdb);
+ virtual ~NdbIndexScanOperation();
+
+ int setBound(const NdbColumnImpl*, int type, const void* aValue, Uint32 len);
+ int saveBoundATTRINFO();
+
+ virtual int equal_impl(const NdbColumnImpl*, const char*, Uint32);
+ virtual NdbRecAttr* getValue_impl(const NdbColumnImpl*, char*);
+
+ void fix_get_values();
+ int next_result_ordered(bool fetchAllowed);
+ int send_next_scan_ordered(Uint32 idx);
+ int compare(Uint32 key, Uint32 cols, const NdbReceiver*, const NdbReceiver*);
+
+ Uint32 m_sort_columns;
+};
+
+#endif
diff --git a/ndb/include/ndbapi/NdbOperation.hpp b/ndb/include/ndbapi/NdbOperation.hpp
index cfa656cb2d5..c48dccd4864 100644
--- a/ndb/include/ndbapi/NdbOperation.hpp
+++ b/ndb/include/ndbapi/NdbOperation.hpp
@@ -42,8 +42,8 @@ class NdbOperation
friend class NdbScanReceiver;
friend class NdbScanFilter;
friend class NdbScanFilterImpl;
+ friend class NdbReceiver;
friend class NdbBlob;
-
public:
/**
* @name Define Standard Operation Type
@@ -196,196 +196,7 @@ public:
*/
virtual int interpretedDeleteTuple();
- /**
- * Scan a table to read tuples.
- *
- * The operation only sets a temporary read lock while
- * reading the tuple.
- * The tuple lock is released when the result of the read reaches the
- * application.
- *
- * @param Parallelism Number of parallel tuple reads are performed
- * in the scan.
- * Currently a maximum of 256 parallel tuple
- * reads are allowed.
- * The parallelism can in reality be lower
- * than specified
- * depending on the number of nodes
- * in the cluster
- * @return 0 if successful otherwise -1.
- */
- int openScanRead(Uint32 Parallelism = 16 );
-
- /**
- * Scan a table to write or update tuples.
- *
- * The operation sets an exclusive lock on the tuple and sends the result
- * to the application.
- * Thus when the application reads the data, the tuple is
- * still locked with an exclusive lock.
- *
- * @param parallelism Number of parallel tuple reads are performed
- * in the scan.
- * Currently a maximum of 256 parallel tuple
- * reads are allowed.
- * The parallelism can in reality be lower
- * than specified depending on the number
- * of nodes in the cluster
- * @return 0 if successful otherwise -1.
- *
- */
- int openScanExclusive(Uint32 parallelism = 16);
-
- /**
- * Scan a table to read tuples.
- *
- * The operation only sets a read lock while
- * reading the tuple.
- * Thus when the application reads the data, the tuple is
- * still locked with a read lock.
- *
- * @param parallelism Number of parallel tuple reads are performed
- * in the scan.
- * Currently a maximum of 256 parallel tuple
- * reads are allowed.
- * The parallelism can in reality be lower
- * than specified
- * depending on the number of nodes
- * in the cluster
- * @return 0 if successful otherwise -1.
- */
- int openScanReadHoldLock(Uint32 parallelism = 16);
-
- /**
- * Scan a table to read tuples.
- *
- * The operation does not wait for locks held by other transactions
- * but returns the latest committed tuple instead.
- *
- * @param parallelism Number of parallel tuple reads are performed
- * in the scan.
- * Currently a maximum of 256 parallel tuple
- * reads are allowed.
- * The parallelism can in reality be lower
- * than specified
- * depending on the number of nodes
- * in the cluster
- * @return 0 if successful otherwise -1.
- */
- int openScanReadCommitted(Uint32 parallelism = 16);
-
- /** @} *********************************************************************/
-
- /**
- * @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,
- BoundLT = 1, ///< lower bound, strict
- BoundGE = 2, ///< upper bound
- BoundGT = 3, ///< upper bound, strict
- BoundEQ = 4 ///< equality
- };
-
- /**
- * Define bound on index key in range scan.
- *
- * Each index key can have not null lower and/or upper bound, or can
- * be set equal to not null value. The bounds can be defined in any
- * order but a duplicate definition is an error.
- *
- * The scan is most effective when bounds are given for an initial
- * sequence of non-nullable index keys, and all but the last one is an
- * equality. In this case the scan returns a contiguous range from
- * each ordered index fragment.
- *
- * @note This release implements only the case described above,
- * except for the non-nullable limitation. Other sets of
- * bounds return error or empty result set.
- *
- * @note In this release a null key value satisfies any lower
- * bound and no upper bound. This may change.
- *
- * @param attrName Attribute name, alternatively:
- * @param anAttrId Index column id (starting from 0).
- * @param type Type of bound
- * @param value Pointer to bound value
- * @param len Value length in bytes.
- * Fixed per datatype and can be omitted
- * @return 0 if successful otherwise -1
- */
- int setBound(const char* anAttrName, int type, const void* aValue, Uint32 len = 0);
-
- /**
- * Define bound on index key in range scan using index column id.
- * See the other setBound() method for details.
- */
- int setBound(Uint32 anAttrId, int type, const void* aValue, Uint32 len = 0);
-
/** @} *********************************************************************/
-
- /**
- * Validate parallelism parameter by checking the number
- * against number of executing Ndb nodes.
- *
- * @param Parallelism
- * @return 0 if correct parallelism value, otherwise -1.
- *
- */
- int checkParallelism(Uint32 Parallelism);
-
- /**
- * Transfer scan operation to an updating transaction. Use this function
- * when a scan has found a record that you want to update.
- * 1. Start a new transaction.
- * 2. Call the function takeOverForUpdate using your new transaction
- * as parameter, all the properties of the found record will be copied
- * to the new transaction.
- * 3. When you execute the new transaction, the lock held by the scan will
- * be transferred to the new transaction(it's taken over).
- *
- * @note You must have started the scan with openScanExclusive
- * to be able to update the found tuple.
- *
- * @param updateTrans the update transaction connection.
- * @return an NdbOperation or NULL.
- */
- NdbOperation* takeOverForUpdate(NdbConnection* updateTrans);
-
- /**
- * Transfer scan operation to a deleting transaction. Use this function
- * when a scan has found a record that you want to delete.
- * 1. Start a new transaction.
- * 2. Call the function takeOverForDelete using your new transaction
- * as parameter, all the properties of the found record will be copied
- * to the new transaction.
- * 3. When you execute the new transaction, the lock held by the scan will
- * be transferred to the new transaction(its taken over).
- *
- * @note You must have started the scan with openScanExclusive
- * to be able to delete the found tuple.
- *
- * @param deleteTrans the delete transaction connection.
- * @return an NdbOperation or NULL.
- */
- NdbOperation* takeOverForDelete(NdbConnection* deleteTrans);
/**
* @name Specify Search Conditions
@@ -883,16 +694,7 @@ protected:
// Initialise after allocating operation to a transaction
//--------------------------------------------------------------
int init(class NdbTableImpl*, NdbConnection* aCon);
-
- void initScan(); // Initialise after allocating operation
- // to a scan transaction
- virtual void releaseScan(); // Release scan parts of transaction
- void releaseSignals();
- void releaseScanSignals();
- void prepareNextScanResult();
-
- // Common part for Read and Exclusive
- int openScan(Uint32 aParallelism, bool, bool, bool);
+ void initInterpreter();
void next(NdbOperation*); // Set next pointer
@@ -938,19 +740,12 @@ protected:
*****************************************************************************/
int doSend(int ProcessorId, Uint32 lastFlag);
- int doSendScan(int ProcessorId);
-
- int prepareSendScan(Uint32 TC_ConnectPtr,
- Uint64 TransactionId);
-
virtual int prepareSend(Uint32 TC_ConnectPtr,
Uint64 TransactionId);
virtual void setLastFlag(NdbApiSignal* signal, Uint32 lastFlag);
int prepareSendInterpreted(); // Help routine to prepare*
- void TCOPCONF(Uint32 anNdbColumnImplLen); // Handle TC[KEY/INDX]CONF signal
-
int receiveTCKEYREF(NdbApiSignal*);
@@ -958,7 +753,7 @@ protected:
int receiveREAD_CONF(const Uint32* aDataPtr, Uint32 aDataLength);
- int checkMagicNumber(); // Verify correct object
+ int checkMagicNumber(bool b = true); // Verify correct object
int checkState_TransId(NdbApiSignal* aSignal);
@@ -966,10 +761,8 @@ protected:
* These are support methods only used locally in this class.
******************************************************************************/
- virtual int equal_impl(const NdbColumnImpl* anAttrObject,
- const char* aValue,
- Uint32 len);
- NdbRecAttr* getValue(const NdbColumnImpl* anAttrObject, char* aValue = 0);
+ virtual int equal_impl(const NdbColumnImpl*,const char* aValue, Uint32 len);
+ virtual NdbRecAttr* getValue_impl(const NdbColumnImpl*, char* aValue = 0);
int setValue(const NdbColumnImpl* anAttrObject, const char* aValue, Uint32 len);
NdbBlob* getBlobHandle(NdbConnection* aCon, const NdbColumnImpl* anAttrObject);
int incValue(const NdbColumnImpl* anAttrObject, Uint32 aValue);
@@ -981,15 +774,12 @@ protected:
int branch_reg_reg(Uint32 type, Uint32, Uint32, Uint32);
int branch_col(Uint32 type, Uint32, const char *, Uint32, bool, Uint32 Label);
int branch_col_null(Uint32 type, Uint32 col, Uint32 Label);
- int setBound(const NdbColumnImpl* anAttrObject, int type, const void* aValue, Uint32 len);
// Handle ATTRINFO signals
int receiveREAD_AI(Uint32* aDataPtr, Uint32 aLength);
int insertATTRINFO(Uint32 aData);
int insertATTRINFOloop(const Uint32* aDataPtr, Uint32 aLength);
- int getFirstATTRINFOScan();
- int saveBoundATTRINFO();
int insertKEYINFO(const char* aValue,
Uint32 aStartPosition,
@@ -1013,12 +803,8 @@ protected:
Uint32 ptr2int() { return theReceiver.getId(); };
- NdbOperation*
- takeOverScanOp(OperationType opType, NdbConnection* updateTrans);
-
// get table or index key from prepared signals
int getKeyFromTCREQ(Uint32* data, unsigned size);
- int getKeyFromKEYINFO20(Uint32* data, unsigned size);
/******************************************************************************
* These are the private variables that are defined in the operation objects.
@@ -1032,7 +818,6 @@ protected:
Ndb* theNdb; // Point back to the Ndb object.
NdbConnection* theNdbCon; // Point back to the connection object.
NdbOperation* theNext; // Next pointer to operation.
- NdbOperation* theNextScanOp;
NdbApiSignal* theTCREQ; // The TC[KEY/INDX]REQ signal object
NdbApiSignal* theFirstATTRINFO; // The first ATTRINFO signal object
NdbApiSignal* theCurrentATTRINFO; // The current ATTRINFO signal object
@@ -1043,9 +828,6 @@ protected:
NdbApiSignal* theFirstKEYINFO; // The first KEYINFO signal object
NdbApiSignal* theLastKEYINFO; // The first KEYINFO signal object
- NdbRecAttr* theFirstRecAttr; // The first receive attribute object
- NdbRecAttr* theCurrentRecAttr; // The current receive attribute object
-
class NdbLabel* theFirstLabel;
class NdbLabel* theLastLabel;
class NdbBranch* theFirstBranch;
@@ -1060,11 +842,6 @@ protected:
Uint32* theKEYINFOptr; // Pointer to where to write KEYINFO
Uint32* theATTRINFOptr; // Pointer to where to write ATTRINFO
- Uint32 theTotalRecAI_Len; // The total length received according
- // to the TCKEYCONF signal
- Uint32 theCurrRecAI_Len; // The currently received length
- Uint32 theAI_ElementLen; // How many words long is this element
- Uint32* theCurrElemPtr; // The current pointer to the element
class NdbTableImpl* m_currentTable; // The current table
class NdbTableImpl* m_accessTable;
@@ -1106,15 +883,6 @@ protected:
Uint16 m_keyInfoGSN;
Uint16 m_attrInfoGSN;
- // Scan related variables
- Uint32 theParallelism;
- NdbScanReceiver** theScanReceiversArray;
- NdbApiSignal* theSCAN_TABREQ;
- NdbApiSignal* theFirstSCAN_TABINFO_Send;
- NdbApiSignal* theLastSCAN_TABINFO_Send;
- NdbApiSignal* theFirstSCAN_TABINFO_Recv;
- NdbApiSignal* theLastSCAN_TABINFO_Recv;
- NdbApiSignal* theSCAN_TABCONF_Recv;
// saveBoundATTRINFO() moves ATTRINFO here when setBound() is ready
NdbApiSignal* theBoundATTRINFO;
Uint32 theTotalBoundAI_Len;
@@ -1130,11 +898,11 @@ protected:
inline
int
-NdbOperation::checkMagicNumber()
+NdbOperation::checkMagicNumber(bool b)
{
if (theMagicNumber != 0xABCDEF01){
#ifdef NDB_NO_DROPPED_SIGNAL
- abort();
+ if(b) abort();
#endif
return -1;
}
diff --git a/ndb/include/ndbapi/NdbRecAttr.hpp b/ndb/include/ndbapi/NdbRecAttr.hpp
index 36b54035d96..da03df13027 100644
--- a/ndb/include/ndbapi/NdbRecAttr.hpp
+++ b/ndb/include/ndbapi/NdbRecAttr.hpp
@@ -73,8 +73,9 @@ class NdbOperation;
class NdbRecAttr
{
friend class NdbOperation;
+ friend class NdbIndexScanOperation;
friend class NdbEventOperationImpl;
- friend class NdbScanReceiver;
+ friend class NdbReceiver;
friend class Ndb;
friend class NdbOut& operator<<(class NdbOut&, const class AttributeS&);
@@ -244,9 +245,8 @@ private:
NdbRecAttr();
Uint32 attrId() const; /* Get attribute id */
- void setNULL(); /* Set NULL indicator */
- void setNotNULL(); /* Set Not NULL indicator */
- void setUNDEFINED(); /* Set UNDEFINED indicator */
+ bool setNULL(); /* Set NULL indicator */
+ bool receive_data(const Uint32*, Uint32);
void release(); /* Release memory if allocated */
void init(); /* Initialise object when allocated */
@@ -269,6 +269,7 @@ private:
Uint32 theAttrId; /* The attribute id */
int theNULLind;
+ bool m_nullable;
Uint32 theAttrSize;
Uint32 theArraySize;
const NdbDictionary::Column* m_column;
@@ -289,29 +290,7 @@ NdbRecAttr::getColumn() const {
inline
Uint32
NdbRecAttr::attrSize() const {
-
- switch(getType()){
- case NdbDictionary::Column::Int:
- case NdbDictionary::Column::Unsigned:
- case NdbDictionary::Column::Float:
- return 4;
- case NdbDictionary::Column::Decimal:
- case NdbDictionary::Column::Char:
- case NdbDictionary::Column::Varchar:
- case NdbDictionary::Column::Binary:
- case NdbDictionary::Column::Varbinary:
- return 1;
- case NdbDictionary::Column::Bigint:
- case NdbDictionary::Column::Bigunsigned:
- case NdbDictionary::Column::Double:
- case NdbDictionary::Column::Datetime:
- return 8;
- case NdbDictionary::Column::Timespec:
- return 12;
- case NdbDictionary::Column::Undefined:
- default:
- return 0;
- }
+ return theAttrSize;
}
inline
@@ -449,24 +428,11 @@ NdbRecAttr::attrId() const
}
inline
-void
+bool
NdbRecAttr::setNULL()
{
theNULLind = 1;
-}
-
-inline
-void
-NdbRecAttr::setNotNULL()
-{
- theNULLind = 0;
-}
-
-inline
-void
-NdbRecAttr::setUNDEFINED()
-{
- theNULLind = -1;
+ return m_nullable;
}
inline
diff --git a/ndb/include/ndbapi/NdbReceiver.hpp b/ndb/include/ndbapi/NdbReceiver.hpp
index a1a08a9735a..13898fc8e5f 100644
--- a/ndb/include/ndbapi/NdbReceiver.hpp
+++ b/ndb/include/ndbapi/NdbReceiver.hpp
@@ -23,6 +23,12 @@
class Ndb;
class NdbReceiver
{
+ friend class Ndb;
+ friend class NdbOperation;
+ friend class NdbScanOperation;
+ friend class NdbIndexOperation;
+ friend class NdbIndexScanOperation;
+ friend class NdbConnection;
public:
enum ReceiverType { NDB_UNINITIALIZED,
NDB_OPERATION = 1,
@@ -32,6 +38,7 @@ public:
NdbReceiver(Ndb *aNdb);
void init(ReceiverType type, void* owner);
+ void release();
~NdbReceiver();
Uint32 getId(){
@@ -42,18 +49,51 @@ public:
return m_type;
}
+ inline NdbConnection * getTransaction();
void* getOwner(){
return m_owner;
}
bool checkMagicNumber() const;
+ inline void next(NdbReceiver* next) { m_next = next;}
+ inline NdbReceiver* next() { return m_next; }
+
private:
Uint32 theMagicNumber;
Ndb* m_ndb;
Uint32 m_id;
+ Uint32 m_tcPtrI;
+ Uint32 m_key_info;
ReceiverType m_type;
void* m_owner;
+ NdbReceiver* m_next;
+
+ /**
+ * At setup
+ */
+ class NdbRecAttr * getValue(const class NdbColumnImpl*, char * user_dst_ptr);
+ void do_get_value(NdbReceiver*, Uint32 rows, Uint32 key_size);
+ void prepareSend();
+
+ int execKEYINFO20(Uint32 info, const Uint32* ptr, Uint32 len);
+ int execTRANSID_AI(const Uint32* ptr, Uint32 len);
+ int execTCOPCONF(Uint32 len);
+ int execSCANOPCONF(Uint32 tcPtrI, Uint32 len, Uint32 rows);
+ class NdbRecAttr* theFirstRecAttr;
+ class NdbRecAttr* theCurrentRecAttr;
+ class NdbRecAttr** m_rows;
+
+ Uint32 m_list_index; // When using multiple
+ Uint32 m_current_row;
+ Uint32 m_result_rows;
+ Uint32 m_defined_rows;
+
+ Uint32 m_expected_result_length;
+ Uint32 m_received_result_length;
+
+ bool nextResult() const { return m_current_row < m_result_rows; }
+ void copyout(NdbReceiver&);
};
#ifdef NDB_NO_DROPPED_SIGNAL
@@ -72,5 +112,32 @@ NdbReceiver::checkMagicNumber() const {
return retVal;
}
+inline
+void
+NdbReceiver::prepareSend(){
+ m_current_row = 0;
+ m_received_result_length = 0;
+ m_expected_result_length = 0;
+ theCurrentRecAttr = theFirstRecAttr;
+}
+
+inline
+int
+NdbReceiver::execTCOPCONF(Uint32 len){
+ Uint32 tmp = m_received_result_length;
+ m_expected_result_length = len;
+ return (tmp == len ? 1 : 0);
+}
+
+inline
+int
+NdbReceiver::execSCANOPCONF(Uint32 tcPtrI, Uint32 len, Uint32 rows){
+ m_tcPtrI = tcPtrI;
+ m_result_rows = rows;
+ Uint32 tmp = m_received_result_length;
+ m_expected_result_length = len;
+ return (tmp == len ? 1 : 0);
+}
+
#endif
#endif
diff --git a/ndb/include/ndbapi/NdbResultSet.hpp b/ndb/include/ndbapi/NdbResultSet.hpp
index d48df01214e..483e08179c0 100644
--- a/ndb/include/ndbapi/NdbResultSet.hpp
+++ b/ndb/include/ndbapi/NdbResultSet.hpp
@@ -30,17 +30,15 @@
#define NdbResultSet_H
-#include <NdbCursorOperation.hpp>
-#include <NdbIndexOperation.hpp>
#include <NdbScanOperation.hpp>
/**
* @class NdbResultSet
- * @brief NdbResultSet contains a NdbCursorOperation.
+ * @brief NdbResultSet contains a NdbScanOperation.
*/
class NdbResultSet
{
- friend class NdbCursorOperation;
+ friend class NdbScanOperation;
public:
@@ -93,22 +91,62 @@ public:
*/
int nextResult(bool fetchAllowed = true);
+ /**
+ * Close result set (scan)
+ */
void close();
- NdbOperation* updateTuple();
- NdbOperation* updateTuple(NdbConnection* takeOverTransaction);
+ /**
+ * Restart
+ */
+ int restart();
+ /**
+ * Transfer scan operation to an updating transaction. Use this function
+ * when a scan has found a record that you want to update.
+ * 1. Start a new transaction.
+ * 2. Call the function takeOverForUpdate using your new transaction
+ * as parameter, all the properties of the found record will be copied
+ * to the new transaction.
+ * 3. When you execute the new transaction, the lock held by the scan will
+ * be transferred to the new transaction(it's taken over).
+ *
+ * @note You must have started the scan with openScanExclusive
+ * to be able to update the found tuple.
+ *
+ * @param updateTrans the update transaction connection.
+ * @return an NdbOperation or NULL.
+ */
+ NdbOperation* updateTuple();
+ NdbOperation* updateTuple(NdbConnection* updateTrans);
+
+ /**
+ * Transfer scan operation to a deleting transaction. Use this function
+ * when a scan has found a record that you want to delete.
+ * 1. Start a new transaction.
+ * 2. Call the function takeOverForDelete using your new transaction
+ * as parameter, all the properties of the found record will be copied
+ * to the new transaction.
+ * 3. When you execute the new transaction, the lock held by the scan will
+ * be transferred to the new transaction(its taken over).
+ *
+ * @note You must have started the scan with openScanExclusive
+ * to be able to delete the found tuple.
+ *
+ * @param deleteTrans the delete transaction connection.
+ * @return an NdbOperation or NULL.
+ */
int deleteTuple();
int deleteTuple(NdbConnection* takeOverTransaction);
private:
- NdbResultSet(NdbCursorOperation*);
+ NdbResultSet(NdbScanOperation*);
~NdbResultSet();
void init();
- NdbCursorOperation* m_operation;
+ NdbScanOperation* m_operation;
};
#endif
diff --git a/ndb/include/ndbapi/NdbScanOperation.hpp b/ndb/include/ndbapi/NdbScanOperation.hpp
index 151dc5bb99f..c7ae029e742 100644
--- a/ndb/include/ndbapi/NdbScanOperation.hpp
+++ b/ndb/include/ndbapi/NdbScanOperation.hpp
@@ -29,9 +29,7 @@
#ifndef NdbScanOperation_H
#define NdbScanOperation_H
-
#include <NdbOperation.hpp>
-#include <NdbCursorOperation.hpp>
class NdbBlob;
@@ -39,63 +37,71 @@ class NdbBlob;
* @class NdbScanOperation
* @brief Class of scan operations for use in transactions.
*/
-class NdbScanOperation : public NdbCursorOperation
-{
+class NdbScanOperation : public NdbOperation {
friend class Ndb;
friend class NdbConnection;
friend class NdbResultSet;
friend class NdbOperation;
-
+ friend class NdbBlob;
public:
/**
+ * Type of cursor
+ */
+ enum CursorType {
+ NoCursor = 0,
+ ScanCursor = 1,
+ IndexCursor = 2
+ };
+
+ /**
+ * Lock when performing scan
+ */
+ enum LockMode {
+ LM_Read = 0,
+ LM_Exclusive = 1,
+ LM_CommittedRead = 2,
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ LM_Dirty = 2
+#endif
+ };
+
+ /**
+ * Type of cursor
+ */
+ CursorType get_cursor_type() const;
+
+ /**
* readTuples returns a NdbResultSet where tuples are stored.
* Tuples are not stored in NdbResultSet until execute(NoCommit)
* has been executed and nextResult has been called.
*
* @param parallel Scan parallelism
+ * @param batch No of rows to fetch from each fragment at a time
* @param LockMode Scan lock handling
* @returns NdbResultSet.
+ * @note specifying 0 for batch and parallall means max performance
*/
- virtual NdbResultSet* readTuples(unsigned parallel = 0,
- LockMode = LM_Read );
+ NdbResultSet* readTuples(LockMode = LM_Read,
+ Uint32 batch = 0, Uint32 parallel = 0);
+
+ inline NdbResultSet* readTuples(int parallell){
+ return readTuples(LM_Read, 0, parallell);
+ }
+
+ inline NdbResultSet* readTuplesExclusive(int parallell = 0){
+ return readTuples(LM_Exclusive, 0, parallell);
+ }
-#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
-
- int updateTuples();
- int updateTuples(Uint32 parallelism);
-
- int deleteTuples();
- int deleteTuples(Uint32 parallelism);
-
- // Overload setValue for updateTuples
- int setValue(const char* anAttrName, const char* aValue, Uint32 len = 0);
- int setValue(const char* anAttrName, Int32 aValue);
- int setValue(const char* anAttrName, Uint32 aValue);
- int setValue(const char* anAttrName, Int64 aValue);
- int setValue(const char* anAttrName, Uint64 aValue);
- int setValue(const char* anAttrName, float aValue);
- int setValue(const char* anAttrName, double aValue);
-
- int setValue(Uint32 anAttrId, const char* aValue, Uint32 len = 0);
- int setValue(Uint32 anAttrId, Int32 aValue);
- int setValue(Uint32 anAttrId, Uint32 aValue);
- int setValue(Uint32 anAttrId, Int64 aValue);
- int setValue(Uint32 anAttrId, Uint64 aValue);
- int setValue(Uint32 anAttrId, float aValue);
- int setValue(Uint32 anAttrId, double aValue);
-#endif
-
NdbBlob* getBlobHandle(const char* anAttrName);
NdbBlob* getBlobHandle(Uint32 anAttrId);
-private:
- NdbScanOperation(Ndb* aNdb);
+protected:
+ CursorType m_cursor_type;
+ NdbScanOperation(Ndb* aNdb);
~NdbScanOperation();
- NdbCursorOperation::CursorType cursorType();
-
- virtual int nextResult(bool fetchAllowed = true);
+ int nextResult(bool fetchAllowed = true);
virtual void release();
void closeScan();
@@ -111,125 +117,54 @@ private:
virtual void setErrorCode(int aErrorCode);
virtual void setErrorCodeAbort(int aErrorCode);
- virtual int equal_impl(const NdbColumnImpl* anAttrObject,
- const char* aValue,
- Uint32 len);
-private:
+ NdbResultSet * m_resultSet;
+ NdbResultSet* getResultSet();
NdbConnection *m_transConnection;
- bool m_autoExecute;
- bool m_updateOp;
- bool m_writeOp;
- bool m_deleteOp;
- class SetValueRecList* m_setValueList;
-};
-#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
-class AttrInfo;
-class SetValueRecList;
+ // Scan related variables
+ Uint32 theBatchSize;
+ Uint32 theParallelism;
+ Uint32 m_keyInfo;
+ NdbApiSignal* theSCAN_TABREQ;
-class SetValueRec {
- friend class SetValueRecList;
-public:
- SetValueRec();
- ~SetValueRec();
-
- enum SetValueType {
- SET_STRING_ATTR1 = 0,
- SET_INT32_ATTR1 = 1,
- SET_UINT32_ATTR1 = 2,
- SET_INT64_ATTR1 = 3,
- SET_UINT64_ATTR1 = 4,
- SET_FLOAT_ATTR1 = 5,
- SET_DOUBLE_ATTR1 = 6,
- SET_STRING_ATTR2 = 7,
- SET_INT32_ATTR2 = 8,
- SET_UINT32_ATTR2 = 9,
- SET_INT64_ATTR2 = 10,
- SET_UINT64_ATTR2 = 11,
- SET_FLOAT_ATTR2 = 12,
- SET_DOUBLE_ATTR2 = 13
- };
-
- SetValueType stype;
- union {
- char* anAttrName;
- Uint32 anAttrId;
- };
- struct String {
- char* aStringValue;
- Uint32 len;
- };
- union {
- String stringStruct;
- Int32 anInt32Value;
- Uint32 anUint32Value;
- Int64 anInt64Value;
- Uint64 anUint64Value;
- float aFloatValue;
- double aDoubleValue;
- };
-private:
- SetValueRec* next;
-};
-
-inline
-SetValueRec::SetValueRec() :
- next(0)
-{
-}
+ int getFirstATTRINFOScan();
+ int doSendScan(int ProcessorId);
+ int prepareSendScan(Uint32 TC_ConnectPtr, Uint64 TransactionId);
+
+ int fix_receivers(Uint32 parallel);
+ Uint32* m_array; // containing all arrays below
+ Uint32 m_allocated_receivers;
+ NdbReceiver** m_receivers; // All receivers
-class SetValueRecList {
-public:
- SetValueRecList();
- ~SetValueRecList();
-
- void add(const char* anAttrName, const char* aValue, Uint32 len = 0);
- void add(const char* anAttrName, Int32 aValue);
- void add(const char* anAttrName, Uint32 aValue);
- void add(const char* anAttrName, Int64 aValue);
- void add(const char* anAttrName, Uint64 aValue);
- void add(const char* anAttrName, float aValue);
- void add(const char* anAttrName, double aValue);
- void add(Uint32 anAttrId, const char* aValue, Uint32 len = 0);
- void add(Uint32 anAttrId, Int32 aValue);
- void add(Uint32 anAttrId, Uint32 aValue);
- void add(Uint32 anAttrId, Int64 aValue);
- void add(Uint32 anAttrId, Uint64 aValue);
- void add(Uint32 anAttrId, float aValue);
- void add(Uint32 anAttrId, double aValue);
-
- typedef void(* IterateFn)(SetValueRec&, NdbOperation&);
- static void callSetValueFn(SetValueRec&, NdbOperation&);
- void iterate(IterateFn nextfn, NdbOperation&);
-private:
- SetValueRec* first;
- SetValueRec* last;
-};
+ Uint32* m_prepared_receivers; // These are to be sent
+
+ Uint32 m_current_api_receiver;
+ Uint32 m_api_receivers_count;
+ NdbReceiver** m_api_receivers; // These are currently used by api
+
+ Uint32 m_conf_receivers_count; // NOTE needs mutex to access
+ NdbReceiver** m_conf_receivers; // receive thread puts them here
+
+ Uint32 m_sent_receivers_count; // NOTE needs mutex to access
+ NdbReceiver** m_sent_receivers; // receive thread puts them here
+
+ int send_next_scan(Uint32 cnt, bool close);
+ void receiver_delivered(NdbReceiver*);
+ void receiver_completed(NdbReceiver*);
+ void execCLOSE_SCAN_REP();
-inline
-SetValueRecList::SetValueRecList() :
- first(0),
- last(0)
-{
-}
+ int getKeyFromKEYINFO20(Uint32* data, unsigned size);
+ NdbOperation* takeOverScanOp(OperationType opType, NdbConnection*);
-inline
-SetValueRecList::~SetValueRecList() {
- if (first) delete first;
- first = last = 0;
-}
+ Uint32 m_ordered;
+ int restart();
+};
inline
-void SetValueRecList::iterate(SetValueRecList::IterateFn nextfn, NdbOperation& oper)
-{
- SetValueRec* recPtr = first;
- while(recPtr) {
- (*nextfn)(*recPtr, oper);
- recPtr = recPtr->next; // Move to next in list - MASV
- }
+NdbScanOperation::CursorType
+NdbScanOperation::get_cursor_type() const {
+ return m_cursor_type;
}
#endif
-
-#endif
diff --git a/ndb/include/portlib/NdbTCP.h b/ndb/include/portlib/NdbTCP.h
index 42c34855c39..4dc8435eef1 100644
--- a/ndb/include/portlib/NdbTCP.h
+++ b/ndb/include/portlib/NdbTCP.h
@@ -64,7 +64,7 @@ typedef int socklen_t;
#define NDB_NONBLOCK O_NONBLOCK
#define NDB_SOCKET_TYPE int
#define NDB_INVALID_SOCKET -1
-#define NDB_CLOSE_SOCKET(x) close(x)
+#define NDB_CLOSE_SOCKET(x) ::close(x)
#define InetErrno errno
diff --git a/ndb/include/transporter/TransporterDefinitions.hpp b/ndb/include/transporter/TransporterDefinitions.hpp
index cb859e310db..0301d12348f 100644
--- a/ndb/include/transporter/TransporterDefinitions.hpp
+++ b/ndb/include/transporter/TransporterDefinitions.hpp
@@ -69,6 +69,7 @@ struct TCP_TransporterConfiguration {
* SHM Transporter Configuration
*/
struct SHM_TransporterConfiguration {
+ Uint32 port;
NodeId remoteNodeId;
NodeId localNodeId;
bool compression;
diff --git a/ndb/include/transporter/TransporterRegistry.hpp b/ndb/include/transporter/TransporterRegistry.hpp
index 6c979777f18..3c6c307406c 100644
--- a/ndb/include/transporter/TransporterRegistry.hpp
+++ b/ndb/include/transporter/TransporterRegistry.hpp
@@ -29,20 +29,10 @@
#define TransporterRegistry_H
#include "TransporterDefinitions.hpp"
+#include <SocketServer.hpp>
#include <NdbTCP.h>
-// A transporter is always in a PerformState.
-// PerformIO is used initially and as long as any of the events
-// PerformConnect, ...
-enum PerformState {
- PerformNothing = 4, // Does nothing
- PerformIO = 0, // Is connected
- PerformConnect = 1, // Is trying to connect
- PerformDisconnect = 2, // Trying to disconnect
- RemoveTransporter = 3 // Will be removed
-};
-
// A transporter is always in an IOState.
// NoHalt is used initially and as long as it is no restrictions on
// sending or receiving.
@@ -60,18 +50,45 @@ enum TransporterType {
tt_OSE_TRANSPORTER = 4
};
+static const char *performStateString[] =
+ { "is connected",
+ "is trying to connect",
+ "does nothing",
+ "is trying to disconnect" };
+
class Transporter;
class TCP_Transporter;
class SCI_Transporter;
class SHM_Transporter;
class OSE_Transporter;
+class TransporterRegistry;
+class SocketAuthenticator;
+
+class TransporterService : public SocketServer::Service {
+ SocketAuthenticator * m_auth;
+ TransporterRegistry * m_transporter_registry;
+public:
+ TransporterService(SocketAuthenticator *auth= 0)
+ {
+ m_auth= auth;
+ m_transporter_registry= 0;
+ }
+ void setTransporterRegistry(TransporterRegistry *t)
+ {
+ m_transporter_registry= t;
+ }
+ SocketServer::Session * newSession(NDB_SOCKET_TYPE socket);
+};
+
/**
* @class TransporterRegistry
* @brief ...
*/
class TransporterRegistry {
friend class OSE_Receiver;
+ friend class Transporter;
+ friend class TransporterService;
public:
/**
* Constructor
@@ -98,6 +115,12 @@ public:
*/
~TransporterRegistry();
+ bool start_service(SocketServer& server);
+ bool start_clients();
+ bool stop_clients();
+ void start_clients_thread();
+ void update_connections();
+
/**
* Start/Stop receiving
*/
@@ -110,16 +133,26 @@ public:
void startSending();
void stopSending();
+ // A transporter is always in a PerformState.
+ // PerformIO is used initially and as long as any of the events
+ // PerformConnect, ...
+ enum PerformState {
+ CONNECTED = 0,
+ CONNECTING = 1,
+ DISCONNECTED = 2,
+ DISCONNECTING = 3
+ };
+ const char *getPerformStateString(NodeId nodeId) const
+ { return performStateString[(unsigned)performStates[nodeId]]; };
+
/**
* Get and set methods for PerformState
*/
- PerformState performState(NodeId nodeId);
- void setPerformState(NodeId nodeId, PerformState state);
-
- /**
- * Set perform state for all transporters
- */
- void setPerformState(PerformState state);
+ void do_connect(NodeId node_id);
+ void do_disconnect(NodeId node_id);
+ bool is_connected(NodeId node_id) { return performStates[node_id] == CONNECTED; };
+ void report_connect(NodeId node_id);
+ void report_disconnect(NodeId node_id, int errnum);
/**
* Get and set methods for IOState
@@ -174,8 +207,6 @@ public:
void performReceive();
void performSend();
- void checkConnections();
-
/**
* Force sending if more than or equal to sendLimit
* number have asked for send. Returns 0 if not sending
@@ -187,11 +218,18 @@ public:
void printState();
#endif
+ unsigned short m_service_port;
+
protected:
private:
void * callbackObj;
+ TransporterService *m_transporter_service;
+ char *m_interface_name;
+ struct NdbThread *m_start_clients_thread;
+ bool m_run_start_clients_thread;
+
int sendCounter;
NodeId localNodeId;
bool nodeIdSpecified;
@@ -202,11 +240,6 @@ private:
int nSHMTransporters;
int nOSETransporters;
- int m_ccCount;
- int m_ccIndex;
- int m_ccStep;
- int m_nTransportersPerformConnect;
- bool m_ccReady;
/**
* Arrays holding all transporters in the order they are created
*/
diff --git a/ndb/include/util/BaseString.hpp b/ndb/include/util/BaseString.hpp
index 8755c13e9bb..a1bb91ea9c5 100644
--- a/ndb/include/util/BaseString.hpp
+++ b/ndb/include/util/BaseString.hpp
@@ -176,7 +176,7 @@ public:
/**
* Trim string from <i>delim</i>
*/
- static char* trim(char * src, const char * delim = " \t");
+ static char* trim(char * src, const char * delim);
private:
char* m_chr;
unsigned m_len;
diff --git a/ndb/include/util/Bitmask.hpp b/ndb/include/util/Bitmask.hpp
index 7355742f845..bb217adab5f 100644
--- a/ndb/include/util/Bitmask.hpp
+++ b/ndb/include/util/Bitmask.hpp
@@ -19,11 +19,6 @@
#include <ndb_global.h>
-#ifndef NDB_ASSERT
-#define NDB_ASSERT(x, s) \
- do { if (!(x)) { printf("%s\n", s); abort(); } } while (0)
-#endif
-
/**
* Bitmask implementation. Size is given explicitly
* (as first argument). All methods are static.
@@ -140,7 +135,7 @@ public:
inline bool
BitmaskImpl::get(unsigned size, const Uint32 data[], unsigned n)
{
- NDB_ASSERT(n < (size << 5), "bit get out of range");
+ assert(n < (size << 5));
return (data[n >> 5] & (1 << (n & 31))) != 0;
}
@@ -153,7 +148,7 @@ BitmaskImpl::set(unsigned size, Uint32 data[], unsigned n, bool value)
inline void
BitmaskImpl::set(unsigned size, Uint32 data[], unsigned n)
{
- NDB_ASSERT(n < (size << 5), "bit set out of range");
+ assert(n < (size << 5));
data[n >> 5] |= (1 << (n & 31));
}
@@ -176,7 +171,7 @@ BitmaskImpl::assign(unsigned size, Uint32 dst[], const Uint32 src[])
inline void
BitmaskImpl::clear(unsigned size, Uint32 data[], unsigned n)
{
- NDB_ASSERT(n < (size << 5), "bit clear out of range");
+ assert(n < (size << 5));
data[n >> 5] &= ~(1 << (n & 31));
}
@@ -326,7 +321,7 @@ BitmaskImpl::getText(unsigned size, const Uint32 data[], char* buf)
* XXX replace size by length in bits
*/
template <unsigned size>
-class Bitmask {
+struct BitmaskPOD {
public:
/**
* POD data representation
@@ -334,7 +329,7 @@ public:
struct Data {
Uint32 data[size];
#if 0
- Data & operator=(const Bitmask<size> & src) {
+ Data & operator=(const BitmaskPOD<size> & src) {
src.copyto(size, data);
return *this;
}
@@ -348,19 +343,17 @@ public:
STATIC_CONST( NotFound = BitmaskImpl::NotFound );
STATIC_CONST( TextLength = size * 8 );
- Bitmask() { clear();}
-
/**
* assign - Set all bits in <em>dst</em> to corresponding in <em>src/<em>
*/
- void assign(const typename Bitmask<size>::Data & src);
+ void assign(const typename BitmaskPOD<size>::Data & src);
/**
* assign - Set all bits in <em>dst</em> to corresponding in <em>src/<em>
*/
static void assign(Uint32 dst[], const Uint32 src[]);
- static void assign(Uint32 dst[], const Bitmask<size> & src);
- void assign(const Bitmask<size> & src);
+ static void assign(Uint32 dst[], const BitmaskPOD<size> & src);
+ void assign(const BitmaskPOD<size> & src);
/**
* copy this to <em>dst</em>
@@ -432,43 +425,43 @@ public:
* equal - Bitwise equal.
*/
static bool equal(const Uint32 data[], const Uint32 data2[]);
- bool equal(const Bitmask<size>& mask2) const;
+ bool equal(const BitmaskPOD<size>& mask2) const;
/**
* bitOR - Bitwise (x | y) into first operand.
*/
static void bitOR(Uint32 data[], const Uint32 data2[]);
- Bitmask<size>& bitOR(const Bitmask<size>& mask2);
+ BitmaskPOD<size>& bitOR(const BitmaskPOD<size>& mask2);
/**
* bitAND - Bitwise (x & y) into first operand.
*/
static void bitAND(Uint32 data[], const Uint32 data2[]);
- Bitmask<size>& bitAND(const Bitmask<size>& mask2);
+ BitmaskPOD<size>& bitAND(const BitmaskPOD<size>& mask2);
/**
* bitANDC - Bitwise (x & ~y) into first operand.
*/
static void bitANDC(Uint32 data[], const Uint32 data2[]);
- Bitmask<size>& bitANDC(const Bitmask<size>& mask2);
+ BitmaskPOD<size>& bitANDC(const BitmaskPOD<size>& mask2);
/**
* bitXOR - Bitwise (x ^ y) into first operand.
*/
static void bitXOR(Uint32 data[], const Uint32 data2[]);
- Bitmask<size>& bitXOR(const Bitmask<size>& mask2);
+ BitmaskPOD<size>& bitXOR(const BitmaskPOD<size>& mask2);
/**
* contains - Check if all bits set in data2 (that) are also set in data (this)
*/
static bool contains(Uint32 data[], const Uint32 data2[]);
- bool contains(Bitmask<size> that);
+ bool contains(BitmaskPOD<size> that);
/**
- * overlaps - Check if any bit set in this Bitmask (data) is also set in that (data2)
+ * overlaps - Check if any bit set in this BitmaskPOD (data) is also set in that (data2)
*/
static bool overlaps(Uint32 data[], const Uint32 data2[]);
- bool overlaps(Bitmask<size> that);
+ bool overlaps(BitmaskPOD<size> that);
/**
* getText - Return as hex-digits (only for debug routines).
@@ -479,286 +472,292 @@ public:
template <unsigned size>
inline void
-Bitmask<size>::assign(Uint32 dst[], const Uint32 src[])
+BitmaskPOD<size>::assign(Uint32 dst[], const Uint32 src[])
{
BitmaskImpl::assign(size, dst, src);
}
template <unsigned size>
inline void
-Bitmask<size>::assign(Uint32 dst[], const Bitmask<size> & src)
+BitmaskPOD<size>::assign(Uint32 dst[], const BitmaskPOD<size> & src)
{
BitmaskImpl::assign(size, dst, src.rep.data);
}
template <unsigned size>
inline void
-Bitmask<size>::assign(const typename Bitmask<size>::Data & src)
+BitmaskPOD<size>::assign(const typename BitmaskPOD<size>::Data & src)
{
- assign(rep.data, src.data);
+ BitmaskPOD<size>::assign(rep.data, src.data);
}
template <unsigned size>
inline void
-Bitmask<size>::assign(const Bitmask<size> & src)
+BitmaskPOD<size>::assign(const BitmaskPOD<size> & src)
{
- assign(rep.data, src.rep.data);
+ BitmaskPOD<size>::assign(rep.data, src.rep.data);
}
template <unsigned size>
inline void
-Bitmask<size>::copyto(unsigned sz, Uint32 dst[]) const
+BitmaskPOD<size>::copyto(unsigned sz, Uint32 dst[]) const
{
BitmaskImpl::assign(sz, dst, rep.data);
}
template <unsigned size>
inline void
-Bitmask<size>::assign(unsigned sz, const Uint32 src[])
+BitmaskPOD<size>::assign(unsigned sz, const Uint32 src[])
{
BitmaskImpl::assign(sz, rep.data, src);
}
template <unsigned size>
inline bool
-Bitmask<size>::get(const Uint32 data[], unsigned n)
+BitmaskPOD<size>::get(const Uint32 data[], unsigned n)
{
return BitmaskImpl::get(size, data, n);
}
template <unsigned size>
inline bool
-Bitmask<size>::get(unsigned n) const
+BitmaskPOD<size>::get(unsigned n) const
{
- return get(rep.data, n);
+ return BitmaskPOD<size>::get(rep.data, n);
}
template <unsigned size>
inline void
-Bitmask<size>::set(Uint32 data[], unsigned n, bool value)
+BitmaskPOD<size>::set(Uint32 data[], unsigned n, bool value)
{
BitmaskImpl::set(size, data, n, value);
}
template <unsigned size>
inline void
-Bitmask<size>::set(unsigned n, bool value)
+BitmaskPOD<size>::set(unsigned n, bool value)
{
- set(rep.data, n, value);
+ BitmaskPOD<size>::set(rep.data, n, value);
}
template <unsigned size>
inline void
-Bitmask<size>::set(Uint32 data[], unsigned n)
+BitmaskPOD<size>::set(Uint32 data[], unsigned n)
{
BitmaskImpl::set(size, data, n);
}
template <unsigned size>
inline void
-Bitmask<size>::set(unsigned n)
+BitmaskPOD<size>::set(unsigned n)
{
- set(rep.data, n);
+ BitmaskPOD<size>::set(rep.data, n);
}
template <unsigned size>
inline void
-Bitmask<size>::set(Uint32 data[])
+BitmaskPOD<size>::set(Uint32 data[])
{
BitmaskImpl::set(size, data);
}
template <unsigned size>
inline void
-Bitmask<size>::set()
+BitmaskPOD<size>::set()
{
- set(rep.data);
+ BitmaskPOD<size>::set(rep.data);
}
template <unsigned size>
inline void
-Bitmask<size>::clear(Uint32 data[], unsigned n)
+BitmaskPOD<size>::clear(Uint32 data[], unsigned n)
{
BitmaskImpl::clear(size, data, n);
}
template <unsigned size>
inline void
-Bitmask<size>::clear(unsigned n)
+BitmaskPOD<size>::clear(unsigned n)
{
- clear(rep.data, n);
+ BitmaskPOD<size>::clear(rep.data, n);
}
template <unsigned size>
inline void
-Bitmask<size>::clear(Uint32 data[])
+BitmaskPOD<size>::clear(Uint32 data[])
{
BitmaskImpl::clear(size, data);
}
template <unsigned size>
inline void
-Bitmask<size>::clear()
+BitmaskPOD<size>::clear()
{
- clear(rep.data);
+ BitmaskPOD<size>::clear(rep.data);
}
template <unsigned size>
inline bool
-Bitmask<size>::isclear(const Uint32 data[])
+BitmaskPOD<size>::isclear(const Uint32 data[])
{
return BitmaskImpl::isclear(size, data);
}
template <unsigned size>
inline bool
-Bitmask<size>::isclear() const
+BitmaskPOD<size>::isclear() const
{
- return isclear(rep.data);
+ return BitmaskPOD<size>::isclear(rep.data);
}
template <unsigned size>
unsigned
-Bitmask<size>::count(const Uint32 data[])
+BitmaskPOD<size>::count(const Uint32 data[])
{
return BitmaskImpl::count(size, data);
}
template <unsigned size>
inline unsigned
-Bitmask<size>::count() const
+BitmaskPOD<size>::count() const
{
- return count(rep.data);
+ return BitmaskPOD<size>::count(rep.data);
}
template <unsigned size>
unsigned
-Bitmask<size>::find(const Uint32 data[], unsigned n)
+BitmaskPOD<size>::find(const Uint32 data[], unsigned n)
{
return BitmaskImpl::find(size, data, n);
}
template <unsigned size>
inline unsigned
-Bitmask<size>::find(unsigned n) const
+BitmaskPOD<size>::find(unsigned n) const
{
- return find(rep.data, n);
+ return BitmaskPOD<size>::find(rep.data, n);
}
template <unsigned size>
inline bool
-Bitmask<size>::equal(const Uint32 data[], const Uint32 data2[])
+BitmaskPOD<size>::equal(const Uint32 data[], const Uint32 data2[])
{
return BitmaskImpl::equal(size, data, data2);
}
template <unsigned size>
inline bool
-Bitmask<size>::equal(const Bitmask<size>& mask2) const
+BitmaskPOD<size>::equal(const BitmaskPOD<size>& mask2) const
{
- return equal(rep.data, mask2.rep.data);
+ return BitmaskPOD<size>::equal(rep.data, mask2.rep.data);
}
template <unsigned size>
inline void
-Bitmask<size>::bitOR(Uint32 data[], const Uint32 data2[])
+BitmaskPOD<size>::bitOR(Uint32 data[], const Uint32 data2[])
{
BitmaskImpl::bitOR(size,data, data2);
}
template <unsigned size>
-inline Bitmask<size>&
-Bitmask<size>::bitOR(const Bitmask<size>& mask2)
+inline BitmaskPOD<size>&
+BitmaskPOD<size>::bitOR(const BitmaskPOD<size>& mask2)
{
- bitOR(rep.data, mask2.rep.data);
+ BitmaskPOD<size>::bitOR(rep.data, mask2.rep.data);
return *this;
}
template <unsigned size>
inline void
-Bitmask<size>::bitAND(Uint32 data[], const Uint32 data2[])
+BitmaskPOD<size>::bitAND(Uint32 data[], const Uint32 data2[])
{
BitmaskImpl::bitAND(size,data, data2);
}
template <unsigned size>
-inline Bitmask<size>&
-Bitmask<size>::bitAND(const Bitmask<size>& mask2)
+inline BitmaskPOD<size>&
+BitmaskPOD<size>::bitAND(const BitmaskPOD<size>& mask2)
{
- bitAND(rep.data, mask2.rep.data);
+ BitmaskPOD<size>::bitAND(rep.data, mask2.rep.data);
return *this;
}
template <unsigned size>
inline void
-Bitmask<size>::bitANDC(Uint32 data[], const Uint32 data2[])
+BitmaskPOD<size>::bitANDC(Uint32 data[], const Uint32 data2[])
{
BitmaskImpl::bitANDC(size,data, data2);
}
template <unsigned size>
-inline Bitmask<size>&
-Bitmask<size>::bitANDC(const Bitmask<size>& mask2)
+inline BitmaskPOD<size>&
+BitmaskPOD<size>::bitANDC(const BitmaskPOD<size>& mask2)
{
- bitANDC(rep.data, mask2.rep.data);
+ BitmaskPOD<size>::bitANDC(rep.data, mask2.rep.data);
return *this;
}
template <unsigned size>
inline void
-Bitmask<size>::bitXOR(Uint32 data[], const Uint32 data2[])
+BitmaskPOD<size>::bitXOR(Uint32 data[], const Uint32 data2[])
{
BitmaskImpl::bitXOR(size,data, data2);
}
template <unsigned size>
-inline Bitmask<size>&
-Bitmask<size>::bitXOR(const Bitmask<size>& mask2)
+inline BitmaskPOD<size>&
+BitmaskPOD<size>::bitXOR(const BitmaskPOD<size>& mask2)
{
- bitXOR(rep.data, mask2.rep.data);
+ BitmaskPOD<size>::bitXOR(rep.data, mask2.rep.data);
return *this;
}
template <unsigned size>
char *
-Bitmask<size>::getText(const Uint32 data[], char* buf)
+BitmaskPOD<size>::getText(const Uint32 data[], char* buf)
{
return BitmaskImpl::getText(size, data, buf);
}
template <unsigned size>
inline char *
-Bitmask<size>::getText(char* buf) const
+BitmaskPOD<size>::getText(char* buf) const
{
- return getText(rep.data, buf);
+ return BitmaskPOD<size>::getText(rep.data, buf);
}
template <unsigned size>
inline bool
-Bitmask<size>::contains(Uint32 data[], const Uint32 data2[])
+BitmaskPOD<size>::contains(Uint32 data[], const Uint32 data2[])
{
return BitmaskImpl::contains(size, data, data2);
}
template <unsigned size>
inline bool
-Bitmask<size>::contains(Bitmask<size> that)
+BitmaskPOD<size>::contains(BitmaskPOD<size> that)
{
- return contains(this->rep.data, that.rep.data);
+ return BitmaskPOD<size>::contains(this->rep.data, that.rep.data);
}
template <unsigned size>
inline bool
-Bitmask<size>::overlaps(Uint32 data[], const Uint32 data2[])
+BitmaskPOD<size>::overlaps(Uint32 data[], const Uint32 data2[])
{
return BitmaskImpl::overlaps(size, data, data2);
}
template <unsigned size>
inline bool
-Bitmask<size>::overlaps(Bitmask<size> that)
+BitmaskPOD<size>::overlaps(BitmaskPOD<size> that)
{
- return overlaps(this->rep.data, that.rep.data);
+ return BitmaskPOD<size>::overlaps(this->rep.data, that.rep.data);
}
+template <unsigned size>
+class Bitmask : public BitmaskPOD<size> {
+public:
+ Bitmask() { this->clear();}
+};
+
#endif
diff --git a/ndb/include/util/ConfigValues.hpp b/ndb/include/util/ConfigValues.hpp
index 3fbeedb25a0..457488e3c42 100644
--- a/ndb/include/util/ConfigValues.hpp
+++ b/ndb/include/util/ConfigValues.hpp
@@ -32,9 +32,8 @@ public:
class ConstIterator {
friend class ConfigValuesFactory;
const ConfigValues & m_cfg;
- protected:
- Uint32 m_currentSection;
public:
+ Uint32 m_currentSection;
ConstIterator(const ConfigValues&c) : m_cfg(c) { m_currentSection = 0;}
bool openSection(Uint32 key, Uint32 no);
@@ -57,6 +56,9 @@ public:
ConfigValues & m_cfg;
public:
Iterator(ConfigValues&c) : ConstIterator(c), m_cfg(c) {}
+ Iterator(ConfigValues&c, const ConstIterator& i):ConstIterator(c),m_cfg(c){
+ m_currentSection = i.m_currentSection;
+ }
bool set(Uint32 key, Uint32 value);
bool set(Uint32 key, Uint64 value);
diff --git a/ndb/include/util/NdbSqlUtil.hpp b/ndb/include/util/NdbSqlUtil.hpp
index 841da513d4a..a79245868e0 100644
--- a/ndb/include/util/NdbSqlUtil.hpp
+++ b/ndb/include/util/NdbSqlUtil.hpp
@@ -17,8 +17,7 @@
#ifndef NDB_SQL_UTIL_HPP
#define NDB_SQL_UTIL_HPP
-#include <string.h>
-#include <ndb_types.h>
+#include <ndb_global.h>
#include <kernel/ndb_limits.h>
class NdbSqlUtil {
@@ -80,7 +79,7 @@ public:
Datetime, // Precision down to 1 sec (size 8 bytes)
Timespec, // Precision down to 1 nsec (size 12 bytes)
Blob, // Blob
- Clob // Text blob
+ Text // Text blob
};
Enum m_typeId;
Cmp* m_cmp; // set to NULL if cmp not implemented
@@ -125,12 +124,13 @@ private:
static Cmp cmpDatetime;
static Cmp cmpTimespec;
static Cmp cmpBlob;
- static Cmp cmpClob;
+ static Cmp cmpText;
};
inline int
NdbSqlUtil::cmp(Uint32 typeId, const Uint32* p1, const Uint32* p2, Uint32 full, Uint32 size)
{
+ // XXX require size >= 1
if (size > full)
return CmpError;
switch ((Type::Enum)typeId) {
@@ -192,10 +192,38 @@ NdbSqlUtil::cmp(Uint32 typeId, const Uint32* p1, const Uint32* p2, Uint32 full,
}
return CmpUnknown;
}
- case Type::Mediumint: // XXX fix these
- break;
+ case Type::Mediumint:
+ {
+ if (size >= 1) {
+ union { const Uint32* p; const unsigned char* v; } u1, u2;
+ u1.p = p1;
+ u2.p = p2;
+ Int32 v1 = sint3korr(u1.v);
+ Int32 v2 = sint3korr(u2.v);
+ if (v1 < v2)
+ return -1;
+ if (v1 > v2)
+ return +1;
+ return 0;
+ }
+ return CmpUnknown;
+ }
case Type::Mediumunsigned:
- break;
+ {
+ if (size >= 1) {
+ union { const Uint32* p; const unsigned char* v; } u1, u2;
+ u1.p = p1;
+ u2.p = p2;
+ Uint32 v1 = uint3korr(u1.v);
+ Uint32 v2 = uint3korr(u2.v);
+ if (v1 < v2)
+ return -1;
+ if (v1 > v2)
+ return +1;
+ return 0;
+ }
+ return CmpUnknown;
+ }
case Type::Int:
{
if (size >= 1) {
@@ -287,6 +315,7 @@ NdbSqlUtil::cmp(Uint32 typeId, const Uint32* p1, const Uint32* p2, Uint32 full,
return CmpUnknown;
}
case Type::Decimal:
+ // XXX not used by MySQL or NDB
break;
case Type::Char:
{
@@ -317,10 +346,28 @@ NdbSqlUtil::cmp(Uint32 typeId, const Uint32* p1, const Uint32* p2, Uint32 full,
}
return CmpUnknown;
}
- case Type::Binary: // XXX fix these
- break;
+ case Type::Binary:
+ {
+ // compare byte wise
+ union { const Uint32* p; const char* v; } u1, u2;
+ u1.p = p1;
+ u2.p = p2;
+ int k = memcmp(u1.v, u2.v, size << 2);
+ return k < 0 ? -1 : k > 0 ? +1 : full == size ? 0 : CmpUnknown;
+ }
case Type::Varbinary:
- break;
+ {
+ // assume correctly padded and compare byte wise
+ if (size >= 1) {
+ union { const Uint32* p; const char* v; } u1, u2;
+ u1.p = p1;
+ u2.p = p2;
+ // length in first 2 bytes
+ int k = memcmp(u1.v + 2, u2.v + 2, (size << 2) - 2);
+ return k < 0 ? -1 : k > 0 ? +1 : full == size ? 0 : CmpUnknown;
+ }
+ return CmpUnknown;
+ }
case Type::Datetime:
{
/*
@@ -331,29 +378,66 @@ NdbSqlUtil::cmp(Uint32 typeId, const Uint32* p1, const Uint32* p2, Uint32 full,
u1.p = p1;
u2.p = p2;
// skip format check
- int k = strncmp(u1.v, u2.v, 4);
+ int k = memcmp(u1.v, u2.v, 4);
if (k != 0)
- return k;
+ return k < 0 ? -1 : +1;
if (size >= 2) {
- return strncmp(u1.v + 4, u2.v + 4, 4);
+ k = memcmp(u1.v + 4, u2.v + 4, 4);
+ return k < 0 ? -1 : k > 0 ? +1 : 0;
}
}
return CmpUnknown;
}
- case Type::Timespec: // XXX fix this
- break;
- case Type::Blob: // XXX fix
- break;
- case Type::Clob:
+ case Type::Timespec:
+ {
+ /*
+ * Timespec is CC YY MM DD hh mm ss \0 NN NN NN NN
+ */
+ if (size >= 1) {
+ union { const Uint32* p; const char* v; } u1, u2;
+ u1.p = p1;
+ u2.p = p2;
+ // skip format check
+ int k = memcmp(u1.v, u2.v, 4);
+ if (k != 0)
+ return k < 0 ? -1 : +1;
+ if (size >= 2) {
+ k = memcmp(u1.v + 4, u2.v + 4, 4);
+ if (k != 0)
+ return k < 0 ? -1 : +1;
+ Uint32 n1 = *(const Uint32*)(u1.v + 8);
+ Uint32 n2 = *(const Uint32*)(u2.v + 8);
+ if (n1 < n2)
+ return -1;
+ if (n2 > n1)
+ return +1;
+ return 0;
+ }
+ }
+ return CmpUnknown;
+ }
+ case Type::Blob:
{
- // skip blob head, the rest is varchar
+ // skip blob head, the rest is binary
const unsigned skip = NDB_BLOB_HEAD_SIZE;
if (size >= skip + 1) {
union { const Uint32* p; const char* v; } u1, u2;
u1.p = p1 + skip;
u2.p = p2 + skip;
- // length in first 2 bytes
- int k = strncmp(u1.v + 2, u2.v + 2, ((size - skip) << 2) - 2);
+ int k = memcmp(u1.v, u2.v, (size - 1) << 2);
+ return k < 0 ? -1 : k > 0 ? +1 : full == size ? 0 : CmpUnknown;
+ }
+ return CmpUnknown;
+ }
+ case Type::Text:
+ {
+ // skip blob head, the rest is char
+ const unsigned skip = NDB_BLOB_HEAD_SIZE;
+ if (size >= skip + 1) {
+ union { const Uint32* p; const char* v; } u1, u2;
+ u1.p = p1 + skip;
+ u2.p = p2 + skip;
+ int k = memcmp(u1.v, u2.v, (size - 1) << 2);
return k < 0 ? -1 : k > 0 ? +1 : full == size ? 0 : CmpUnknown;
}
return CmpUnknown;
diff --git a/ndb/include/util/Properties.hpp b/ndb/include/util/Properties.hpp
index 2c30f7f7e3c..df8e2887001 100644
--- a/ndb/include/util/Properties.hpp
+++ b/ndb/include/util/Properties.hpp
@@ -55,7 +55,7 @@ public:
static const char delimiter = ':';
static const char version[];
- Properties();
+ Properties(bool case_insensitive= false);
Properties(const Properties &);
Properties(const Property *, int len);
virtual ~Properties();
diff --git a/ndb/include/util/SocketAuthenticator.hpp b/ndb/include/util/SocketAuthenticator.hpp
new file mode 100644
index 00000000000..1b82567feaa
--- /dev/null
+++ b/ndb/include/util/SocketAuthenticator.hpp
@@ -0,0 +1,39 @@
+/* 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 SOCKET_AUTHENTICATOR_HPP
+#define SOCKET_AUTHENTICATOR_HPP
+
+class SocketAuthenticator
+{
+public:
+ virtual ~SocketAuthenticator() {};
+ virtual bool client_authenticate(int sockfd) = 0;
+ virtual bool server_authenticate(int sockfd) = 0;
+};
+
+class SocketAuthSimple : public SocketAuthenticator
+{
+ const char *m_passwd;
+ const char *m_username;
+public:
+ SocketAuthSimple(const char *username, const char *passwd);
+ virtual ~SocketAuthSimple();
+ virtual bool client_authenticate(int sockfd);
+ virtual bool server_authenticate(int sockfd);
+};
+
+#endif // SOCKET_AUTHENTICATOR_HPP
diff --git a/ndb/include/util/SocketClient.hpp b/ndb/include/util/SocketClient.hpp
new file mode 100644
index 00000000000..de9a081464a
--- /dev/null
+++ b/ndb/include/util/SocketClient.hpp
@@ -0,0 +1,38 @@
+/* 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 SOCKET_CLIENT_HPP
+#define SOCKET_CLIENT_HPP
+
+#include <NdbTCP.h>
+class SocketAuthenticator;
+
+class SocketClient
+{
+ NDB_SOCKET_TYPE m_sockfd;
+ struct sockaddr_in m_servaddr;
+ unsigned short m_port;
+ char *m_server_name;
+ SocketAuthenticator *m_auth;
+public:
+ SocketClient(const char *server_name, unsigned short port, SocketAuthenticator *sa = 0);
+ ~SocketClient();
+ bool init();
+ NDB_SOCKET_TYPE connect();
+ bool close();
+};
+
+#endif // SOCKET_ClIENT_HPP
diff --git a/ndb/src/common/debugger/DebuggerNames.cpp b/ndb/src/common/debugger/DebuggerNames.cpp
index ebe94a6059f..2142138e435 100644
--- a/ndb/src/common/debugger/DebuggerNames.cpp
+++ b/ndb/src/common/debugger/DebuggerNames.cpp
@@ -29,10 +29,11 @@ static const char * localBlockNames[NO_OF_BLOCKS];
static
int
initSignalNames(const char * dst[], const GsnName src[], unsigned short len){
- for(int i = 0; i<=MAX_GSN; i++)
+ int i;
+ for(i = 0; i<=MAX_GSN; i++)
dst[i] = 0;
- for(int i = 0; i<len; i++){
+ for(i = 0; i<len; i++){
unsigned short gsn = src[i].gsn;
const char * name = src[i].name;
@@ -54,10 +55,11 @@ int
initSignalPrinters(SignalDataPrintFunction dst[],
const NameFunctionPair src[],
unsigned short len){
- for(int i = 0; i<=MAX_GSN; i++)
+ int i;
+ for(i = 0; i<=MAX_GSN; i++)
dst[i] = 0;
- for(int i = 0; i<len; i++){
+ for(i = 0; i<len; i++){
unsigned short gsn = src[i].gsn;
SignalDataPrintFunction fun = src[i].function;
@@ -79,10 +81,11 @@ int
initBlockNames(const char * dst[],
const BlockName src[],
unsigned len){
- for(int i = 0; i<NO_OF_BLOCKS; i++)
+ int i;
+ for(i = 0; i<NO_OF_BLOCKS; i++)
dst[i] = 0;
- for(unsigned i = 0; i<len; i++){
+ for(i = 0; i<len; i++){
const int index = src[i].number - MIN_BLOCK_NO;
if(index < 0 && index >= NO_OF_BLOCKS || dst[index] != 0){
fprintf(stderr,
diff --git a/ndb/src/common/debugger/EventLogger.cpp b/ndb/src/common/debugger/EventLogger.cpp
index dd957d67383..50c3b778731 100644
--- a/ndb/src/common/debugger/EventLogger.cpp
+++ b/ndb/src/common/debugger/EventLogger.cpp
@@ -135,7 +135,7 @@ EventLogger::defEventLogMatrixSize = sizeof(EventLogger::defEventLogMatrix)/
*/
const EventLogger::EventCategoryName EventLogger::eventCategoryNames[] = {
{ LogLevel::llStartUp, "STARTUP" },
- { LogLevel::llStatistic, "STATISTIC" },
+ { LogLevel::llStatistic, "STATISTICS" },
{ LogLevel::llCheckpoint, "CHECKPOINT" },
{ LogLevel::llNodeRestart, "NODERESTART" },
{ LogLevel::llConnection, "CONNECTION" },
@@ -1303,14 +1303,15 @@ bool
EventLogger::matchEventCategory(const char * str,
LogLevel::EventCategory * cat,
bool exactMatch){
+ unsigned i;
if(cat == 0 || str == 0)
return false;
char * tmp = strdup(str);
- for(size_t i = 0; i<strlen(tmp); i++)
+ for(i = 0; i<strlen(tmp); i++)
tmp[i] = toupper(tmp[i]);
- for(Uint32 i = 0; i<noOfEventCategoryNames; i++){
+ for(i = 0; i<noOfEventCategoryNames; i++){
if(strcmp(tmp, eventCategoryNames[i].name) == 0){
* cat = eventCategoryNames[i].category;
free(tmp);
@@ -1350,15 +1351,6 @@ EventLogger::EventLogger() : Logger(), m_logLevel(), m_filterLevel(15)
EventLogger::~EventLogger()
{
-
-}
-
-bool
-EventLogger::open()
-{
- char clusterLog[128];
- NdbConfig_ClusterLogFileName(clusterLog, 128);
- return open(clusterLog);
}
bool
diff --git a/ndb/src/common/debugger/SignalLoggerManager.cpp b/ndb/src/common/debugger/SignalLoggerManager.cpp
index 3839a348222..d642ed09a68 100644
--- a/ndb/src/common/debugger/SignalLoggerManager.cpp
+++ b/ndb/src/common/debugger/SignalLoggerManager.cpp
@@ -488,31 +488,6 @@ SignalLoggerManager::printLinearSection(FILE * output,
}
void
-SignalLoggerManager::printSegmentedSection(FILE * output,
- const SignalHeader & sh,
- const SegmentedSectionPtr ptr[3],
- unsigned i)
-{
- fprintf(output, "SECTION %u type=segmented", i);
- if (i >= 3) {
- fprintf(output, " *** invalid ***\n");
- return;
- }
- const Uint32 len = ptr[i].sz;
- SectionSegment * ssp = ptr[i].p;
- Uint32 pos = 0;
- fprintf(output, " size=%u\n", (unsigned)len);
- while (pos < len) {
- if (pos > 0 && pos % SectionSegment::DataLength == 0) {
- ssp = g_sectionSegmentPool.getPtr(ssp->m_nextSegment);
- }
- printDataWord(output, pos, ssp->theData[pos % SectionSegment::DataLength]);
- }
- if (len > 0)
- putc('\n', output);
-}
-
-void
SignalLoggerManager::printDataWord(FILE * output, Uint32 & pos, const Uint32 data)
{
const char* const hex = "0123456789abcdef";
diff --git a/ndb/src/common/debugger/signaldata/DictTabInfo.cpp b/ndb/src/common/debugger/signaldata/DictTabInfo.cpp
index a0e0195adad..7e7bf87e2db 100644
--- a/ndb/src/common/debugger/signaldata/DictTabInfo.cpp
+++ b/ndb/src/common/debugger/signaldata/DictTabInfo.cpp
@@ -48,6 +48,7 @@ DictTabInfo::TableMapping[] = {
DTIMAP(Table, CustomTriggerId, CustomTriggerId),
DTIMAP2(Table, FrmLen, FrmLen, 0, MAX_FRM_DATA_SIZE),
DTIMAPB(Table, FrmData, FrmData, 0, MAX_FRM_DATA_SIZE, FrmLen),
+ DTIMAP(Table, FragmentCount, FragmentCount),
DTIBREAK(AttributeName)
};
@@ -128,6 +129,7 @@ DictTabInfo::Table::init(){
CustomTriggerId = RNIL;
FrmLen = 0;
memset(FrmData, 0, sizeof(FrmData));
+ FragmentCount = 0;
}
void
diff --git a/ndb/src/common/debugger/signaldata/LCP.cpp b/ndb/src/common/debugger/signaldata/LCP.cpp
index 825659d13b3..6b4bb13e2cd 100644
--- a/ndb/src/common/debugger/signaldata/LCP.cpp
+++ b/ndb/src/common/debugger/signaldata/LCP.cpp
@@ -25,7 +25,8 @@ printSTART_LCP_REQ(FILE * output, const Uint32 * theData,
const StartLcpReq * const sig = (StartLcpReq *) theData;
- char buf1[sig->participatingDIH.TextLength+1], buf2[sig->participatingLQH.TextLength+1];
+ char buf1[8*_NDB_NODE_BITMASK_SIZE+1];
+ char buf2[8*_NDB_NODE_BITMASK_SIZE+1];
fprintf(output,
" Sender: %d LcpId: %d\n"
" ParticipatingDIH = %s\n"
diff --git a/ndb/src/common/debugger/signaldata/Makefile.am b/ndb/src/common/debugger/signaldata/Makefile.am
index 0d6ed45dcef..0a5806e1e00 100644
--- a/ndb/src/common/debugger/signaldata/Makefile.am
+++ b/ndb/src/common/debugger/signaldata/Makefile.am
@@ -22,7 +22,7 @@ libsignaldataprint_la_SOURCES = \
CopyGCI.cpp SystemError.cpp StartRec.cpp NFCompleteRep.cpp \
FailRep.cpp DisconnectRep.cpp SignalDroppedRep.cpp \
SumaImpl.cpp NdbSttor.cpp CreateFragmentation.cpp \
- UtilLock.cpp TuxMaint.cpp TupAccess.cpp AccLock.cpp \
+ UtilLock.cpp TuxMaint.cpp AccLock.cpp \
LqhTrans.cpp ReadNodesConf.cpp CntrStart.cpp
include $(top_srcdir)/ndb/config/common.mk.am
@@ -30,3 +30,4 @@ include $(top_srcdir)/ndb/config/type_ndbapi.mk.am
# Don't update the files from bitkeeper
%::SCCS/s.%
+
diff --git a/ndb/src/common/debugger/signaldata/ScanTab.cpp b/ndb/src/common/debugger/signaldata/ScanTab.cpp
index b4246059f6a..4b057171963 100644
--- a/ndb/src/common/debugger/signaldata/ScanTab.cpp
+++ b/ndb/src/common/debugger/signaldata/ScanTab.cpp
@@ -30,20 +30,34 @@ printSCANTABREQ(FILE * output, const Uint32 * theData, Uint32 len, Uint16 receiv
fprintf(output, " apiConnectPtr: H\'%.8x\n",
sig->apiConnectPtr);
fprintf(output, " requestInfo: H\'%.8x:\n", requestInfo);
- fprintf(output, " Parallellism: %u, LockMode: %u, Holdlock: %u, RangeScan: %u\n",
- sig->getParallelism(requestInfo), sig->getLockMode(requestInfo), sig->getHoldLockFlag(requestInfo), sig->getRangeScanFlag(requestInfo));
-
+ fprintf(output, " Parallellism: %u, Batch: %u LockMode: %u, Holdlock: %u, RangeScan: %u\n",
+ sig->getParallelism(requestInfo),
+ sig->getScanBatch(requestInfo),
+ sig->getLockMode(requestInfo),
+ sig->getHoldLockFlag(requestInfo),
+ sig->getRangeScanFlag(requestInfo));
+
fprintf(output, " attrLen: %d, tableId: %d, tableSchemaVer: %d\n",
sig->attrLen, sig->tableId, sig->tableSchemaVersion);
fprintf(output, " transId(1, 2): (H\'%.8x, H\'%.8x) storedProcId: H\'%.8x\n",
sig->transId1, sig->transId2, sig->storedProcId);
- fprintf(output, " OperationPtr(s):\n");
- for(int i = 0; i<16; i=i+4){
- fprintf(output, " H\'%.8x, H\'%.8x, H\'%.8x, H\'%.8x\n",
- sig->apiOperationPtr[i], sig->apiOperationPtr[i+1],
- sig->apiOperationPtr[i+2], sig->apiOperationPtr[i+3]);
+ fprintf(output, " OperationPtr(s):\n ");
+ Uint32 restLen = (len - 9);
+ const Uint32 * rest = &sig->apiOperationPtr[0];
+ while(restLen >= 7){
+ fprintf(output,
+ " H\'%.8x H\'%.8x H\'%.8x H\'%.8x H\'%.8x H\'%.8x H\'%.8x\n",
+ rest[0], rest[1], rest[2], rest[3],
+ rest[4], rest[5], rest[6]);
+ restLen -= 7;
+ rest += 7;
+ }
+ if(restLen > 0){
+ for(Uint32 i = 0; i<restLen; i++)
+ fprintf(output, " H\'%.8x", rest[i]);
+ fprintf(output, "\n");
}
return false;
}
@@ -60,51 +74,28 @@ printSCANTABCONF(FILE * output, const Uint32 * theData, Uint32 len, Uint16 recei
fprintf(output, " transId(1, 2): (H\'%.8x, H\'%.8x)\n",
sig->transId1, sig->transId2);
- fprintf(output, " requestInfo: H\'%.8x(Operations: %u, ScanStatus: %u(\"",
- requestInfo, sig->getOperations(requestInfo), sig->getScanStatus(requestInfo));
- switch(sig->getScanStatus(requestInfo)){
- case 0:
- fprintf(output, "ZFALSE");
- break;
- case 1:
- fprintf(output, "ZTRUE");
- break;
- case 2:
- fprintf(output, "ZCLOSED");
- break;
- default:
- fprintf(output, "UNKNOWN");
- break;
+ fprintf(output, " requestInfo: Eod: %d OpCount: %d\n",
+ (requestInfo & ScanTabConf::EndOfData == ScanTabConf::EndOfData),
+ (requestInfo & (~ScanTabConf::EndOfData)));
+ size_t op_count= requestInfo & (~ScanTabConf::EndOfData);
+ if(op_count){
+ fprintf(output, " Operation(s) [api tc rows len]:\n");
+ ScanTabConf::OpData * op = (ScanTabConf::OpData*)
+ (theData + ScanTabConf::SignalLength);
+ for(int i = 0; i<op_count; i++){
+ if(op->info != ScanTabConf::EndOfData)
+ fprintf(output, " [0x%x 0x%x %d %d]",
+ op->apiPtrI, op->tcPtrI,
+ ScanTabConf::getRows(op->info),
+ ScanTabConf::getLength(op->info));
+ else
+ fprintf(output, " [0x%x 0x%x eod]",
+ op->apiPtrI, op->tcPtrI);
+
+ op++;
+ }
+ fprintf(output, "\n");
}
- fprintf(output, "\"))\n");
-#if 0
- fprintf(output, " Operation(s):\n");
- for(int i = 0; i<16; i++){
- fprintf(output, " [%.2u]ix=%d l=%.2d,",
- i, sig->getIdx(sig->operLenAndIdx[i]), sig->getLen(sig->operLenAndIdx[i]));
- if (((i+1) % 4) == 0)
- fprintf(output, "\n");
- }
-#endif
- return false;
-}
-
-bool
-printSCANTABINFO(FILE * output, const Uint32 * theData, Uint32 len, Uint16 receiverBlockNo){
-
- const ScanTabInfo * const sig = (ScanTabInfo *) theData;
-
- fprintf(output, " apiConnectPtr: H\'%.8x\n",
- sig->apiConnectPtr);
-
- fprintf(output, " Operation(s):\n");
- for(int i = 0; i<16; i++){
- fprintf(output, " [%.2u]ix=%d l=%.2d,",
- i, sig->getIdx(sig->operLenAndIdx[i]), sig->getLen(sig->operLenAndIdx[i]));
- if (((i+1) % 4) == 0)
- fprintf(output, "\n");
- }
-
return false;
}
@@ -120,8 +111,8 @@ printSCANTABREF(FILE * output, const Uint32 * theData, Uint32 len, Uint16 receiv
sig->transId1, sig->transId2);
fprintf(output, " Errorcode: %u\n", sig->errorCode);
-
- // fprintf(output, " sendScanNextReqWithClose: %u\n", sig->sendScanNextReqWithClose);
+
+ fprintf(output, " closeNeeded: %u\n", sig->closeNeeded);
return false;
}
@@ -147,13 +138,21 @@ printSCANNEXTREQ(FILE * output, const Uint32 * theData, Uint32 len, Uint16 recei
if(receiverBlockNo == DBTC){
const ScanNextReq * const sig = (ScanNextReq *) theData;
- fprintf(output, " aipConnectPtr: H\'%.8x\n",
+ fprintf(output, " apiConnectPtr: H\'%.8x\n",
sig->apiConnectPtr);
- fprintf(output, " transId(1, 2): (H\'%.8x, H\'%.8x)\n",
+ fprintf(output, " transId(1, 2): (H\'%.8x, H\'%.8x) ",
sig->transId1, sig->transId2);
fprintf(output, " Stop this scan: %u\n", sig->stopScan);
+
+ const Uint32 * ops = theData + ScanNextReq::SignalLength;
+ if(len > ScanNextReq::SignalLength){
+ fprintf(output, " tcFragPtr(s): ");
+ for(size_t i = ScanNextReq::SignalLength; i<len; i++)
+ fprintf(output, " 0x%x", * ops++);
+ fprintf(output, "\n");
+ }
}
if (receiverBlockNo == DBLQH){
return printSCANFRAGNEXTREQ(output, theData, len, receiverBlockNo);
diff --git a/ndb/src/common/debugger/signaldata/SignalDataPrint.cpp b/ndb/src/common/debugger/signaldata/SignalDataPrint.cpp
index d49e316ad38..65351663789 100644
--- a/ndb/src/common/debugger/signaldata/SignalDataPrint.cpp
+++ b/ndb/src/common/debugger/signaldata/SignalDataPrint.cpp
@@ -73,7 +73,6 @@
#include <signaldata/CntrStart.hpp>
#include <signaldata/ReadNodesConf.hpp>
#include <signaldata/TuxMaint.hpp>
-#include <signaldata/TupAccess.hpp>
#include <signaldata/AccLock.hpp>
bool printCONTINUEB(FILE *, const Uint32 *, Uint32, Uint16);
@@ -249,14 +248,15 @@ SignalDataPrintFunctions[] = {
,{ GSN_READ_NODESCONF, printREAD_NODES_CONF }
,{ GSN_TUX_MAINT_REQ, printTUX_MAINT_REQ }
- ,{ GSN_TUP_READ_ATTRS, printTUP_READ_ATTRS }
- ,{ GSN_TUP_QUERY_TH, printTUP_QUERY_TH }
- ,{ GSN_TUP_STORE_TH, printTUP_STORE_TH }
,{ GSN_ACC_LOCKREQ, printACC_LOCKREQ }
,{ GSN_LQH_TRANSCONF, printLQH_TRANSCONF }
};
const unsigned short NO_OF_PRINT_FUNCTIONS = sizeof(SignalDataPrintFunctions)/sizeof(NameFunctionPair);
-
-
+template class Bitmask<1>;
+template class Bitmask<2>;
+template class Bitmask<4>;
+template struct BitmaskPOD<1>;
+template struct BitmaskPOD<2>;
+template struct BitmaskPOD<4>;
diff --git a/ndb/src/common/debugger/signaldata/SignalNames.cpp b/ndb/src/common/debugger/signaldata/SignalNames.cpp
index 377a588dbb0..9d4d5bdf6f5 100644
--- a/ndb/src/common/debugger/signaldata/SignalNames.cpp
+++ b/ndb/src/common/debugger/signaldata/SignalNames.cpp
@@ -32,7 +32,6 @@ const GsnName SignalNames [] = {
,{ GSN_READCONF, "READCONF" }
,{ GSN_SCAN_NEXTREQ, "SCAN_NEXTREQ" }
,{ GSN_SCAN_TABCONF, "SCAN_TABCONF" }
- ,{ GSN_SCAN_TABINFO, "SCAN_TABINFO" }
,{ GSN_SCAN_TABREF, "SCAN_TABREF" }
,{ GSN_SCAN_TABREQ, "SCAN_TABREQ" }
,{ GSN_TC_COMMITCONF, "TC_COMMITCONF" }
@@ -641,9 +640,6 @@ const GsnName SignalNames [] = {
,{ GSN_TUX_MAINT_REQ, "TUX_MAINT_REQ" }
,{ GSN_TUX_MAINT_CONF, "TUX_MAINT_CONF" }
,{ GSN_TUX_MAINT_REF, "TUX_MAINT_REF" }
- ,{ GSN_TUP_READ_ATTRS, "TUP_READ_ATTRS" }
- ,{ GSN_TUP_QUERY_TH, "TUP_QUERY_TH" }
- ,{ GSN_TUP_STORE_TH, "TUP_STORE_TH" }
,{ GSN_TUX_BOUND_INFO, "TUX_BOUND_INFO" }
,{ GSN_ACC_LOCKREQ, "ACC_LOCKREQ" }
diff --git a/ndb/src/common/debugger/signaldata/TupAccess.cpp b/ndb/src/common/debugger/signaldata/TupAccess.cpp
deleted file mode 100644
index e94d4636cf5..00000000000
--- a/ndb/src/common/debugger/signaldata/TupAccess.cpp
+++ /dev/null
@@ -1,131 +0,0 @@
-/* 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 <signaldata/TupAccess.hpp>
-#include <SignalLoggerManager.hpp>
-#include <AttributeHeader.hpp>
-
-bool
-printTUP_READ_ATTRS(FILE* output, const Uint32* theData, Uint32 len, Uint16 rbn)
-{
- const TupReadAttrs* const sig = (const TupReadAttrs*)theData;
- if (sig->errorCode == RNIL)
- fprintf(output, " errorCode=RNIL flags=%x\n", sig->requestInfo);
- else
- fprintf(output, " errorCode=%u flags=%x\n", sig->errorCode, sig->requestInfo);
- fprintf(output, " table: id=%u", sig->tableId);
- fprintf(output, " fragment: id=%u ptr=0x%x\n", sig->fragId, sig->fragPtrI);
- fprintf(output, " tuple: addr=0x%x version=%u", sig->tupAddr, sig->tupVersion);
- fprintf(output, " realPage=0x%x offset=%u\n", sig->pageId, sig->pageOffset);
- const Uint32* buffer = (const Uint32*)sig + TupReadAttrs::SignalLength;
- Uint32 attrCount = buffer[0];
- bool readKeys = (sig->requestInfo & TupReadAttrs::ReadKeys);
- if (sig->errorCode == RNIL && ! readKeys ||
- sig->errorCode == 0 && readKeys) {
- fprintf(output, " input: attrCount=%u\n", attrCount);
- for (unsigned i = 0; i < attrCount; i++) {
- AttributeHeader ah(buffer[1 + i]);
- fprintf(output, " %u: attrId=%u\n", i, ah.getAttributeId());
- }
- }
- if (sig->errorCode == 0) {
- fprintf(output, " output: attrCount=%u\n", attrCount);
- Uint32 pos = 1 + attrCount;
- for (unsigned i = 0; i < attrCount; i++) {
- AttributeHeader ah(buffer[pos++]);
- fprintf(output, " %u: attrId=%u dataSize=%u\n", i, ah.getAttributeId(), ah.getDataSize());
- Uint32 next = pos + ah.getDataSize();
- Uint32 printpos = 0;
- while (pos < next) {
- SignalLoggerManager::printDataWord(output, printpos, buffer[pos]);
- pos++;
- }
- if (ah.getDataSize() > 0)
- fprintf(output, "\n");
- }
- }
- return true;
-}
-
-bool
-printTUP_QUERY_TH(FILE* output, const Uint32* theData, Uint32 len, Uint16 rbn)
-{
- const TupQueryTh* const sig = (const TupQueryTh*)theData;
- fprintf(output, "tableId = %u, fragId = %u ", sig->tableId, sig->fragId);
- fprintf(output, "tuple: addr = 0x%x version = %u\n", sig->tupAddr,
- sig->tupVersion);
- fprintf(output, "transId1 = 0x%x, transId2 = 0x%x, savePointId = %u\n",
- sig->transId1, sig->transId2, sig->savePointId);
- return true;
-}
-
-bool
-printTUP_STORE_TH(FILE* output, const Uint32* theData, Uint32 len, Uint16 rbn)
-{
- const TupStoreTh* const sig = (const TupStoreTh*)theData;
- if (sig->errorCode == RNIL)
- fprintf(output, " errorCode=RNIL\n");
- else
- fprintf(output, " errorCode=%u\n", sig->errorCode);
- fprintf(output, " table: id=%u", sig->tableId);
- fprintf(output, " fragment: id=%u ptr=0x%x\n", sig->fragId, sig->fragPtrI);
- fprintf(output, " tuple: addr=0x%x", sig->tupAddr);
- if ((sig->tupAddr & 0x1) == 0) {
- fprintf(output, " fragPage=0x%x index=%u",
- sig->tupAddr >> MAX_TUPLES_BITS,
- (sig->tupAddr & ((1 <<MAX_TUPLES_BITS) - 1)) >> 1);
- fprintf(output, " realPage=0x%x offset=%u\n", sig->pageId, sig->pageOffset);
- } else {
- fprintf(output, " cacheId=%u\n",
- sig->tupAddr >> 1);
- }
- if (sig->tupVersion != 0) {
- fprintf(output, " version=%u ***invalid***\n", sig->tupVersion);
- }
- bool showdata = true;
- switch (sig->opCode) {
- case TupStoreTh::OpRead:
- fprintf(output, " operation=Read\n");
- showdata = false;
- break;
- case TupStoreTh::OpInsert:
- fprintf(output, " operation=Insert\n");
- break;
- case TupStoreTh::OpUpdate:
- fprintf(output, " operation=Update\n");
- break;
- case TupStoreTh::OpDelete:
- fprintf(output, " operation=Delete\n");
- showdata = false;
- break;
- default:
- fprintf(output, " operation=%u ***invalid***\n", sig->opCode);
- break;
- }
- fprintf(output, " data: offset=%u size=%u", sig->dataOffset, sig->dataSize);
- if (! showdata) {
- fprintf(output, " [not printed]\n");
- } else {
- fprintf(output, "\n");
- const Uint32* buffer = (const Uint32*)sig + TupStoreTh::SignalLength;
- Uint32 pos = 0;
- while (pos < sig->dataSize)
- SignalLoggerManager::printDataWord(output, pos, buffer[sig->dataOffset + pos]);
- if (sig->dataSize > 0)
- fprintf(output, "\n");
- }
- return true;
-};
diff --git a/ndb/src/common/logger/FileLogHandler.cpp b/ndb/src/common/logger/FileLogHandler.cpp
index d13dd7b2a78..632db71db15 100644
--- a/ndb/src/common/logger/FileLogHandler.cpp
+++ b/ndb/src/common/logger/FileLogHandler.cpp
@@ -14,8 +14,8 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+#include <ndb_global.h>
#include <FileLogHandler.hpp>
-
#include <File.hpp>
//
@@ -146,7 +146,7 @@ FileLogHandler::createNewFile()
{
bool rc = true;
int fileNo = 1;
- char newName[MAXPATHLEN];
+ char newName[PATH_MAX];
do
{
diff --git a/ndb/src/common/logger/Logger.cpp b/ndb/src/common/logger/Logger.cpp
index 9c9f1eece18..c2fdecb642b 100644
--- a/ndb/src/common/logger/Logger.cpp
+++ b/ndb/src/common/logger/Logger.cpp
@@ -350,3 +350,4 @@ Logger::log(LoggerLevel logLevel, const char* pMsg, va_list ap) const
// PRIVATE
//
+template class Vector<LogHandler*>;
diff --git a/ndb/src/common/mgmcommon/ConfigInfo.cpp b/ndb/src/common/mgmcommon/ConfigInfo.cpp
index c2b5fdabf01..552b49727fb 100644
--- a/ndb/src/common/mgmcommon/ConfigInfo.cpp
+++ b/ndb/src/common/mgmcommon/ConfigInfo.cpp
@@ -14,15 +14,26 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+#include <NdbTCP.h>
#include "ConfigInfo.hpp"
#include <mgmapi_config_parameters.h>
+#include <ndb_limits.h>
#define MAX_LINE_LENGTH 255
#define KEY_INTERNAL 0
-
+#define MAX_INT_RNIL (RNIL - 1)
/****************************************************************************
* Section names
****************************************************************************/
+
+const ConfigInfo::AliasPair
+ConfigInfo::m_sectionNameAliases[]={
+ {"API", "MYSQLD"},
+ {"DB", "NDBD"},
+ {"MGM", "NDB_MGMD"},
+ {0, 0}
+};
+
const char*
ConfigInfo::m_sectionNames[]={
"SYSTEM",
@@ -47,24 +58,25 @@ sizeof(m_sectionNames)/sizeof(char*);
/****************************************************************************
* Section Rules declarations
****************************************************************************/
-bool transformComputer(InitConfigFileParser::Context & ctx, const char *);
-bool transformSystem(InitConfigFileParser::Context & ctx, const char *);
-bool transformExternalSystem(InitConfigFileParser::Context & ctx, const char *);
-bool transformNode(InitConfigFileParser::Context & ctx, const char *);
-bool transformExtNode(InitConfigFileParser::Context & ctx, const char *);
-bool transformConnection(InitConfigFileParser::Context & ctx, const char *);
-bool applyDefaultValues(InitConfigFileParser::Context & ctx, const char *);
-bool checkMandatory(InitConfigFileParser::Context & ctx, const char *);
-bool fixPortNumber(InitConfigFileParser::Context & ctx, const char *);
-bool fixShmkey(InitConfigFileParser::Context & ctx, const char *);
-bool checkDbConstraints(InitConfigFileParser::Context & ctx, const char *);
-bool checkConnectionConstraints(InitConfigFileParser::Context &, const char *);
-bool fixNodeHostname(InitConfigFileParser::Context & ctx, const char * data);
-bool fixHostname(InitConfigFileParser::Context & ctx, const char * data);
-bool fixNodeId(InitConfigFileParser::Context & ctx, const char * data);
-bool fixExtConnection(InitConfigFileParser::Context & ctx, const char * data);
-bool fixDepricated(InitConfigFileParser::Context & ctx, const char *);
-bool saveInConfigValues(InitConfigFileParser::Context & ctx, const char *);
+static bool transformComputer(InitConfigFileParser::Context & ctx, const char *);
+static bool transformSystem(InitConfigFileParser::Context & ctx, const char *);
+static bool transformExternalSystem(InitConfigFileParser::Context & ctx, const char *);
+static bool transformNode(InitConfigFileParser::Context & ctx, const char *);
+static bool transformExtNode(InitConfigFileParser::Context & ctx, const char *);
+static bool transformConnection(InitConfigFileParser::Context & ctx, const char *);
+static bool applyDefaultValues(InitConfigFileParser::Context & ctx, const char *);
+static bool checkMandatory(InitConfigFileParser::Context & ctx, const char *);
+static bool fixPortNumber(InitConfigFileParser::Context & ctx, const char *);
+static bool fixShmkey(InitConfigFileParser::Context & ctx, const char *);
+static bool checkDbConstraints(InitConfigFileParser::Context & ctx, const char *);
+static bool checkConnectionConstraints(InitConfigFileParser::Context &, const char *);
+static bool checkTCPConstraints(InitConfigFileParser::Context &, const char *);
+static bool fixNodeHostname(InitConfigFileParser::Context & ctx, const char * data);
+static bool fixHostname(InitConfigFileParser::Context & ctx, const char * data);
+static bool fixNodeId(InitConfigFileParser::Context & ctx, const char * data);
+static bool fixExtConnection(InitConfigFileParser::Context & ctx, const char * data);
+static bool fixDepricated(InitConfigFileParser::Context & ctx, const char *);
+static bool saveInConfigValues(InitConfigFileParser::Context & ctx, const char *);
const ConfigInfo::SectionRule
ConfigInfo::m_SectionRules[] = {
@@ -83,9 +95,6 @@ ConfigInfo::m_SectionRules[] = {
{ "SCI", transformConnection, 0 },
{ "OSE", transformConnection, 0 },
- { "TCP", fixPortNumber, 0 },
- //{ "SHM", fixShmKey, 0 },
-
{ "DB", fixNodeHostname, 0 },
{ "API", fixNodeHostname, 0 },
{ "MGM", fixNodeHostname, 0 },
@@ -106,6 +115,10 @@ ConfigInfo::m_SectionRules[] = {
{ "OSE", fixHostname, "HostName1" },
{ "OSE", fixHostname, "HostName2" },
+ { "TCP", fixPortNumber, 0 }, // has to come after fixHostName
+ { "SHM", fixPortNumber, 0 }, // has to come after fixHostName
+ //{ "SHM", fixShmKey, 0 },
+
/**
* fixExtConnection must be after fixNodeId
*/
@@ -128,7 +141,9 @@ ConfigInfo::m_SectionRules[] = {
{ "SCI", checkConnectionConstraints, 0 },
{ "OSE", checkConnectionConstraints, 0 },
-
+ { "TCP", checkTCPConstraints, "HostName1" },
+ { "TCP", checkTCPConstraints, "HostName2" },
+
{ "*", checkMandatory, 0 },
{ "DB", saveInConfigValues, 0 },
@@ -146,13 +161,21 @@ const int ConfigInfo::m_NoOfRules = sizeof(m_SectionRules)/sizeof(SectionRule);
/****************************************************************************
* Config Rules declarations
****************************************************************************/
-bool addNodeConnections(Vector<ConfigInfo::ConfigRuleSection>&sections,
- struct InitConfigFileParser::Context &ctx,
- const char * ruleData);
+static bool add_node_connections(Vector<ConfigInfo::ConfigRuleSection>&sections,
+ struct InitConfigFileParser::Context &ctx,
+ const char * rule_data);
+static bool add_server_ports(Vector<ConfigInfo::ConfigRuleSection>&sections,
+ struct InitConfigFileParser::Context &ctx,
+ const char * rule_data);
+static bool check_node_vs_replicas(Vector<ConfigInfo::ConfigRuleSection>&sections,
+ struct InitConfigFileParser::Context &ctx,
+ const char * rule_data);
const ConfigInfo::ConfigRule
ConfigInfo::m_ConfigRules[] = {
- { addNodeConnections, 0 },
+ { add_node_connections, 0 },
+ { add_server_ports, 0 },
+ { check_node_vs_replicas, 0 },
{ 0, 0 }
};
@@ -166,24 +189,8 @@ struct DepricationTransform {
static
const DepricationTransform f_deprication[] = {
- { "DB", "NoOfIndexPages", "IndexMemory", 0, 8192 }
- ,{ "DB", "MemorySpaceIndexes", "IndexMemory", 0, 8192 }
- ,{ "DB", "NoOfDataPages", "DataMemory", 0, 8192 }
- ,{ "DB", "MemorySpaceTuples", "DataMemory", 0, 8192 }
- ,{ "DB", "TransactionInactiveTimeBeforeAbort", "TransactionInactiveTimeout",
- 0, 1 }
- ,{ "TCP", "ProcessId1", "NodeId1", 0, 1}
- ,{ "TCP", "ProcessId2", "NodeId2", 0, 1}
- ,{ "TCP", "SendBufferSize", "SendBufferMemory", 0, 16384 }
- ,{ "TCP", "MaxReceiveSize", "ReceiveBufferMemory", 0, 16384 }
-
- ,{ "SHM", "ProcessId1", "NodeId1", 0, 1}
- ,{ "SHM", "ProcessId2", "NodeId2", 0, 1}
- ,{ "SCI", "ProcessId1", "NodeId1", 0, 1}
- ,{ "SCI", "ProcessId2", "NodeId2", 0, 1}
- ,{ "OSE", "ProcessId1", "NodeId1", 0, 1}
- ,{ "OSE", "ProcessId2", "NodeId2", 0, 1}
- ,{ 0, 0, 0, 0, 0}
+ { "DB", "Discless", "Diskless", 0, 1 },
+ { 0, 0, 0, 0, 0}
};
/**
@@ -241,27 +248,14 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
KEY_INTERNAL,
"HostName",
"COMPUTER",
- "Hostname of computer (e.g. alzato.com)",
+ "Hostname of computer (e.g. mysql.com)",
ConfigInfo::USED,
false,
ConfigInfo::STRING,
MANDATORY,
0,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
- {
- CFG_NODE_BYTE_ORDER,
- "ByteOrder",
- "COMPUTER",
- "Not yet implemented",
- ConfigInfo::USED, // Actually not used, but since it is MANDATORY,
- // we don't want any warning message
- false,
- ConfigInfo::STRING,
- MANDATORY, // Big == 0, Little == 1, NotSet == 2 (?)
- 0,
- 1 },
-
/****************************************************************************
* SYSTEM
***************************************************************************/
@@ -311,7 +305,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::INT,
0,
0,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
{
CFG_SYS_CONFIG_GENERATION,
@@ -323,7 +317,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::INT,
0,
0,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
/***************************************************************************
* DB
@@ -350,7 +344,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::STRING,
UNDEFINED,
0,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
{
CFG_NODE_SYSTEM,
@@ -362,7 +356,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::STRING,
UNDEFINED,
0,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
{
CFG_NODE_ID,
@@ -377,6 +371,18 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
(MAX_NODES - 1) },
{
+ KEY_INTERNAL,
+ "ServerPort",
+ "DB",
+ "Port used to setup transporter",
+ ConfigInfo::USED,
+ false,
+ ConfigInfo::INT,
+ UNDEFINED,
+ 1,
+ 65535 },
+
+ {
CFG_DB_NO_REPLICAS,
"NoOfReplicas",
"DB",
@@ -386,7 +392,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::INT,
MANDATORY,
1,
- 2 },
+ 4 },
{
CFG_DB_NO_ATTRIBUTES,
@@ -398,7 +404,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::INT,
1000,
32,
- 4096 },
+ MAX_INT_RNIL/16 },
{
CFG_DB_NO_TABLES,
@@ -408,9 +414,9 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::USED,
false,
ConfigInfo::INT,
- 32,
+ 128,
8,
- 128 },
+ MAX_INT_RNIL },
{
CFG_DB_NO_INDEXES,
@@ -422,7 +428,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::INT,
128,
0,
- 2048 },
+ MAX_INT_RNIL },
{
CFG_DB_NO_INDEX_OPS,
@@ -434,8 +440,8 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::INT,
8192,
0,
- 1000000
- },
+ MAX_INT_RNIL
+ },
{
CFG_DB_NO_TRIGGERS,
@@ -447,7 +453,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::INT,
768,
0,
- 2432 },
+ MAX_INT_RNIL },
{
CFG_DB_NO_TRIGGER_OPS,
@@ -457,9 +463,9 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::USED,
false,
ConfigInfo::INT,
- 1000,
+ 4000,
0,
- 1000000 },
+ MAX_INT_RNIL },
{
KEY_INTERNAL,
@@ -471,7 +477,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::STRING,
MANDATORY,
0,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
{
CFG_DB_NO_SAVE_MSGS,
@@ -483,7 +489,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::INT,
25,
0,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
{
CFG_DB_MEMLOCK,
@@ -495,33 +501,9 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::BOOL,
false,
0,
- 0x7FFFFFFF },
-
- {
- KEY_INTERNAL,
- "SleepWhenIdle",
- "DB",
- 0,
- ConfigInfo::DEPRICATED,
- true,
- ConfigInfo::BOOL,
- true,
- 0,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
{
- KEY_INTERNAL,
- "NoOfSignalsToExecuteBetweenCommunicationInterfacePoll",
- "DB",
- 0,
- ConfigInfo::DEPRICATED,
- true,
- ConfigInfo::INT,
- 20,
- 1,
- 0x7FFFFFFF },
-
- {
CFG_DB_WATCHDOG_INTERVAL,
"TimeBetweenWatchDogCheck",
"DB",
@@ -529,9 +511,9 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::USED,
true,
ConfigInfo::INT,
- 4000,
+ 6000,
70,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
{
CFG_DB_STOP_ON_ERROR,
@@ -543,7 +525,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::BOOL,
true,
0,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
{
CFG_DB_STOP_ON_ERROR_INSERT,
@@ -565,9 +547,9 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::USED,
false,
ConfigInfo::INT,
- 8192,
+ 32768,
32,
- 1000000 },
+ MAX_INT_RNIL },
{
CFG_DB_NO_TRANSACTIONS,
@@ -579,7 +561,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::INT,
4096,
32,
- 1000000 },
+ MAX_INT_RNIL },
{
CFG_DB_NO_SCANS,
@@ -589,7 +571,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::USED,
false,
ConfigInfo::INT,
- 25,
+ 256,
2,
500 },
@@ -601,9 +583,9 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::USED,
false,
ConfigInfo::INT,
- 1024000,
+ (1024 * 1024),
1024,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
{
CFG_DB_INDEX_MEM,
@@ -613,33 +595,9 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::USED,
false,
ConfigInfo::INT64,
- 3000 * 8192,
+ 3 * 1024 * 8192,
128 * 8192,
- ((Uint64)192000) * ((Uint64)8192) },
-
- {
- KEY_INTERNAL,
- "NoOfIndexPages",
- "DB",
- "IndexMemory",
- ConfigInfo::DEPRICATED,
- false,
- ConfigInfo::INT,
- 3000,
- 128,
- 192000 },
-
- {
- KEY_INTERNAL,
- "MemorySpaceIndexes",
- "DB",
- "IndexMemory",
- ConfigInfo::DEPRICATED,
- false,
- ConfigInfo::INT,
- UNDEFINED,
- 128,
- 192000 },
+ ((Uint64)MAX_INT_RNIL) * ((Uint64)8192) },
{
CFG_DB_DATA_MEM,
@@ -649,35 +607,11 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::USED,
false,
ConfigInfo::INT64,
- 10000 * 8192,
+ 10 * 1024 * 8192,
128 * 8192,
- ((Uint64)400000) * ((Uint64)8192) },
+ ((Uint64)MAX_INT_RNIL) * ((Uint64)8192) },
{
- KEY_INTERNAL,
- "NoOfDataPages",
- "DB",
- "DataMemory",
- ConfigInfo::DEPRICATED,
- false,
- ConfigInfo::INT,
- 10000,
- 128,
- 400000 },
-
- {
- KEY_INTERNAL,
- "MemorySpaceTuples",
- "DB",
- "DataMemory",
- ConfigInfo::DEPRICATED,
- false,
- ConfigInfo::INT,
- UNDEFINED,
- 128,
- 400000 },
-
- {
CFG_DB_START_PARTIAL_TIMEOUT,
"StartPartialTimeout",
"DB",
@@ -709,23 +643,11 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::USED,
true,
ConfigInfo::INT,
- 5*60000,
+ 0,
0,
~0 },
{
- KEY_INTERNAL,
- "TimeToWaitAlive",
- "DB",
- "Start{Partial/Partitioned/Failure}Time",
- ConfigInfo::DEPRICATED,
- true,
- ConfigInfo::INT,
- 25,
- 2,
- 4000 },
-
- {
CFG_DB_HEARTBEAT_INTERVAL,
"HeartbeatIntervalDbDb",
"DB",
@@ -735,7 +657,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::INT,
1500,
10,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
{
CFG_DB_API_HEARTBEAT_INTERVAL,
@@ -747,7 +669,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::INT,
1500,
100,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
{
CFG_DB_LCP_INTERVAL,
@@ -783,7 +705,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::INT,
8,
1,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
{
KEY_INTERNAL,
@@ -808,7 +730,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::INT,
1000,
1000,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
{
CFG_DB_TRANSACTION_INACTIVE_TIMEOUT,
@@ -822,9 +744,9 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::USED,
true,
ConfigInfo::INT,
- 3000,
+ MAX_INT_RNIL,
0,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
{
CFG_DB_TRANSACTION_DEADLOCK_TIMEOUT,
@@ -837,33 +759,21 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::USED,
true,
ConfigInfo::INT,
- 3000,
+ 1200,
50,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
{
KEY_INTERNAL,
- "TransactionInactiveTimeBeforeAbort",
- "DB",
- "TransactionInactiveTimeout",
- ConfigInfo::DEPRICATED,
- true,
- ConfigInfo::INT,
- 3000,
- 20,
- 0x7FFFFFFF },
-
- {
- KEY_INTERNAL,
"NoOfDiskPagesToDiskDuringRestartTUP",
"DB",
"?",
ConfigInfo::USED,
true,
ConfigInfo::INT,
- 50,
+ 40,
1,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
{
KEY_INTERNAL,
@@ -873,9 +783,9 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::USED,
true,
ConfigInfo::INT,
- 10,
+ 40,
1,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
{
KEY_INTERNAL,
@@ -885,9 +795,9 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::USED,
true,
ConfigInfo::INT,
- 25,
+ 20,
1,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
{
KEY_INTERNAL,
@@ -897,14 +807,14 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::USED,
true,
ConfigInfo::INT,
- 5,
+ 20,
1,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
{
CFG_DB_DISCLESS,
- "Discless",
+ "Diskless",
"DB",
"Run wo/ disk",
ConfigInfo::USED,
@@ -913,6 +823,20 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
0,
0,
1},
+
+ {
+ KEY_INTERNAL,
+ "Discless",
+ "DB",
+ "Diskless",
+ ConfigInfo::DEPRICATED,
+ true,
+ ConfigInfo::BOOL,
+ 0,
+ 0,
+ 1},
+
+
{
CFG_DB_ARBIT_TIMEOUT,
@@ -922,9 +846,9 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::USED,
false,
ConfigInfo::INT,
- 1000,
+ 3000,
10,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
{
CFG_DB_FILESYSTEM_PATH,
@@ -936,7 +860,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::STRING,
UNDEFINED,
0,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
{
CFG_LOGLEVEL_STARTUP,
@@ -1059,7 +983,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::INT,
(2 * 1024 * 1024) + (2 * 1024 * 1024), // sum of BackupDataBufferSize and BackupLogBufferSize
0,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
{
CFG_DB_BACKUP_DATA_BUFFER_MEM,
@@ -1071,7 +995,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::INT,
(2 * 1024 * 1024), // remember to change BackupMemory
0,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
{
CFG_DB_BACKUP_LOG_BUFFER_MEM,
@@ -1083,7 +1007,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::INT,
(2 * 1024 * 1024), // remember to change BackupMemory
0,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
{
CFG_DB_BACKUP_WRITE_SIZE,
@@ -1095,7 +1019,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::INT,
32768,
0,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
/***************************************************************************
* REP
@@ -1122,7 +1046,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::STRING,
UNDEFINED,
0,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
{
CFG_NODE_SYSTEM,
@@ -1134,7 +1058,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::STRING,
UNDEFINED,
0,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
{
CFG_NODE_ID,
@@ -1158,7 +1082,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::STRING,
MANDATORY,
0,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
{
CFG_REP_HEARTBEAT_INTERVAL,
@@ -1170,7 +1094,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::INT,
3000,
100,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
/***************************************************************************
* API
@@ -1197,7 +1121,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::STRING,
UNDEFINED,
0,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
{
CFG_NODE_SYSTEM,
@@ -1209,7 +1133,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::STRING,
UNDEFINED,
0,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
{
CFG_NODE_ID,
@@ -1231,9 +1155,9 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::USED,
false,
ConfigInfo::STRING,
- MANDATORY,
0,
- 0x7FFFFFFF },
+ 0,
+ MAX_INT_RNIL },
{
CFG_NODE_ARBIT_RANK,
@@ -1243,7 +1167,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::USED,
false,
ConfigInfo::INT,
- 2,
+ 0,
0,
2 },
@@ -1257,7 +1181,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::INT,
0,
0,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
/****************************************************************************
* MGM
@@ -1284,7 +1208,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::STRING,
UNDEFINED,
0,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
{
CFG_NODE_SYSTEM,
@@ -1296,7 +1220,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::STRING,
UNDEFINED,
0,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
{
CFG_NODE_ID,
@@ -1320,7 +1244,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::STRING,
0,
0,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
{
KEY_INTERNAL,
@@ -1330,9 +1254,9 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::USED,
false,
ConfigInfo::STRING,
- MANDATORY,
0,
- 0x7FFFFFFF },
+ 0,
+ MAX_INT_RNIL },
{
KEY_INTERNAL,
@@ -1344,7 +1268,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::INT,
100,
0,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
{
CFG_MGM_PORT,
@@ -1354,9 +1278,9 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::USED,
false,
ConfigInfo::INT,
- 2200,
+ NDB_BASE_PORT,
0,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
{
KEY_INTERNAL,
@@ -1368,7 +1292,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::INT,
2199,
0,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
{
CFG_NODE_ARBIT_RANK,
@@ -1378,7 +1302,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::USED,
false,
ConfigInfo::INT,
- 2,
+ 1,
0,
2 },
@@ -1392,7 +1316,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::INT,
0,
0,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
/****************************************************************************
* TCP
@@ -1419,7 +1343,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::STRING,
UNDEFINED,
0,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
{
CFG_TCP_HOSTNAME_2,
@@ -1431,7 +1355,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::STRING,
UNDEFINED,
0,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
{
CFG_CONNECTION_NODE_1,
@@ -1443,19 +1367,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::STRING,
MANDATORY,
0,
- 0x7FFFFFFF },
-
- {
- KEY_INTERNAL,
- "ProcessId1",
- "TCP",
- "NodeId1",
- ConfigInfo::DEPRICATED,
- false,
- ConfigInfo::INT,
- UNDEFINED,
- 0,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
{
CFG_CONNECTION_NODE_2,
@@ -1467,43 +1379,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::STRING,
MANDATORY,
0,
- 0x7FFFFFFF },
-
- {
- KEY_INTERNAL,
- "ProcessId2",
- "TCP",
- "NodeId2",
- ConfigInfo::DEPRICATED,
- false,
- ConfigInfo::INT,
- UNDEFINED,
- 0,
- 0x7FFFFFFF },
-
- {
- KEY_INTERNAL,
- "IpAddress1",
- "TCP",
- "HostName1",
- ConfigInfo::DEPRICATED,
- false,
- ConfigInfo::STRING,
- UNDEFINED,
- 0,
- 0x7FFFFFFF },
-
- {
- KEY_INTERNAL,
- "IpAddress2",
- "TCP",
- "HostName2",
- ConfigInfo::DEPRICATED,
- false,
- ConfigInfo::STRING,
- UNDEFINED,
- 0,
- 0 },
+ MAX_INT_RNIL },
{
CFG_CONNECTION_SEND_SIGNAL_ID,
@@ -1515,7 +1391,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::BOOL,
true,
0,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
{
@@ -1528,19 +1404,19 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::BOOL,
false,
0,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
{
- CFG_TCP_SERVER_PORT,
+ CFG_CONNECTION_SERVER_PORT,
"PortNumber",
"TCP",
"Port used for this transporter",
ConfigInfo::USED,
false,
ConfigInfo::INT,
- 2202,
+ MANDATORY,
0,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
{
CFG_TCP_SEND_BUFFER_SIZE,
@@ -1552,21 +1428,9 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::INT,
16 * 16384,
1 * 16384,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
{
- KEY_INTERNAL,
- "SendBufferSize",
- "TCP",
- "SendBufferMemory",
- ConfigInfo::DEPRICATED,
- false,
- ConfigInfo::INT,
- 16,
- 1,
- 0x7FFFFFFF },
-
- {
CFG_TCP_RECEIVE_BUFFER_SIZE,
"ReceiveBufferMemory",
"TCP",
@@ -1576,19 +1440,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::INT,
4 * 16384,
1 * 16384,
- 0x7FFFFFFF },
-
- {
- KEY_INTERNAL,
- "MaxReceiveSize",
- "TCP",
- "ReceiveBufferMemory",
- ConfigInfo::DEPRICATED,
- false,
- ConfigInfo::INT,
- 4,
- 1,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
{
CFG_TCP_PROXY,
@@ -1603,19 +1455,6 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
0 },
{
- KEY_INTERNAL,
- "Compression",
- "TCP",
- 0,
- ConfigInfo::DEPRICATED,
- false,
- ConfigInfo::BOOL,
- false,
- 0,
- 0x7FFFFFFF },
-
-
- {
CFG_CONNECTION_NODE_1_SYSTEM,
"NodeId1_System",
"TCP",
@@ -1625,7 +1464,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::STRING,
UNDEFINED,
0,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
{
CFG_CONNECTION_NODE_2_SYSTEM,
@@ -1637,7 +1476,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::STRING,
UNDEFINED,
0,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
/****************************************************************************
@@ -1665,20 +1504,20 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::STRING,
MANDATORY,
0,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
{
- KEY_INTERNAL,
- "ProcessId1",
+ CFG_CONNECTION_SERVER_PORT,
+ "PortNumber",
"SHM",
- "NodeId1",
- ConfigInfo::DEPRICATED,
+ "Port used for this transporter",
+ ConfigInfo::USED,
false,
- ConfigInfo::STRING,
- UNDEFINED,
+ ConfigInfo::INT,
+ MANDATORY,
0,
- 0x7FFFFFFF },
-
+ MAX_INT_RNIL },
+
{
CFG_CONNECTION_NODE_2,
"NodeId2",
@@ -1689,19 +1528,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::STRING,
MANDATORY,
0,
- 0x7FFFFFFF },
-
- {
- KEY_INTERNAL,
- "ProcessId2",
- "SHM",
- "NodeId1",
- ConfigInfo::DEPRICATED,
- false,
- ConfigInfo::STRING,
- UNDEFINED,
- 0,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
{
CFG_CONNECTION_SEND_SIGNAL_ID,
@@ -1713,7 +1540,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::BOOL,
false,
0,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
{
@@ -1726,7 +1553,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::BOOL,
true,
0,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
{
CFG_SHM_KEY,
@@ -1738,7 +1565,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::INT,
MANDATORY,
0,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
{
CFG_SHM_BUFFER_MEM,
@@ -1750,21 +1577,9 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::INT,
1048576,
4096,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
{
- KEY_INTERNAL,
- "Compression",
- "SHM",
- 0,
- ConfigInfo::DEPRICATED,
- false,
- ConfigInfo::BOOL,
- false,
- 0,
- 0x7FFFFFFF },
-
- {
CFG_CONNECTION_NODE_1_SYSTEM,
"NodeId1_System",
"SHM",
@@ -1774,7 +1589,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::STRING,
UNDEFINED,
0,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
{
CFG_CONNECTION_NODE_2_SYSTEM,
@@ -1786,7 +1601,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::STRING,
UNDEFINED,
0,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
/****************************************************************************
* SCI
@@ -1813,19 +1628,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::INT,
MANDATORY,
0,
- 0x7FFFFFFF },
-
- {
- KEY_INTERNAL,
- "ProcessId1",
- "SCI",
- "NodeId1",
- ConfigInfo::DEPRICATED,
- false,
- ConfigInfo::INT,
- UNDEFINED,
- 0,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
{
CFG_CONNECTION_NODE_2,
@@ -1837,19 +1640,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::INT,
MANDATORY,
0,
- 0x7FFFFFFF },
-
- {
- KEY_INTERNAL,
- "ProcessId2",
- "SCI",
- "NodeId2",
- ConfigInfo::DEPRICATED,
- false,
- ConfigInfo::INT,
- UNDEFINED,
- 0,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
{
CFG_SCI_ID_0,
@@ -1861,7 +1652,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::INT,
MANDATORY,
0,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
{
CFG_SCI_ID_1,
@@ -1873,7 +1664,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::INT,
MANDATORY,
0,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
{
CFG_CONNECTION_SEND_SIGNAL_ID,
@@ -1885,7 +1676,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::BOOL,
true,
0,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
{
CFG_CONNECTION_CHECKSUM,
@@ -1897,7 +1688,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::BOOL,
false,
0,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
{
CFG_SCI_SEND_LIMIT,
@@ -1909,7 +1700,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::INT,
2048,
512,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
{
CFG_SCI_BUFFER_MEM,
@@ -1921,67 +1712,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::INT,
1048576,
262144,
- 0x7FFFFFFF },
-
- {
- KEY_INTERNAL,
- "Node1_NoOfAdapters",
- "SCI",
- 0,
- ConfigInfo::DEPRICATED,
- false,
- ConfigInfo::INT,
- UNDEFINED,
- 0,
- 0x7FFFFFFF },
-
- {
- KEY_INTERNAL,
- "Node2_NoOfAdapters",
- "SCI",
- 0,
- ConfigInfo::DEPRICATED,
- false,
- ConfigInfo::INT,
- UNDEFINED,
- 0,
- 0x7FFFFFFF },
-
- {
- KEY_INTERNAL,
- "Node1_Adapter",
- "SCI",
- 0,
- ConfigInfo::DEPRICATED,
- false,
- ConfigInfo::INT,
- UNDEFINED,
- 0,
- 0x7FFFFFFF },
-
- {
- KEY_INTERNAL,
- "Node2_Adapter",
- "SCI",
- 0,
- ConfigInfo::DEPRICATED,
- false,
- ConfigInfo::INT,
- UNDEFINED,
- 0,
- 0x7FFFFFFF },
-
- {
- KEY_INTERNAL,
- "Compression",
- "SCI",
- 0,
- ConfigInfo::DEPRICATED,
- false,
- ConfigInfo::BOOL,
- false,
- 0,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
{
CFG_CONNECTION_NODE_1_SYSTEM,
@@ -1993,7 +1724,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::STRING,
UNDEFINED,
0,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
{
CFG_CONNECTION_NODE_2_SYSTEM,
@@ -2005,7 +1736,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::STRING,
UNDEFINED,
0,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
/****************************************************************************
* OSE
@@ -2032,7 +1763,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::STRING,
UNDEFINED,
0,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
{
CFG_OSE_HOSTNAME_2,
@@ -2044,7 +1775,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::STRING,
UNDEFINED,
0,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
{
CFG_CONNECTION_NODE_1,
@@ -2056,19 +1787,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::INT,
MANDATORY,
0,
- 0x7FFFFFFF },
-
- {
- KEY_INTERNAL,
- "ProcessId1",
- "OSE",
- "NodeId1",
- ConfigInfo::DEPRICATED,
- false,
- ConfigInfo::INT,
- UNDEFINED,
- 0,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
{
CFG_CONNECTION_NODE_2,
@@ -2080,19 +1799,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::INT,
UNDEFINED,
0,
- 0x7FFFFFFF },
-
- {
- KEY_INTERNAL,
- "ProcessId2",
- "OSE",
- "NodeId2",
- ConfigInfo::DEPRICATED,
- false,
- ConfigInfo::INT,
- MANDATORY,
- 0,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
{
CFG_CONNECTION_SEND_SIGNAL_ID,
@@ -2104,7 +1811,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::BOOL,
true,
0,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
{
CFG_CONNECTION_CHECKSUM,
@@ -2116,7 +1823,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::BOOL,
false,
0,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
{
CFG_OSE_PRIO_A_SIZE,
@@ -2128,7 +1835,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::INT,
1000,
0,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
{
CFG_OSE_PRIO_B_SIZE,
@@ -2140,7 +1847,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::INT,
1000,
0,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
{
CFG_OSE_RECEIVE_ARRAY_SIZE,
@@ -2152,19 +1859,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::INT,
10,
0,
- 0x7FFFFFFF },
-
- {
- KEY_INTERNAL,
- "Compression",
- "OSE",
- 0,
- ConfigInfo::DEPRICATED,
- false,
- ConfigInfo::BOOL,
- false,
- 0,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
{
CFG_CONNECTION_NODE_1_SYSTEM,
@@ -2176,7 +1871,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::STRING,
UNDEFINED,
0,
- 0x7FFFFFFF },
+ MAX_INT_RNIL},
{
CFG_CONNECTION_NODE_2_SYSTEM,
@@ -2188,7 +1883,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::STRING,
UNDEFINED,
0,
- 0x7FFFFFFF },
+ MAX_INT_RNIL },
};
const int ConfigInfo::m_NoOfParams = sizeof(m_ParamInfo) / sizeof(ParamInfo);
@@ -2197,22 +1892,21 @@ const int ConfigInfo::m_NoOfParams = sizeof(m_ParamInfo) / sizeof(ParamInfo);
/****************************************************************************
* Ctor
****************************************************************************/
-inline void require(bool v) { if(!v) abort();}
+static void require(bool v) { if(!v) abort();}
-ConfigInfo::ConfigInfo() {
+ConfigInfo::ConfigInfo()
+ : m_info(true), m_systemDefaults(true)
+{
+ int i;
Properties *section;
const Properties *oldpinfo;
- m_info.setCaseInsensitiveNames(true);
- m_systemDefaults.setCaseInsensitiveNames(true);
-
- for (int i=0; i<m_NoOfParams; i++) {
+ for (i=0; i<m_NoOfParams; i++) {
const ParamInfo & param = m_ParamInfo[i];
// Create new section if it did not exist
if (!m_info.getCopy(param._section, &section)) {
- Properties newsection;
- newsection.setCaseInsensitiveNames(true);
+ Properties newsection(true);
m_info.put(param._section, &newsection);
}
@@ -2220,7 +1914,7 @@ ConfigInfo::ConfigInfo() {
m_info.getCopy(param._section, &section);
// Create pinfo (parameter info) entry
- Properties pinfo;
+ Properties pinfo(true);
pinfo.put("Id", param._paramId);
pinfo.put("Fname", param._fname);
pinfo.put("Description", param._description);
@@ -2248,8 +1942,7 @@ ConfigInfo::ConfigInfo() {
if(param._type != ConfigInfo::SECTION){
Properties * p;
if(!m_systemDefaults.getCopy(param._section, &p)){
- p = new Properties();
- p->setCaseInsensitiveNames(true);
+ p = new Properties(true);
}
if(param._type != STRING &&
param._default != UNDEFINED &&
@@ -2261,7 +1954,7 @@ ConfigInfo::ConfigInfo() {
}
}
- for (int i=0; i<m_NoOfParams; i++) {
+ for (i=0; i<m_NoOfParams; i++) {
if(m_ParamInfo[i]._section == NULL){
ndbout << "Check that each entry has a section failed." << endl;
ndbout << "Parameter \"" << m_ParamInfo[i]._fname << endl;
@@ -2376,6 +2069,14 @@ ConfigInfo::isSection(const char * section) const {
return false;
}
+const char*
+ConfigInfo::getAlias(const char * section) const {
+ for (int i = 0; m_sectionNameAliases[i].name != 0; i++)
+ if(!strcmp(section, m_sectionNameAliases[i].alias))
+ return m_sectionNameAliases[i].name;
+ return 0;
+}
+
bool
ConfigInfo::verify(const Properties * section, const char* fname,
Uint64 value) const {
@@ -2489,11 +2190,27 @@ transformNode(InitConfigFileParser::Context & ctx, const char * data){
Uint32 id;
if(!ctx.m_currentSection->get("Id", &id)){
+ Uint32 nextNodeId= 1;
+ ctx.m_userProperties.get("NextNodeId", &nextNodeId);
+ id= nextNodeId;
+ while (ctx.m_userProperties.get("AllocatedNodeId_", id, &id))
+ id++;
+ ctx.m_userProperties.put("NextNodeId", id+1, true);
+ ctx.m_currentSection->put("Id", id);
+#if 0
ctx.reportError("Mandatory parameter Id missing from section "
"[%s] starting at line: %d",
ctx.fname, ctx.m_sectionLineno);
return false;
+#endif
+ } else if(ctx.m_userProperties.get("AllocatedNodeId_", id, &id)) {
+ ctx.reportError("Duplicate Id in section "
+ "[%s] starting at line: %d",
+ ctx.fname, ctx.m_sectionLineno);
+ return false;
}
+
+ ctx.m_userProperties.put("AllocatedNodeId_", id, id);
snprintf(ctx.pname, sizeof(ctx.pname), "Node_%d", id);
ctx.m_currentSection->put("Type", ctx.fname);
@@ -2502,6 +2219,13 @@ transformNode(InitConfigFileParser::Context & ctx, const char * data){
ctx.m_userProperties.get("NoOfNodes", &nodes);
ctx.m_userProperties.put("NoOfNodes", ++nodes, true);
+ /**
+ * Update count (per type)
+ */
+ nodes = 0;
+ ctx.m_userProperties.get(ctx.fname, &nodes);
+ ctx.m_userProperties.put(ctx.fname, ++nodes, true);
+
return true;
}
@@ -2510,10 +2234,16 @@ fixNodeHostname(InitConfigFileParser::Context & ctx, const char * data){
const char * compId;
if(!ctx.m_currentSection->get("ExecuteOnComputer", &compId)){
- ctx.reportError("Parameter \"ExecuteOnComputer\" missing from section "
- "[%s] starting at line: %d",
- ctx.fname, ctx.m_sectionLineno);
- return false;
+ require(ctx.m_currentSection->put("HostName", ""));
+
+ const char * type;
+ if(ctx.m_currentSection->get("Type", &type) && strcmp(type,"DB") == 0) {
+ ctx.reportError("Parameter \"ExecuteOnComputer\" missing from DB section"
+ " [%s] starting at line: %d",
+ ctx.fname, ctx.m_sectionLineno);
+ return false;
+ }
+ return true;
}
const Properties * computer;
@@ -2598,6 +2328,9 @@ transformSystem(InitConfigFileParser::Context & ctx, const char * data){
ctx.fname, ctx.m_sectionLineno);
return false;
}
+
+ ndbout << "transformSystem " << name << endl;
+
snprintf(ctx.pname, sizeof(ctx.pname), "SYSTEM_%s", name);
return true;
@@ -2638,6 +2371,22 @@ transformComputer(InitConfigFileParser::Context & ctx, const char * data){
ctx.m_userProperties.get("NoOfComputers", &computers);
ctx.m_userProperties.put("NoOfComputers", ++computers, true);
+ const char * hostname = 0;
+ ctx.m_currentSection->get("HostName", &hostname);
+ if(!hostname){
+ return true;
+ }
+
+ if(!strcmp(hostname, "localhost") || !strcmp(hostname, "127.0.0.1")){
+ if(ctx.m_userProperties.get("$computer-localhost", &hostname)){
+ ctx.reportError("Mixing of localhost with other hostname(%s) is illegal",
+ hostname);
+ return false;
+ }
+ } else {
+ ctx.m_userProperties.put("$computer-localhost", hostname);
+ }
+
return true;
}
@@ -2725,7 +2474,7 @@ checkMandatory(InitConfigFileParser::Context & ctx, const char * data){
* Transform a string "NodeidX" (e.g. "uppsala.32")
* into a Uint32 "NodeIdX" (e.g. 32) and a string "SystemX" (e.g. "uppsala").
*/
-bool fixNodeId(InitConfigFileParser::Context & ctx, const char * data)
+static bool fixNodeId(InitConfigFileParser::Context & ctx, const char * data)
{
char buf[] = "NodeIdX"; buf[6] = data[sizeof("NodeI")];
char sysbuf[] = "SystemX"; sysbuf[6] = data[sizeof("NodeI")];
@@ -2761,7 +2510,7 @@ bool fixNodeId(InitConfigFileParser::Context & ctx, const char * data)
* - name of external system in parameter extSystemName, and
* - nodeId of external node in parameter extSystemNodeId.
*/
-bool
+static bool
isExtConnection(InitConfigFileParser::Context & ctx,
const char **extSystemName, Uint32 * extSystemNodeId){
@@ -2789,7 +2538,7 @@ isExtConnection(InitConfigFileParser::Context & ctx,
* If connection is to an external system, then move connection into
* external system configuration (i.e. a sub-property).
*/
-bool
+static bool
fixExtConnection(InitConfigFileParser::Context & ctx, const char * data){
const char * extSystemName;
@@ -2844,7 +2593,7 @@ fixExtConnection(InitConfigFileParser::Context & ctx, const char * data){
* -# Via Node's ExecuteOnComputer lookup Hostname
* -# Add HostName to Connection
*/
-bool
+static bool
fixHostname(InitConfigFileParser::Context & ctx, const char * data){
char buf[] = "NodeIdX"; buf[6] = data[sizeof("HostNam")];
@@ -2867,28 +2616,61 @@ fixHostname(InitConfigFileParser::Context & ctx, const char * data){
/**
* Connection rule: Fix port number (using a port number adder)
*/
-bool
+static bool
fixPortNumber(InitConfigFileParser::Context & ctx, const char * data){
- if(!ctx.m_currentSection->contains("PortNumber")){
- Uint32 adder = 0;
- ctx.m_userProperties.get("PortNumberAdder", &adder);
- Uint32 base = 0;
- if(!(ctx.m_userDefaults && ctx.m_userDefaults->get("PortNumber", &base)) &&
- !ctx.m_systemDefaults->get("PortNumber", &base)){
- return false;
+ Uint32 id1= 0, id2= 0;
+ require(ctx.m_currentSection->get("NodeId1", &id1));
+ require(ctx.m_currentSection->get("NodeId2", &id2));
+ id1 = id1 < id2 ? id1 : id2;
+
+ const Properties * node;
+ require(ctx.m_config->get("Node", id1, &node));
+ BaseString hostname;
+ require(node->get("HostName", hostname));
+
+ if (hostname.c_str()[0] == 0) {
+ ctx.reportError("Hostname required on nodeid %d since it will act as server.", id1);
+ return false;
+ }
+
+ Uint32 port= 0;
+ if (!node->get("ServerPort", &port) && !ctx.m_userProperties.get("ServerPort_", id1, &port)) {
+ Uint32 adder= 0;
+ {
+ BaseString server_port_adder(hostname);
+ server_port_adder.append("_ServerPortAdder");
+ ctx.m_userProperties.get(server_port_adder.c_str(), &adder);
+ ctx.m_userProperties.put(server_port_adder.c_str(), adder+1, true);
+ }
+
+ Uint32 base= 0;
+ if (!ctx.m_userProperties.get("ServerPortBase", &base)){
+ if(!(ctx.m_userDefaults && ctx.m_userDefaults->get("PortNumber", &base)) &&
+ !ctx.m_systemDefaults->get("PortNumber", &base)) {
+ base= NDB_BASE_PORT+2;
+ // ctx.reportError("Cannot retrieve base port number");
+ // return false;
+ }
+ ctx.m_userProperties.put("ServerPortBase", base);
}
- ctx.m_currentSection->put("PortNumber", base + adder);
- adder++;
- ctx.m_userProperties.put("PortNumberAdder", adder, true);
+ port= base + adder;
+ ctx.m_userProperties.put("ServerPort_", id1, port);
}
+
+ if(ctx.m_currentSection->contains("PortNumber")) {
+ ndbout << "PortNumber should no longer be specificied per connection, please remove from config. Will be changed to " << port << endl;
+ ctx.m_currentSection->put("PortNumber", port, true);
+ } else
+ ctx.m_currentSection->put("PortNumber", port);
+
return true;
}
/**
* DB Node rule: Check various constraints
*/
-bool
+static bool
checkDbConstraints(InitConfigFileParser::Context & ctx, const char *){
Uint32 t1 = 0, t2 = 0;
@@ -2921,7 +2703,7 @@ checkDbConstraints(InitConfigFileParser::Context & ctx, const char *){
/**
* Connection rule: Check varius constraints
*/
-bool
+static bool
checkConnectionConstraints(InitConfigFileParser::Context & ctx, const char *){
Uint32 id1 = 0, id2 = 0;
@@ -2977,6 +2759,22 @@ checkConnectionConstraints(InitConfigFileParser::Context & ctx, const char *){
ctx.fname, ctx.m_sectionLineno);
return false;
}
+
+ return true;
+}
+
+static bool
+checkTCPConstraints(InitConfigFileParser::Context & ctx, const char * data){
+
+ const char * host;
+ struct in_addr addr;
+ if(ctx.m_currentSection->get(data, &host) && strlen(host) &&
+ Ndb_getInAddr(&addr, host)){
+ ctx.reportError("Unable to lookup/illegal hostname %s"
+ " - [%s] starting at line: %d",
+ host, ctx.fname, ctx.m_sectionLineno);
+ return false;
+ }
return true;
}
@@ -3000,7 +2798,8 @@ transform(InitConfigFileParser::Context & ctx,
require(ctx.m_currentSection->getTypeOf(oldName, &oldType));
ConfigInfo::Type newType = ctx.m_info->getType(ctx.m_currentInfo, newName);
if(!((oldType == PropertiesType_Uint32 || oldType == PropertiesType_Uint64)
- && (newType == ConfigInfo::INT || newType == ConfigInfo::INT64))){
+ && (newType == ConfigInfo::INT || newType == ConfigInfo::INT64 || newType == ConfigInfo::BOOL))){
+ ndbout << "oldType: " << (int)oldType << ", newType: " << (int)newType << endl;
ctx.reportError("Unable to handle type conversion w.r.t deprication %s %s"
"- [%s] starting at line: %d",
oldName, newName,
@@ -3019,23 +2818,24 @@ transform(InitConfigFileParser::Context & ctx,
return false;
}
- if(newType == ConfigInfo::INT){
+ if(newType == ConfigInfo::INT || newType == ConfigInfo::BOOL){
require(dst.put(newName, (Uint32)newVal));
- } else {
+ } else if(newType == ConfigInfo::INT64) {
require(dst.put64(newName, newVal));
}
return true;
}
-bool
+static bool
fixDepricated(InitConfigFileParser::Context & ctx, const char * data){
+ const char * name;
/**
* Transform old values to new values
* Transform new values to old values (backward compatible)
*/
- Properties tmp;
+ Properties tmp(true);
Properties::Iterator it(ctx.m_currentSection);
- for (const char* name = it.first(); name != NULL; name = it.next()) {
+ for (name = it.first(); name != NULL; name = it.next()) {
const DepricationTransform * p = &f_deprication[0];
while(p->m_section != 0){
if(strcmp(p->m_section, ctx.fname) == 0){
@@ -3056,7 +2856,7 @@ fixDepricated(InitConfigFileParser::Context & ctx, const char * data){
}
Properties::Iterator it2(&tmp);
- for (const char* name = it2.first(); name != NULL; name = it2.next()) {
+ for (name = it2.first(); name != NULL; name = it2.next()) {
PropertiesType type;
require(tmp.getTypeOf(name, &type));
switch(type){
@@ -3086,7 +2886,7 @@ fixDepricated(InitConfigFileParser::Context & ctx, const char * data){
return true;
}
-bool
+static bool
saveInConfigValues(InitConfigFileParser::Context & ctx, const char * data){
const Properties * sec;
if(!ctx.m_currentInfo->get(ctx.fname, &sec)){
@@ -3151,22 +2951,24 @@ saveInConfigValues(InitConfigFileParser::Context & ctx, const char * data){
default:
abort();
}
+ require(ok);
}
ctx.m_configValues.closeSection();
} while(0);
return true;
}
-bool
-addNodeConnections(Vector<ConfigInfo::ConfigRuleSection>&sections,
+static bool
+add_node_connections(Vector<ConfigInfo::ConfigRuleSection>&sections,
struct InitConfigFileParser::Context &ctx,
- const char * ruleData)
+ const char * rule_data)
{
+ Uint32 i;
Properties * props= ctx.m_config;
- Properties p_connections;
- Properties p_connections2;
+ Properties p_connections(true);
+ Properties p_connections2(true);
- for (Uint32 i = 0;; i++){
+ for (i = 0;; i++){
const Properties * tmp;
Uint32 nodeId1, nodeId2;
@@ -3184,11 +2986,11 @@ addNodeConnections(Vector<ConfigInfo::ConfigRuleSection>&sections,
Uint32 nNodes;
ctx.m_userProperties.get("NoOfNodes", &nNodes);
- Properties p_db_nodes;
- Properties p_api_mgm_nodes;
+ Properties p_db_nodes(true);
+ Properties p_api_mgm_nodes(true);
- Uint32 i_db= 0, i_api_mgm= 0;
- for (Uint32 i= 0, n= 0; n < nNodes; i++){
+ Uint32 i_db= 0, i_api_mgm= 0, n;
+ for (i= 0, n= 0; n < nNodes; i++){
const Properties * tmp;
if(!props->get("Node", i, &tmp)) continue;
n++;
@@ -3205,13 +3007,13 @@ addNodeConnections(Vector<ConfigInfo::ConfigRuleSection>&sections,
Uint32 nodeId1, nodeId2, dummy;
- for (Uint32 i= 0; p_db_nodes.get("", i, &nodeId1); i++){
+ for (i= 0; p_db_nodes.get("", i, &nodeId1); i++){
for (Uint32 j= i+1;; j++){
if(!p_db_nodes.get("", j, &nodeId2)) break;
if(!p_connections2.get("", nodeId1+nodeId2<<16, &dummy)) {
ConfigInfo::ConfigRuleSection s;
s.m_sectionType= BaseString("TCP");
- s.m_sectionData= new Properties;
+ s.m_sectionData= new Properties(true);
char buf[16];
snprintf(buf, sizeof(buf), "%u", nodeId1);
s.m_sectionData->put("NodeId1", buf);
@@ -3222,13 +3024,13 @@ addNodeConnections(Vector<ConfigInfo::ConfigRuleSection>&sections,
}
}
- for (Uint32 i= 0; p_api_mgm_nodes.get("", i, &nodeId1); i++){
+ for (i= 0; p_api_mgm_nodes.get("", i, &nodeId1); i++){
if(!p_connections.get("", nodeId1, &dummy)) {
for (Uint32 j= 0;; j++){
if(!p_db_nodes.get("", j, &nodeId2)) break;
ConfigInfo::ConfigRuleSection s;
s.m_sectionType= BaseString("TCP");
- s.m_sectionData= new Properties;
+ s.m_sectionData= new Properties(true);
char buf[16];
snprintf(buf, sizeof(buf), "%u", nodeId1);
s.m_sectionData->put("NodeId1", buf);
@@ -3241,3 +3043,63 @@ addNodeConnections(Vector<ConfigInfo::ConfigRuleSection>&sections,
return true;
}
+
+
+static bool add_server_ports(Vector<ConfigInfo::ConfigRuleSection>&sections,
+ struct InitConfigFileParser::Context &ctx,
+ const char * rule_data)
+{
+#if 0
+ Properties * props= ctx.m_config;
+ Properties computers(true);
+ Uint32 port_base = NDB_BASE_PORT+2;
+
+ Uint32 nNodes;
+ ctx.m_userProperties.get("NoOfNodes", &nNodes);
+
+ for (Uint32 i= 0, n= 0; n < nNodes; i++){
+ Properties * tmp;
+ if(!props->get("Node", i, &tmp)) continue;
+ n++;
+
+ const char * type;
+ if(!tmp->get("Type", &type)) continue;
+
+ Uint32 port;
+ if (tmp->get("ServerPort", &port)) continue;
+
+ Uint32 computer;
+ if (!tmp->get("ExecuteOnComputer", &computer)) continue;
+
+ Uint32 adder= 0;
+ computers.get("",computer, &adder);
+
+ if (strcmp(type,"DB") == 0) {
+ adder++;
+ tmp->put("ServerPort", port_base+adder);
+ computers.put("",computer, adder);
+ }
+ }
+#endif
+ return true;
+}
+
+static bool
+check_node_vs_replicas(Vector<ConfigInfo::ConfigRuleSection>&sections,
+ struct InitConfigFileParser::Context &ctx,
+ const char * rule_data)
+{
+ Uint32 db_nodes = 0;
+ Uint32 replicas = 0;
+ ctx.m_userProperties.get("DB", &db_nodes);
+ ctx.m_userProperties.get("NoOfReplicas", &replicas);
+ if((db_nodes % replicas) != 0){
+ ctx.reportError("Invalid no of db nodes wrt no of replicas.\n"
+ "No of nodes must be dividable with no or replicas");
+ return false;
+ }
+
+ return true;
+}
+
+template class Vector<ConfigInfo::ConfigRuleSection>;
diff --git a/ndb/src/common/mgmcommon/ConfigInfo.hpp b/ndb/src/common/mgmcommon/ConfigInfo.hpp
index 79c17b436fe..9a954fe78d5 100644
--- a/ndb/src/common/mgmcommon/ConfigInfo.hpp
+++ b/ndb/src/common/mgmcommon/ConfigInfo.hpp
@@ -61,6 +61,11 @@ public:
Uint64 _max;
};
+ struct AliasPair{
+ const char * name;
+ const char * alias;
+ };
+
/**
* Entry for one section rule
*/
@@ -100,6 +105,7 @@ public:
* @note Result is not defined if section/name are wrong!
*/
bool verify(const Properties* secti, const char* fname, Uint64 value) const;
+ const char* getAlias(const char*) const;
bool isSection(const char*) const;
const char* getDescription(const Properties * sec, const char* fname) const;
@@ -123,6 +129,7 @@ private:
static const ParamInfo m_ParamInfo[];
static const int m_NoOfParams;
+ static const AliasPair m_sectionNameAliases[];
static const char* m_sectionNames[];
static const int m_noOfSectionNames;
diff --git a/ndb/src/common/mgmcommon/ConfigRetriever.cpp b/ndb/src/common/mgmcommon/ConfigRetriever.cpp
index d2c622593de..2e809907058 100644
--- a/ndb/src/common/mgmcommon/ConfigRetriever.cpp
+++ b/ndb/src/common/mgmcommon/ConfigRetriever.cpp
@@ -37,37 +37,26 @@
#include <mgmapi.h>
#include <mgmapi_config_parameters.h>
+#include <mgmapi_configuration.hpp>
#include <ConfigValues.hpp>
#include <NdbHost.h>
//****************************************************************************
//****************************************************************************
-ConfigRetriever::ConfigRetriever() {
+ConfigRetriever::ConfigRetriever(Uint32 version, Uint32 node_type) {
- _localConfigFileName = NULL;
- m_defaultConnectString = NULL;
-
-
- errorString = 0;
- _localConfig = new LocalConfig();
- m_connectString = NULL;
+ m_handle= 0;
+ m_version = version;
+ m_node_type = node_type;
}
ConfigRetriever::~ConfigRetriever(){
- if(_localConfigFileName != 0)
- free(_localConfigFileName);
-
- if(m_defaultConnectString != 0)
- free(m_defaultConnectString);
- if(m_connectString != 0)
- free(m_connectString);
-
- if(errorString != 0)
- free(errorString);
-
- delete _localConfig;
+ if (m_handle) {
+ ndb_mgm_disconnect(m_handle);
+ ndb_mgm_destroy_handle(&m_handle);
+ }
}
@@ -75,67 +64,51 @@ ConfigRetriever::~ConfigRetriever(){
//****************************************************************************
int
-ConfigRetriever::init(bool onlyNodeId) {
- if (_localConfig->init(onlyNodeId, m_connectString, _localConfigFileName, m_defaultConnectString)) {
- return _ownNodeId = (*_localConfig)._ownNodeId;
+ConfigRetriever::init() {
+ if (!_localConfig.init(m_connectString.c_str(),
+ _localConfigFileName.c_str())){
+
+ setError(CR_ERROR, "error in retrieving contact info for mgmtsrvr");
+ _localConfig.printError();
+ _localConfig.printUsage();
+ return -1;
}
-
- setError(CR_ERROR, "error in retrieving contact info for mgmtsrvr");
- _localConfig->printError();
- _localConfig->printUsage();
-
- return -1;
-}
-//****************************************************************************
-//****************************************************************************
-//****************************************************************************
-//****************************************************************************
-struct ndb_mgm_configuration*
-ConfigRetriever::getConfig(int verId, int nodeType) {
+ return _ownNodeId = _localConfig._ownNodeId;
+}
- int res = init();
- if (res == -1) {
- return 0;
- }
+int
+ConfigRetriever::do_connect(){
- if (_localConfig->items == 0){
- setError(CR_ERROR,"No Management Servers configured in local config file");
- return 0;
+ if(!m_handle)
+ m_handle= ndb_mgm_create_handle();
+
+ if (m_handle == 0) {
+ setError(CR_ERROR, "Unable to allocate mgm handle");
+ return -1;
}
int retry = 1;
int retry_max = 12; // Max number of retry attempts
int retry_interval= 5; // Seconds between each retry
- do {
+ while(retry < retry_max){
Uint32 type = CR_ERROR;
- for (int i = 0; i<_localConfig->items; i++){
- MgmtSrvrId * m = _localConfig->ids[i];
- struct ndb_mgm_configuration * p = 0;
+ BaseString tmp;
+ for (int i = 0; i<_localConfig.ids.size(); i++){
+ MgmtSrvrId * m = &_localConfig.ids[i];
switch(m->type){
case MgmId_TCP:
- p = getConfig(m->data.tcp.remoteHost, m->data.tcp.port, verId);
- break;
- case MgmId_File:
- p = getConfig(m->data.file.filename, verId);
- break;
- default:
- setError(CR_ERROR, "Unknown error type");
- break;
- }
-
- if (p != 0) {
- if(!verifyConfig(p, nodeType)){
- free(p);
+ tmp.assfmt("%s:%d", m->name.c_str(), m->port);
+ if (ndb_mgm_connect(m_handle, tmp.c_str()) == 0) {
return 0;
}
- return p;
+ setError(CR_RETRY, ndb_mgm_get_latest_error_desc(m_handle));
+ case MgmId_File:
+ break;
}
- if(latestErrorType == CR_RETRY)
- type = CR_RETRY;
- } // for
-
- if(type == CR_RETRY){
+ }
+
+ if(latestErrorType == CR_RETRY){
REPORT_WARNING("Failed to retrieve cluster configuration");
ndbout << "(Cause of failure: " << getErrorString() << ")" << endl;
ndbout << "Attempt " << retry << " of " << retry_max << ". "
@@ -146,60 +119,63 @@ ConfigRetriever::getConfig(int verId, int nodeType) {
break;
}
retry++;
-
- } while (retry <= retry_max);
+ }
- return 0;
+ ndb_mgm_destroy_handle(&m_handle);
+ m_handle= 0;
+ return -1;
}
-ndb_mgm_configuration *
-ConfigRetriever::getConfig(const char * mgmhost,
- short port,
- int versionId){
-
- NdbMgmHandle h;
- h = ndb_mgm_create_handle();
- if (h == NULL) {
- setError(CR_ERROR, "Unable to allocate mgm handle");
- return 0;
- }
+//****************************************************************************
+//****************************************************************************
+//****************************************************************************
+//****************************************************************************
+struct ndb_mgm_configuration*
+ConfigRetriever::getConfig() {
+
+ struct ndb_mgm_configuration * p = 0;
- BaseString tmp;
- tmp.assfmt("%s:%d", mgmhost, port);
- if (ndb_mgm_connect(h, tmp.c_str()) != 0) {
- setError(CR_RETRY, ndb_mgm_get_latest_error_desc(h));
- ndb_mgm_destroy_handle(&h);
+ if(m_handle != 0){
+ p = getConfig(m_handle);
+ } else {
+ for (int i = 0; i<_localConfig.ids.size(); i++){
+ MgmtSrvrId * m = &_localConfig.ids[i];
+ switch(m->type){
+ case MgmId_File:
+ p = getConfig(m->name.c_str());
+ break;
+ case MgmId_TCP:
+ break;
+ }
+ if(p)
+ break;
+ }
+ }
+ if(p == 0)
return 0;
+
+ if(!verifyConfig(p)){
+ free(p);
+ p= 0;
}
+
+ return p;
+}
- ndb_mgm_configuration * conf = ndb_mgm_get_configuration(h, versionId);
+ndb_mgm_configuration *
+ConfigRetriever::getConfig(NdbMgmHandle m_handle){
+
+ ndb_mgm_configuration * conf = ndb_mgm_get_configuration(m_handle,m_version);
if(conf == 0){
- setError(CR_ERROR, ndb_mgm_get_latest_error_desc(h));
- }
-
- ndb_mgm_disconnect(h);
- ndb_mgm_destroy_handle(&h);
-
- return conf;
-#if 0
- bool compatible;
- if (global_ndb_check)
- compatible = ndbCompatible_ndb_mgmt(versionId, version);
- else
- compatible = ndbCompatible_api_mgmt(versionId, version);
-
- if(!compatible){ // if(version != versionId){
- NDB_CLOSE_SOCKET(sockfd);
- snprintf(err_buf, sizeof(err_buf), "Management Server: Invalid version. "
- "Version from server: %d Own version: %d", version, versionId);
- setError(CR_ERROR, err_buf);
+ setError(CR_ERROR, ndb_mgm_get_latest_error_desc(m_handle));
return 0;
}
-#endif
+
+ return conf;
}
ndb_mgm_configuration *
-ConfigRetriever::getConfig(const char * filename, int versionId){
+ConfigRetriever::getConfig(const char * filename){
struct stat sbuf;
const int res = stat(filename, &sbuf);
@@ -242,60 +218,29 @@ ConfigRetriever::getConfig(const char * filename, int versionId){
void
ConfigRetriever::setError(ErrorType et, const char * s){
- if(errorString != 0){
- free(errorString);
- }
- if(s == 0)
- errorString = 0;
- else
- errorString = strdup(s);
+ errorString.assign(s ? s : "");
latestErrorType = et;
}
const char *
ConfigRetriever::getErrorString(){
- return errorString;
+ return errorString.c_str();
}
void
ConfigRetriever::setLocalConfigFileName(const char * localConfigFileName) {
- if(_localConfigFileName != 0)
- free(_localConfigFileName);
- if(localConfigFileName != 0)
- _localConfigFileName = strdup(localConfigFileName);
- else
- _localConfigFileName = 0;
+ _localConfigFileName.assign(localConfigFileName ? localConfigFileName : "");
}
void
ConfigRetriever::setConnectString(const char * connectString) {
- if(m_connectString != 0)
- free(m_connectString);
- if (connectString != 0) {
- m_connectString = strdup(connectString);
- } else {
- m_connectString = 0;
- }
-}
-
-/**
- * @note Do not use! Use the one above if possible. /elathal
- */
-void
-ConfigRetriever::setDefaultConnectString(const char * defaultConnectString) {
- if(m_defaultConnectString != 0)
- free(m_defaultConnectString);
- if (defaultConnectString != 0) {
- m_defaultConnectString = strdup(defaultConnectString);
- } else {
- m_defaultConnectString = 0;
- }
+ m_connectString.assign(connectString ? connectString : "");
}
bool
-ConfigRetriever::verifyConfig(const struct ndb_mgm_configuration * conf,
- int type){
+ConfigRetriever::verifyConfig(const struct ndb_mgm_configuration * conf){
+
char buf[255];
ndb_mgm_configuration_iterator * it;
it = ndb_mgm_create_configuration_iterator((struct ndb_mgm_configuration *)conf, CFG_SECTION_NODE);
@@ -308,8 +253,8 @@ ConfigRetriever::verifyConfig(const struct ndb_mgm_configuration * conf,
}
NdbAutoPtr<ndb_mgm_configuration_iterator> ptr(it);
- if(ndb_mgm_find(it, CFG_NODE_ID, getOwnNodeId()) != 0){
- snprintf(buf, 255, "Unable to find node with id: %d", getOwnNodeId());
+ if(ndb_mgm_find(it, CFG_NODE_ID, _ownNodeId) != 0){
+ snprintf(buf, 255, "Unable to find node with id: %d", _ownNodeId);
setError(CR_ERROR, buf);
return false;
}
@@ -323,12 +268,15 @@ ConfigRetriever::verifyConfig(const struct ndb_mgm_configuration * conf,
char localhost[MAXHOSTNAMELEN];
if(NdbHost_GetHostName(localhost) != 0){
- snprintf(buf, 255, "Unable to own hostname");
+ snprintf(buf, 255, "Unable to get own hostname");
setError(CR_ERROR, buf);
return false;
}
do {
+ if(strlen(hostname) == 0)
+ break;
+
if(strcasecmp(hostname, localhost) == 0)
break;
@@ -363,11 +311,67 @@ ConfigRetriever::verifyConfig(const struct ndb_mgm_configuration * conf,
return false;
}
- if(_type != type){
+ if(_type != m_node_type){
snprintf(buf, 255, "Supplied node type(%d) and config node type(%d) "
- " don't match", type, _type);
+ " don't match", m_node_type, _type);
setError(CR_ERROR, buf);
return false;
}
+
+ /**
+ * Check hostnames
+ */
+ ndb_mgm_configuration_iterator iter(* conf, CFG_SECTION_CONNECTION);
+ for(iter.first(); iter.valid(); iter.next()){
+
+ Uint32 type = CONNECTION_TYPE_TCP + 1;
+ if(iter.get(CFG_TYPE_OF_SECTION, &type)) continue;
+ if(type != CONNECTION_TYPE_TCP) continue;
+
+ Uint32 nodeId1, nodeId2, remoteNodeId;
+ if(iter.get(CFG_CONNECTION_NODE_1, &nodeId1)) continue;
+ if(iter.get(CFG_CONNECTION_NODE_2, &nodeId2)) continue;
+
+ if(nodeId1 != _ownNodeId && nodeId2 != _ownNodeId) continue;
+ remoteNodeId = (_ownNodeId == nodeId1 ? nodeId2 : nodeId1);
+
+ const char * name;
+ struct in_addr addr;
+ BaseString tmp;
+ if(!iter.get(CFG_TCP_HOSTNAME_1, &name) && strlen(name)){
+ if(Ndb_getInAddr(&addr, name) != 0){
+ tmp.assfmt("Unable to lookup/illegal hostname %s, "
+ "connection from node %d to node %d",
+ name, _ownNodeId, remoteNodeId);
+ setError(CR_ERROR, tmp.c_str());
+ return false;
+ }
+ }
+
+ if(!iter.get(CFG_TCP_HOSTNAME_2, &name) && strlen(name)){
+ if(Ndb_getInAddr(&addr, name) != 0){
+ tmp.assfmt("Unable to lookup/illegal hostname %s, "
+ "connection from node %d to node %d",
+ name, _ownNodeId, remoteNodeId);
+ setError(CR_ERROR, tmp.c_str());
+ return false;
+ }
+ }
+ }
return true;
}
+
+Uint32
+ConfigRetriever::allocNodeId(){
+ unsigned nodeid= _ownNodeId;
+
+ if(m_handle != 0){
+ int res= ndb_mgm_alloc_nodeid(m_handle, m_version, &nodeid, m_node_type);
+ if(res != 0) {
+ setError(CR_ERROR, ndb_mgm_get_latest_error_desc(m_handle));
+ return 0;
+ }
+ }
+
+ return _ownNodeId= nodeid;
+}
diff --git a/ndb/src/common/mgmcommon/IPCConfig.cpp b/ndb/src/common/mgmcommon/IPCConfig.cpp
index ba5fe7ace80..a76c541f3f6 100644
--- a/ndb/src/common/mgmcommon/IPCConfig.cpp
+++ b/ndb/src/common/mgmcommon/IPCConfig.cpp
@@ -339,12 +339,13 @@ IPCConfig::getNodeType(NodeId id) const {
return out;
}
+#include <mgmapi.h>
Uint32
IPCConfig::configureTransporters(Uint32 nodeId,
const class ndb_mgm_configuration & config,
class TransporterRegistry & tr){
- Uint32 noOfTransportersCreated = 0;
+ Uint32 noOfTransportersCreated= 0, server_port= 0;
ndb_mgm_configuration_iterator iter(config, CFG_SECTION_CONNECTION);
for(iter.first(); iter.valid(); iter.next()){
@@ -364,6 +365,16 @@ IPCConfig::configureTransporters(Uint32 nodeId,
Uint32 type = ~0;
if(iter.get(CFG_TYPE_OF_SECTION, &type)) continue;
+ Uint32 tmp_server_port= 0;
+ if(iter.get(CFG_CONNECTION_SERVER_PORT, &tmp_server_port)) break;
+ if (nodeId <= nodeId1 && nodeId <= nodeId2) {
+ if (server_port && server_port != tmp_server_port) {
+ ndbout << "internal error in config setup of server ports line= " << __LINE__ << endl;
+ exit(-1);
+ }
+ server_port= tmp_server_port;
+ }
+
switch(type){
case CONNECTION_TYPE_SHM:{
SHM_TransporterConfiguration conf;
@@ -377,6 +388,8 @@ IPCConfig::configureTransporters(Uint32 nodeId,
if(iter.get(CFG_SHM_KEY, &conf.shmKey)) break;
if(iter.get(CFG_SHM_BUFFER_MEM, &conf.shmSize)) break;
+ conf.port= tmp_server_port;
+
if(!tr.createTransporter(&conf)){
ndbout << "Failed to create SHM Transporter from: "
<< conf.localNodeId << " to: " << conf.remoteNodeId << endl;
@@ -428,10 +441,10 @@ IPCConfig::configureTransporters(Uint32 nodeId,
if(iter.get(CFG_TCP_HOSTNAME_1, &host1)) break;
if(iter.get(CFG_TCP_HOSTNAME_2, &host2)) break;
- if(iter.get(CFG_TCP_SERVER_PORT, &conf.port)) break;
if(iter.get(CFG_TCP_SEND_BUFFER_SIZE, &conf.sendBufferSize)) break;
if(iter.get(CFG_TCP_RECEIVE_BUFFER_SIZE, &conf.maxReceiveSize)) break;
+ conf.port= tmp_server_port;
const char * proxy;
if (!iter.get(CFG_TCP_PROXY, &proxy)) {
if (strlen(proxy) > 0 && nodeId2 == nodeId) {
@@ -490,6 +503,8 @@ IPCConfig::configureTransporters(Uint32 nodeId,
}
}
+ tr.m_service_port= server_port;
+
return noOfTransportersCreated;
}
diff --git a/ndb/src/common/mgmcommon/InitConfigFileParser.cpp b/ndb/src/common/mgmcommon/InitConfigFileParser.cpp
index d52bc54db52..7c842508491 100644
--- a/ndb/src/common/mgmcommon/InitConfigFileParser.cpp
+++ b/ndb/src/common/mgmcommon/InitConfigFileParser.cpp
@@ -43,10 +43,10 @@ InitConfigFileParser::~InitConfigFileParser() {
// Read Config File
//****************************************************************************
InitConfigFileParser::Context::Context(const ConfigInfo * info)
- : m_configValues(1000, 20) {
+ : m_configValues(1000, 20), m_userProperties(true) {
- m_config = new Properties();
- m_defaults = new Properties();
+ m_config = new Properties(true);
+ m_defaults = new Properties(true);
}
InitConfigFileParser::Context::~Context(){
@@ -115,7 +115,7 @@ InitConfigFileParser::parseConfig(FILE * file) {
snprintf(ctx.fname, sizeof(ctx.fname), section); free(section);
ctx.type = InitConfigFileParser::DefaultSection;
ctx.m_sectionLineno = ctx.m_lineno;
- ctx.m_currentSection = new Properties();
+ ctx.m_currentSection = new Properties(true);
ctx.m_userDefaults = NULL;
ctx.m_currentInfo = m_info->getInfo(ctx.fname);
ctx.m_systemDefaults = m_info->getDefaults(ctx.fname);
@@ -137,7 +137,7 @@ InitConfigFileParser::parseConfig(FILE * file) {
free(section);
ctx.type = InitConfigFileParser::Section;
ctx.m_sectionLineno = ctx.m_lineno;
- ctx.m_currentSection = new Properties();
+ ctx.m_currentSection = new Properties(true);
ctx.m_userDefaults = getSection(ctx.fname, ctx.m_defaults);
ctx.m_currentInfo = m_info->getInfo(ctx.fname);
ctx.m_systemDefaults = m_info->getDefaults(ctx.fname);
@@ -222,6 +222,8 @@ bool InitConfigFileParser::parseNameValuePair(Context& ctx, const char* line) {
char tmpLine[MAX_LINE_LENGTH];
char fname[MAX_LINE_LENGTH], rest[MAX_LINE_LENGTH];
char* t;
+ const char *separator_list[]= {":", "=", 0};
+ const char *separator= 0;
if (ctx.m_currentSection == NULL){
ctx.reportError("Value specified outside section");
@@ -233,7 +235,14 @@ bool InitConfigFileParser::parseNameValuePair(Context& ctx, const char* line) {
// *************************************
// Check if a separator exists in line
// *************************************
- if (!strchr(tmpLine, ':')) {
+ for(int i= 0; separator_list[i] != 0; i++) {
+ if(strchr(tmpLine, separator_list[i][0])) {
+ separator= separator_list[i];
+ break;
+ }
+ }
+
+ if (separator == 0) {
ctx.reportError("Parse error");
return false;
}
@@ -241,13 +250,13 @@ bool InitConfigFileParser::parseNameValuePair(Context& ctx, const char* line) {
// *******************************************
// Get pointer to substring before separator
// *******************************************
- t = strtok(tmpLine, ":");
+ t = strtok(tmpLine, separator);
// *****************************************
// Count number of tokens before separator
// *****************************************
if (sscanf(t, "%120s%120s", fname, rest) != 1) {
- ctx.reportError("Multiple names before \':\'");
+ ctx.reportError("Multiple names before \'%c\'", separator[0]);
return false;
}
if (!ctx.m_currentInfo->contains(fname)) {
@@ -475,8 +484,24 @@ InitConfigFileParser::parseSectionHeader(const char* line) const {
tmp[0] = ' ';
trim(tmp);
+ // Convert section header to upper
+ for(int i= strlen(tmp)-1; i >= 0; i--)
+ tmp[i]= toupper(tmp[i]);
+
+ // Get the correct header name if an alias
+ {
+ const char *tmp_alias= m_info->getAlias(tmp);
+ if (tmp_alias) {
+ free(tmp);
+ tmp= strdup(tmp_alias);
+ }
+ }
+
// Lookup token among sections
- if(!m_info->isSection(tmp)) return NULL;
+ if(!m_info->isSection(tmp)) {
+ free(tmp);
+ return NULL;
+ }
if(m_info->getInfo(tmp)) return tmp;
free(tmp);
@@ -497,7 +522,7 @@ InitConfigFileParser::parseDefaultSectionHeader(const char* line) const {
if (no != 2) return NULL;
// Not correct keyword at end
- if (!strcmp(token2, "DEFAULT") == 0) return NULL;
+ if (!strcasecmp(token2, "DEFAULT") == 0) return NULL;
if(m_info->getInfo(token1)){
return strdup(token1);
diff --git a/ndb/src/common/mgmcommon/LocalConfig.cpp b/ndb/src/common/mgmcommon/LocalConfig.cpp
index 12e685ced34..0440ce84dba 100644
--- a/ndb/src/common/mgmcommon/LocalConfig.cpp
+++ b/ndb/src/common/mgmcommon/LocalConfig.cpp
@@ -17,17 +17,16 @@
#include "LocalConfig.hpp"
#include <NdbEnv.h>
#include <NdbConfig.h>
+#include <NdbAutoPtr.hpp>
LocalConfig::LocalConfig(){
- ids = 0; size = 0; items = 0;
error_line = 0; error_msg[0] = 0;
+ _ownNodeId= 0;
}
bool
-LocalConfig::init(bool onlyNodeId,
- const char *connectString,
- const char *fileName,
- const char *defaultConnectString) {
+LocalConfig::init(const char *connectString,
+ const char *fileName) {
/**
* Escalation:
* 1. Check connectString
@@ -39,8 +38,8 @@ LocalConfig::init(bool onlyNodeId,
*/
//1. Check connectString
- if(connectString != 0) {
- if(readConnectString(connectString, onlyNodeId)){
+ if(connectString != 0 && connectString[0] != 0){
+ if(readConnectString(connectString)){
return true;
}
return false;
@@ -49,7 +48,7 @@ LocalConfig::init(bool onlyNodeId,
//2. Check given filename
if (fileName && strlen(fileName) > 0) {
bool fopenError;
- if(readFile(fileName, fopenError, onlyNodeId)){
+ if(readFile(fileName, fopenError)){
return true;
}
return false;
@@ -59,7 +58,7 @@ LocalConfig::init(bool onlyNodeId,
char buf[255];
if(NdbEnv_GetEnv("NDB_CONNECTSTRING", buf, sizeof(buf)) &&
strlen(buf) != 0){
- if(readConnectString(buf, onlyNodeId)){
+ if(readConnectString(buf)){
return true;
}
return false;
@@ -68,10 +67,10 @@ LocalConfig::init(bool onlyNodeId,
//4. Check Ndb.cfg in NDB_HOME
{
bool fopenError;
- char buf[256];
- if(readFile(NdbConfig_NdbCfgName(buf, sizeof(buf), 1 /*true*/), fopenError, onlyNodeId)){
+ char *buf= NdbConfig_NdbCfgName(1 /*true*/);
+ NdbAutoPtr<char> tmp_aptr(buf);
+ if(readFile(buf, fopenError))
return true;
- }
if (!fopenError)
return false;
}
@@ -79,20 +78,20 @@ LocalConfig::init(bool onlyNodeId,
//5. Check Ndb.cfg in cwd
{
bool fopenError;
- char buf[256];
- if(readFile(NdbConfig_NdbCfgName(buf, sizeof(buf), 0 /*false*/), fopenError, onlyNodeId)){
+ char *buf= NdbConfig_NdbCfgName(0 /*false*/);
+ NdbAutoPtr<char> tmp_aptr(buf);
+ if(readFile(buf, fopenError))
return true;
- }
if (!fopenError)
return false;
}
- //6. Check defaultConnectString
- if(defaultConnectString != 0) {
- if(readConnectString(defaultConnectString, onlyNodeId)){
+ //7. Check
+ {
+ char buf[256];
+ snprintf(buf, sizeof(buf), "host=localhost:%u", NDB_BASE_PORT);
+ if(readConnectString(buf))
return true;
- }
- return false;
}
setError(0, "");
@@ -101,30 +100,8 @@ LocalConfig::init(bool onlyNodeId,
}
LocalConfig::~LocalConfig(){
- for(int i = 0; i<items; i++){
- if(ids[i]->type == MgmId_TCP)
- free(ids[i]->data.tcp.remoteHost);
- else if(ids[i]->type == MgmId_File)
- free(ids[i]->data.file.filename);
- delete ids[i];
- }
- if(ids != 0)
- delete[] ids;
}
-void LocalConfig::add(MgmtSrvrId * i){
- if(items == size){
- MgmtSrvrId ** tmp = new MgmtSrvrId * [size+10];
- if(ids != 0){
- memcpy(tmp, ids, items*sizeof(MgmtSrvrId *));
- delete []ids;
- }
- ids = tmp;
- }
- ids[items] = i;
- items++;
-}
-
void LocalConfig::setError(int lineNumber, const char * _msg) {
error_line = lineNumber;
strncpy(error_msg, _msg, sizeof(error_msg));
@@ -144,22 +121,22 @@ void LocalConfig::printUsage() const {
ndbout << "1. Put a Ndb.cfg file in the directory where you start"<<endl
<< " the node. "<< endl
<< " Ex: Ndb.cfg" << endl
- << " | nodeid=11;host=localhost:2200"<<endl<<endl;
+ << " | host=localhost:"<<NDB_BASE_PORT<<endl;
ndbout << "2. Use the environment variable NDB_CONNECTSTRING to "<<endl
<< " provide this information." <<endl
<< " Ex: " << endl
- << " >export NDB_CONNECTSTRING=\"nodeid=11;host=localhost:2200\""
+ << " >export NDB_CONNECTSTRING=\"host=localhost:"<<NDB_BASE_PORT<<"\""
<<endl<<endl;
}
-char *nodeIdTokens[] = {
+const char *nodeIdTokens[] = {
"OwnProcessId %i",
"nodeid=%i",
0
};
-char *hostNameTokens[] = {
+const char *hostNameTokens[] = {
"host://%[^:]:%i",
"host=%[^:]:%i",
"%[^:]:%i",
@@ -167,7 +144,7 @@ char *hostNameTokens[] = {
0
};
-char *fileNameTokens[] = {
+const char *fileNameTokens[] = {
"file://%s",
"file=%s",
0
@@ -183,15 +160,15 @@ LocalConfig::parseNodeId(const char * buf){
bool
LocalConfig::parseHostName(const char * buf){
- char tempString[100];
+ char tempString[1024];
int port;
for(int i = 0; hostNameTokens[i] != 0; i++) {
if (sscanf(buf, hostNameTokens[i], tempString, &port) == 2) {
- MgmtSrvrId* mgmtSrvrId = new MgmtSrvrId();
- mgmtSrvrId->type = MgmId_TCP;
- mgmtSrvrId->data.tcp.remoteHost = strdup(tempString);
- mgmtSrvrId->data.tcp.port = port;
- add(mgmtSrvrId);
+ MgmtSrvrId mgmtSrvrId;
+ mgmtSrvrId.type = MgmId_TCP;
+ mgmtSrvrId.name.assign(tempString);
+ mgmtSrvrId.port = port;
+ ids.push_back(mgmtSrvrId);
return true;
}
}
@@ -200,13 +177,13 @@ LocalConfig::parseHostName(const char * buf){
bool
LocalConfig::parseFileName(const char * buf){
- char tempString[100];
+ char tempString[1024];
for(int i = 0; fileNameTokens[i] != 0; i++) {
if (sscanf(buf, fileNameTokens[i], tempString) == 1) {
- MgmtSrvrId* mgmtSrvrId = new MgmtSrvrId();
- mgmtSrvrId->type = MgmId_File;
- mgmtSrvrId->data.file.filename = strdup(tempString);
- add(mgmtSrvrId);
+ MgmtSrvrId mgmtSrvrId;
+ mgmtSrvrId.type = MgmId_File;
+ mgmtSrvrId.name.assign(tempString);
+ ids.push_back(mgmtSrvrId);
return true;
}
}
@@ -214,17 +191,15 @@ LocalConfig::parseFileName(const char * buf){
}
bool
-LocalConfig::parseString(const char * connectString, bool onlyNodeId, char *line){
- bool return_value = true;
-
+LocalConfig::parseString(const char * connectString, char *line){
char * for_strtok;
char * copy = strdup(connectString);
+ NdbAutoPtr<char> tmp_aptr(copy);
bool b_nodeId = false;
bool found_other = false;
- for (char *tok = strtok_r(copy,";",&for_strtok);
- tok != 0 && !(onlyNodeId && b_nodeId);
+ for (char *tok = strtok_r(copy,";",&for_strtok); tok != 0;
tok = strtok_r(NULL, ";", &for_strtok)) {
if (tok[0] == '#') continue;
@@ -232,28 +207,27 @@ LocalConfig::parseString(const char * connectString, bool onlyNodeId, char *line
if (!b_nodeId) // only one nodeid definition allowed
if (b_nodeId = parseNodeId(tok))
continue;
- if (onlyNodeId)
- continue;
if (found_other = parseHostName(tok))
continue;
if (found_other = parseFileName(tok))
continue;
- snprintf(line, 150, "Unexpected entry: \"%s\"", tok);
- return_value = false;
- break;
+ if (line)
+ snprintf(line, 150, "Unexpected entry: \"%s\"", tok);
+ return false;
}
- if (return_value && !onlyNodeId && !found_other) {
- return_value = false;
- snprintf(line, 150, "Missing host/file name extry in \"%s\"", connectString);
+ if (!found_other) {
+ if (line)
+ snprintf(line, 150, "Missing host/file name extry in \"%s\"",
+ connectString);
+ return false;
}
- free(copy);
- return return_value;
+ return true;
}
-bool LocalConfig::readFile(const char * filename, bool &fopenError, bool onlyNodeId)
+bool LocalConfig::readFile(const char * filename, bool &fopenError)
{
char line[150], line2[150];
@@ -284,7 +258,7 @@ bool LocalConfig::readFile(const char * filename, bool &fopenError, bool onlyNod
strcat(theString, line);
}
- bool return_value = parseString(theString, onlyNodeId, line);
+ bool return_value = parseString(theString, line);
if (!return_value) {
snprintf(line2, 150, "Reading %s: %s", filename, line);
@@ -297,12 +271,14 @@ bool LocalConfig::readFile(const char * filename, bool &fopenError, bool onlyNod
}
bool
-LocalConfig::readConnectString(const char * connectString, bool onlyNodeId){
+LocalConfig::readConnectString(const char * connectString){
char line[150], line2[150];
- bool return_value = parseString(connectString, onlyNodeId, line);
+ bool return_value = parseString(connectString, line);
if (!return_value) {
snprintf(line2, 150, "Reading NDB_CONNECTSTRING \"%s\": %s", connectString, line);
setError(0,line2);
}
return return_value;
}
+
+template class Vector<MgmtSrvrId>;
diff --git a/ndb/src/common/mgmcommon/NdbConfig.c b/ndb/src/common/mgmcommon/NdbConfig.c
index 827ef34a840..6b609b22fa4 100644
--- a/ndb/src/common/mgmcommon/NdbConfig.c
+++ b/ndb/src/common/mgmcommon/NdbConfig.c
@@ -18,43 +18,93 @@
#include <NdbConfig.h>
#include <NdbEnv.h>
-const char*
-NdbConfig_HomePath(char* buf, int buflen){
- const char* p;
- p = NdbEnv_GetEnv("NDB_HOME", buf, buflen);
- if (p == NULL){
- strlcpy(buf, "", buflen);
- p = buf;
- } else {
- const int len = strlen(buf);
- if(len != 0 && buf[len-1] != '/'){
- buf[len] = '/';
- buf[len+1] = 0;
- }
- }
- return p;
-}
-
-const char*
-NdbConfig_NdbCfgName(char* buf, int buflen, int with_ndb_home){
- if (with_ndb_home)
- NdbConfig_HomePath(buf, buflen);
+static char*
+NdbConfig_AllocHomePath(int _len)
+{
+ const char *path= NdbEnv_GetEnv("NDB_HOME", 0, 0);
+ int len= _len;
+ int path_len= 0;
+ char *buf;
+
+ if (path)
+ path_len= strlen(path);
+
+ len+= path_len;
+ buf= malloc(len);
+ if (path_len > 0)
+ snprintf(buf, len, "%s%s", path, DIR_SEPARATOR);
else
- buf[0] = 0;
- strlcat(buf, "Ndb.cfg", buflen);
+ buf[0]= 0;
+
+ return buf;
+}
+
+char*
+NdbConfig_NdbCfgName(int with_ndb_home){
+ char *buf;
+ int len= 0;
+
+ if (with_ndb_home) {
+ buf= NdbConfig_AllocHomePath(128);
+ len= strlen(buf);
+ } else
+ buf= malloc(128);
+ snprintf(buf+len, 128, "Ndb.cfg");
+ return buf;
+}
+
+char*
+NdbConfig_ErrorFileName(int node_id){
+ char *buf= NdbConfig_AllocHomePath(128);
+ int len= strlen(buf);
+ snprintf(buf+len, 128, "ndb_%u_error.log", node_id);
+ return buf;
+}
+
+char*
+NdbConfig_ClusterLogFileName(int node_id){
+ char *buf= NdbConfig_AllocHomePath(128);
+ int len= strlen(buf);
+ snprintf(buf+len, 128, "ndb_%u_cluster.log", node_id);
+ return buf;
+}
+
+char*
+NdbConfig_SignalLogFileName(int node_id){
+ char *buf= NdbConfig_AllocHomePath(128);
+ int len= strlen(buf);
+ snprintf(buf+len, 128, "ndb_%u_signal.log", node_id);
+ return buf;
+}
+
+char*
+NdbConfig_TraceFileName(int node_id, int file_no){
+ char *buf= NdbConfig_AllocHomePath(128);
+ int len= strlen(buf);
+ snprintf(buf+len, 128, "ndb_%u_trace.log.%u", node_id, file_no);
+ return buf;
+}
+
+char*
+NdbConfig_NextTraceFileName(int node_id){
+ char *buf= NdbConfig_AllocHomePath(128);
+ int len= strlen(buf);
+ snprintf(buf+len, 128, "ndb_%u_trace.log.next", node_id);
return buf;
}
-const char*
-NdbConfig_ErrorFileName(char* buf, int buflen){
- NdbConfig_HomePath(buf, buflen);
- strlcat(buf, "error.log", buflen);
+char*
+NdbConfig_PidFileName(int node_id){
+ char *buf= NdbConfig_AllocHomePath(128);
+ int len= strlen(buf);
+ snprintf(buf+len, 128, "ndb_%u.pid", node_id);
return buf;
}
-const char*
-NdbConfig_ClusterLogFileName(char* buf, int buflen){
- NdbConfig_HomePath(buf, buflen);
- strlcat(buf, "cluster.log", buflen);
+char*
+NdbConfig_StdoutFileName(int node_id){
+ char *buf= NdbConfig_AllocHomePath(128);
+ int len= strlen(buf);
+ snprintf(buf+len, 128, "ndb_%u_out.log", node_id);
return buf;
}
diff --git a/ndb/src/common/portlib/Makefile.am b/ndb/src/common/portlib/Makefile.am
index e6ecb30fe04..6f3a3fe01a9 100644
--- a/ndb/src/common/portlib/Makefile.am
+++ b/ndb/src/common/portlib/Makefile.am
@@ -4,7 +4,7 @@ noinst_LTLIBRARIES = libportlib.la
libportlib_la_SOURCES = \
NdbCondition.c NdbMutex.c NdbSleep.c NdbTick.c \
- NdbEnv.c NdbThread.c NdbHost.c NdbTCP.c \
+ NdbEnv.c NdbThread.c NdbHost.c NdbTCP.cpp \
NdbDaemon.c NdbMem.c
include $(top_srcdir)/ndb/config/common.mk.am
diff --git a/ndb/src/common/portlib/NdbTCP.c b/ndb/src/common/portlib/NdbTCP.cpp
index 287dc6c2ecd..4bf4936aa30 100644
--- a/ndb/src/common/portlib/NdbTCP.c
+++ b/ndb/src/common/portlib/NdbTCP.cpp
@@ -16,14 +16,15 @@
#include <NdbMutex.h>
-#include "NdbTCP.h"
+#include <NdbTCP.h>
-#ifdef NDB_WIN32
+#if defined NDB_WIN32 || defined SCO
static NdbMutex & LOCK_gethostbyname = * NdbMutex_Create();
#else
static NdbMutex LOCK_gethostbyname = NDB_MUTEX_INITIALIZER;
#endif
+extern "C"
int
Ndb_getInAddr(struct in_addr * dst, const char *address) {
struct hostent * hostPtr;
diff --git a/ndb/src/common/transporter/Packer.cpp b/ndb/src/common/transporter/Packer.cpp
index fa72af12dac..645517a4b1a 100644
--- a/ndb/src/common/transporter/Packer.cpp
+++ b/ndb/src/common/transporter/Packer.cpp
@@ -391,6 +391,7 @@ Packer::pack(Uint32 * insertPtr,
const SignalHeader * header,
const Uint32 * theData,
const LinearSectionPtr ptr[3]) const {
+ Uint32 i;
Uint32 dataLen32 = header->theLength;
Uint32 no_segs = header->m_noOfSections;
@@ -400,7 +401,7 @@ Packer::pack(Uint32 * insertPtr,
checksumUsed + signalIdUsed + (sizeof(Protocol6)/4);
- for(Uint32 i = 0; i<no_segs; i++){
+ for(i = 0; i<no_segs; i++){
len32 += ptr[i].sz;
}
@@ -429,12 +430,12 @@ Packer::pack(Uint32 * insertPtr,
memcpy(tmpInserPtr, theData, 4 * dataLen32);
tmpInserPtr += dataLen32;
- for(Uint32 i = 0; i<no_segs; i++){
+ for(i = 0; i<no_segs; i++){
tmpInserPtr[i] = ptr[i].sz;
}
tmpInserPtr += no_segs;
- for(Uint32 i = 0; i<no_segs; i++){
+ for(i = 0; i<no_segs; i++){
import(tmpInserPtr, ptr[i]);
}
@@ -450,6 +451,7 @@ Packer::pack(Uint32 * insertPtr,
const Uint32 * theData,
class SectionSegmentPool & thePool,
const SegmentedSectionPtr ptr[3]) const {
+ Uint32 i;
Uint32 dataLen32 = header->theLength;
Uint32 no_segs = header->m_noOfSections;
@@ -458,7 +460,7 @@ Packer::pack(Uint32 * insertPtr,
dataLen32 + no_segs +
checksumUsed + signalIdUsed + (sizeof(Protocol6)/4);
- for(Uint32 i = 0; i<no_segs; i++){
+ for(i = 0; i<no_segs; i++){
len32 += ptr[i].sz;
}
@@ -487,12 +489,12 @@ Packer::pack(Uint32 * insertPtr,
memcpy(tmpInserPtr, theData, 4 * dataLen32);
tmpInserPtr += dataLen32;
- for(Uint32 i = 0; i<no_segs; i++){
+ for(i = 0; i<no_segs; i++){
tmpInserPtr[i] = ptr[i].sz;
}
tmpInserPtr += no_segs;
- for(Uint32 i = 0; i<no_segs; i++){
+ for(i = 0; i<no_segs; i++){
copy(tmpInserPtr, thePool, ptr[i]);
}
diff --git a/ndb/src/common/transporter/SHM_Transporter.cpp b/ndb/src/common/transporter/SHM_Transporter.cpp
index 7c673f93c22..aa6b650afa8 100644
--- a/ndb/src/common/transporter/SHM_Transporter.cpp
+++ b/ndb/src/common/transporter/SHM_Transporter.cpp
@@ -23,26 +23,22 @@
#include <NdbSleep.h>
#include <NdbOut.hpp>
-#ifndef NDB_WIN32
-#include <sys/ipc.h>
-#include <sys/shm.h>
-#endif
-
+#include <InputStream.hpp>
+#include <OutputStream.hpp>
-SHM_Transporter::SHM_Transporter(NodeId lNodeId,
+SHM_Transporter::SHM_Transporter(TransporterRegistry &t_reg,
+ const char *lHostName,
+ const char *rHostName,
+ int r_port,
+ NodeId lNodeId,
NodeId rNodeId,
- key_t _shmKey,
- Uint32 _shmSize,
bool compression,
bool checksum,
- bool signalId) :
- Transporter(lNodeId,
- rNodeId,
- 0,
- compression,
- checksum,
- signalId),
- isServer(lNodeId < rNodeId),
+ bool signalId,
+ key_t _shmKey,
+ Uint32 _shmSize) :
+ Transporter(t_reg, lHostName, rHostName, r_port, lNodeId, rNodeId,
+ 0, compression, checksum, signalId),
shmKey(_shmKey),
shmSize(_shmSize)
{
@@ -68,16 +64,6 @@ SHM_Transporter::initTransporter(){
return true;
}
-bool
-SHM_Transporter::connectImpl(Uint32 timeOutMillis){
- bool res;
- if(isServer)
- res = connectServer(timeOutMillis);
- else
- res = connectClient(timeOutMillis);
- return res;
-}
-
void
SHM_Transporter::setupBuffers(){
Uint32 sharedSize = 0;
@@ -233,3 +219,127 @@ SHM_Transporter::prepareSend(const SignalHeader * const signalHeader,
return SEND_DISCONNECTED;
}
#endif
+
+
+bool
+SHM_Transporter::connect_server_impl(NDB_SOCKET_TYPE sockfd)
+{
+ SocketOutputStream s_output(sockfd);
+ SocketInputStream s_input(sockfd);
+ char buf[256];
+
+ // Create
+ if(!_shmSegCreated){
+ if (!ndb_shm_create()) {
+ report_error(TE_SHM_UNABLE_TO_CREATE_SEGMENT);
+ NDB_CLOSE_SOCKET(sockfd);
+ return false;
+ }
+ _shmSegCreated = true;
+ }
+
+ // Attach
+ if(!_attached){
+ if (!ndb_shm_attach()) {
+ report_error(TE_SHM_UNABLE_TO_ATTACH_SEGMENT);
+ NDB_CLOSE_SOCKET(sockfd);
+ return false;
+ }
+ _attached = true;
+ }
+
+ // Send ok to client
+ s_output.println("shm server 1 ok");
+
+ // Wait for ok from client
+ if (s_input.gets(buf, 256) == 0) {
+ NDB_CLOSE_SOCKET(sockfd);
+ return false;
+ }
+
+ int r= connect_common(sockfd);
+
+ if (r) {
+ // Send ok to client
+ s_output.println("shm server 2 ok");
+ // Wait for ok from client
+ if (s_input.gets(buf, 256) == 0) {
+ NDB_CLOSE_SOCKET(sockfd);
+ return false;
+ }
+ }
+
+ NDB_CLOSE_SOCKET(sockfd);
+ return r;
+}
+
+bool
+SHM_Transporter::connect_client_impl(NDB_SOCKET_TYPE sockfd)
+{
+ SocketInputStream s_input(sockfd);
+ SocketOutputStream s_output(sockfd);
+ char buf[256];
+
+ // Wait for server to create and attach
+ if (s_input.gets(buf, 256) == 0) {
+ NDB_CLOSE_SOCKET(sockfd);
+ return false;
+ }
+
+ // Create
+ if(!_shmSegCreated){
+ if (!ndb_shm_get()) {
+ NDB_CLOSE_SOCKET(sockfd);
+ return false;
+ }
+ _shmSegCreated = true;
+ }
+
+ // Attach
+ if(!_attached){
+ if (!ndb_shm_attach()) {
+ report_error(TE_SHM_UNABLE_TO_ATTACH_SEGMENT);
+ NDB_CLOSE_SOCKET(sockfd);
+ return false;
+ }
+ _attached = true;
+ }
+
+ // Send ok to server
+ s_output.println("shm client 1 ok");
+
+ int r= connect_common(sockfd);
+
+ if (r) {
+ // Wait for ok from server
+ if (s_input.gets(buf, 256) == 0) {
+ NDB_CLOSE_SOCKET(sockfd);
+ return false;
+ }
+ // Send ok to server
+ s_output.println("shm client 2 ok");
+ }
+
+ NDB_CLOSE_SOCKET(sockfd);
+ return r;
+}
+
+bool
+SHM_Transporter::connect_common(NDB_SOCKET_TYPE sockfd)
+{
+ if (!checkConnected())
+ return false;
+
+ if(!setupBuffersDone) {
+ setupBuffers();
+ setupBuffersDone=true;
+ }
+
+ if(setupBuffersDone) {
+ NdbSleep_MilliSleep(m_timeOutMillis);
+ if(*serverStatusFlag == 1 && *clientStatusFlag == 1)
+ return true;
+ }
+
+ return false;
+}
diff --git a/ndb/src/common/transporter/SHM_Transporter.hpp b/ndb/src/common/transporter/SHM_Transporter.hpp
index da4566515e3..be54d0daa2a 100644
--- a/ndb/src/common/transporter/SHM_Transporter.hpp
+++ b/ndb/src/common/transporter/SHM_Transporter.hpp
@@ -32,13 +32,17 @@ typedef Uint32 key_t;
class SHM_Transporter : public Transporter {
friend class TransporterRegistry;
public:
- SHM_Transporter(NodeId lNodeId,
+ SHM_Transporter(TransporterRegistry &,
+ const char *lHostName,
+ const char *rHostName,
+ int r_port,
+ NodeId lNodeId,
NodeId rNodeId,
- key_t shmKey,
- Uint32 shmSize,
bool compression,
bool checksum,
- bool signalId);
+ bool signalId,
+ key_t shmKey,
+ Uint32 shmSize);
/**
* SHM destructor
@@ -75,14 +79,6 @@ protected:
void disconnectImpl();
/**
- * Invokes the connectServer or connectClient.
- * @param timeOutMillis - the timeout the connect thread waits before
- * retrying.
- * @return True if connectImpl successful, otherwise false.
- */
- bool connectImpl(Uint32 timeOutMillis);
-
- /**
* Blocking
*
* -# Create shm segment
@@ -94,7 +90,7 @@ protected:
* i.e., both agrees that the other one has setup the segment.
* Otherwise false.
*/
- bool connectServer(Uint32 timeOutMillis);
+ virtual bool connect_server_impl(NDB_SOCKET_TYPE sockfd);
/**
* Blocking
@@ -108,8 +104,13 @@ protected:
* i.e., both agrees that the other one has setup the segment.
* Otherwise false.
*/
- bool connectClient(Uint32 timeOutMillis);
+ virtual bool connect_client_impl(NDB_SOCKET_TYPE sockfd);
+
+ bool connect_common(NDB_SOCKET_TYPE sockfd);
+ bool ndb_shm_create();
+ bool ndb_shm_get();
+ bool ndb_shm_attach();
/**
* Check if there are two processes attached to the segment (a connection)
@@ -127,7 +128,6 @@ private:
bool _shmSegCreated;
bool _attached;
- const bool isServer;
key_t shmKey;
volatile Uint32 * serverStatusFlag;
volatile Uint32 * clientStatusFlag;
diff --git a/ndb/src/common/transporter/SHM_Transporter.unix.cpp b/ndb/src/common/transporter/SHM_Transporter.unix.cpp
index afbf124432e..28882324fc0 100644
--- a/ndb/src/common/transporter/SHM_Transporter.unix.cpp
+++ b/ndb/src/common/transporter/SHM_Transporter.unix.cpp
@@ -26,114 +26,37 @@
#include <sys/ipc.h>
#include <sys/shm.h>
-
-
bool
-SHM_Transporter::connectServer(Uint32 timeOutMillis){
- if(!_shmSegCreated){
- shmId = shmget(shmKey, shmSize, IPC_CREAT | 960);
- if(shmId == -1){
- perror("shmget: ");
- reportThreadError(remoteNodeId, TE_SHM_UNABLE_TO_CREATE_SEGMENT);
- NdbSleep_MilliSleep(timeOutMillis);
- return false;
- }
- _shmSegCreated = true;
- }
-
- if(!_attached){
- shmBuf = (char *)shmat(shmId, 0, 0);
- if(shmBuf == 0){
- perror("shmat: ");
- reportThreadError(remoteNodeId, TE_SHM_UNABLE_TO_ATTACH_SEGMENT);
- NdbSleep_MilliSleep(timeOutMillis);
- return false;
- }
- _attached = true;
- }
-
- struct shmid_ds info;
- const int res = shmctl(shmId, IPC_STAT, &info);
- if(res == -1){
- perror("shmctl: ");
- reportThreadError(remoteNodeId, TE_SHM_IPC_STAT);
- NdbSleep_MilliSleep(timeOutMillis);
+SHM_Transporter::ndb_shm_create()
+{
+ shmId = shmget(shmKey, shmSize, IPC_CREAT | 960);
+ if(shmId == -1) {
+ perror("shmget: ");
return false;
}
-
- if(info.shm_nattch == 2 && !setupBuffersDone) {
- setupBuffers();
- setupBuffersDone=true;
- }
-
- if(setupBuffersDone) {
- NdbSleep_MilliSleep(timeOutMillis);
- if(*serverStatusFlag==1 && *clientStatusFlag==1)
- return true;
- }
-
-
- if(info.shm_nattch > 2){
- reportThreadError(remoteNodeId, TE_SHM_DISCONNECT);
- NdbSleep_MilliSleep(timeOutMillis);
- return false;
- }
-
- NdbSleep_MilliSleep(timeOutMillis);
- return false;
+ return true;
}
bool
-SHM_Transporter::connectClient(Uint32 timeOutMillis){
- if(!_shmSegCreated){
-
- shmId = shmget(shmKey, shmSize, 0);
- if(shmId == -1){
- NdbSleep_MilliSleep(timeOutMillis);
- return false;
- }
- _shmSegCreated = true;
- }
-
- if(!_attached){
- shmBuf = (char *)shmat(shmId, 0, 0);
- if(shmBuf == 0){
- reportThreadError(remoteNodeId, TE_SHM_UNABLE_TO_ATTACH_SEGMENT);
- NdbSleep_MilliSleep(timeOutMillis);
- return false;
- }
- _attached = true;
- }
-
- struct shmid_ds info;
-
- const int res = shmctl(shmId, IPC_STAT, &info);
- if(res == -1){
- reportThreadError(remoteNodeId, TE_SHM_IPC_STAT);
- NdbSleep_MilliSleep(timeOutMillis);
+SHM_Transporter::ndb_shm_get()
+{
+ shmId = shmget(shmKey, shmSize, 0);
+ if(shmId == -1) {
+ perror("shmget: ");
return false;
}
-
-
- if(info.shm_nattch == 2 && !setupBuffersDone) {
- setupBuffers();
- setupBuffersDone=true;
- }
-
- if(setupBuffersDone) {
- NdbSleep_MilliSleep(timeOutMillis);
- if(*serverStatusFlag==1 && *clientStatusFlag==1)
- return true;
- }
+ return true;
+}
- if(info.shm_nattch > 2){
- reportThreadError(remoteNodeId, TE_SHM_DISCONNECT);
- NdbSleep_MilliSleep(timeOutMillis);
+bool
+SHM_Transporter::ndb_shm_attach()
+{
+ shmBuf = (char *)shmat(shmId, 0, 0);
+ if(shmBuf == 0) {
+ perror("shmat: ");
return false;
}
-
- NdbSleep_MilliSleep(timeOutMillis);
- return false;
+ return true;
}
bool
@@ -141,12 +64,12 @@ SHM_Transporter::checkConnected(){
struct shmid_ds info;
const int res = shmctl(shmId, IPC_STAT, &info);
if(res == -1){
- reportError(callbackObj, remoteNodeId, TE_SHM_IPC_STAT);
+ report_error(TE_SHM_IPC_STAT);
return false;
}
if(info.shm_nattch != 2){
- reportError(callbackObj, remoteNodeId, TE_SHM_DISCONNECT);
+ report_error(TE_SHM_DISCONNECT);
return false;
}
return true;
@@ -168,11 +91,10 @@ SHM_Transporter::disconnectImpl(){
if(isServer && _shmSegCreated){
const int res = shmctl(shmId, IPC_RMID, 0);
if(res == -1){
- reportError(callbackObj, remoteNodeId, TE_SHM_UNABLE_TO_REMOVE_SEGMENT);
+ report_error(TE_SHM_UNABLE_TO_REMOVE_SEGMENT);
return;
}
_shmSegCreated = false;
}
setupBuffersDone=false;
}
-
diff --git a/ndb/src/common/transporter/TCP_Transporter.cpp b/ndb/src/common/transporter/TCP_Transporter.cpp
index 99b6a137797..8833b51e236 100644
--- a/ndb/src/common/transporter/TCP_Transporter.cpp
+++ b/ndb/src/common/transporter/TCP_Transporter.cpp
@@ -63,27 +63,23 @@ ndbstrerror::~ndbstrerror(void)
#define ndbstrerror strerror
#endif
-TCP_Transporter::TCP_Transporter(int sendBufSize, int maxRecvSize,
- int portNo,
- const char *rHostName,
+TCP_Transporter::TCP_Transporter(TransporterRegistry &t_reg,
+ int sendBufSize, int maxRecvSize,
const char *lHostName,
- NodeId rNodeId, NodeId lNodeId,
+ const char *rHostName,
+ int r_port,
+ NodeId lNodeId,
+ NodeId rNodeId,
int byte_order,
bool compr, bool chksm, bool signalId,
Uint32 _reportFreq) :
- Transporter(lNodeId, rNodeId, byte_order, compr, chksm, signalId),
- m_sendBuffer(sendBufSize),
- isServer(lNodeId < rNodeId),
- port(portNo)
+ Transporter(t_reg, lHostName, rHostName, r_port, lNodeId, rNodeId,
+ byte_order, compr, chksm, signalId),
+ m_sendBuffer(sendBufSize)
{
maxReceiveSize = maxRecvSize;
- strncpy(remoteHostName, rHostName, sizeof(remoteHostName));
-
// Initialize member variables
- Ndb_getInAddr(&remoteHostAddress, rHostName);
-
- Ndb_getInAddr(&localHostAddress, lHostName);
theSocket = NDB_INVALID_SOCKET;
sendCount = receiveCount = 0;
@@ -108,6 +104,24 @@ TCP_Transporter::~TCP_Transporter() {
receiveBuffer.destroy();
}
+bool TCP_Transporter::connect_server_impl(NDB_SOCKET_TYPE sockfd)
+{
+ return connect_common(sockfd);
+}
+
+bool TCP_Transporter::connect_client_impl(NDB_SOCKET_TYPE sockfd)
+{
+ return connect_common(sockfd);
+}
+
+bool TCP_Transporter::connect_common(NDB_SOCKET_TYPE sockfd)
+{
+ theSocket = sockfd;
+ setSocketOptions();
+ setSocketNonBlocking(theSocket);
+ return true;
+}
+
bool
TCP_Transporter::initTransporter() {
@@ -316,7 +330,7 @@ TCP_Transporter::doSend() {
sendCount ++;
sendSize += nBytesSent;
if(sendCount == reportFreq){
- reportSendLen(callbackObj,remoteNodeId, sendCount, sendSize);
+ reportSendLen(get_callback_obj(), remoteNodeId, sendCount, sendSize);
sendCount = 0;
sendSize = 0;
}
@@ -331,7 +345,7 @@ TCP_Transporter::doSend() {
#endif
if(DISCONNECT_ERRNO(InetErrno, nBytesSent)){
doDisconnect();
- reportDisconnect(callbackObj, remoteNodeId, InetErrno);
+ report_disconnect(InetErrno);
}
return false;
@@ -361,14 +375,15 @@ TCP_Transporter::doReceive() {
#endif
ndbout_c("receiveBuffer.sizeOfData(%d) > receiveBuffer.sizeOfBuffer(%d)",
receiveBuffer.sizeOfData, receiveBuffer.sizeOfBuffer);
- reportError(callbackObj, remoteNodeId, TE_INVALID_MESSAGE_LENGTH);
+ report_error(TE_INVALID_MESSAGE_LENGTH);
return 0;
}
receiveCount ++;
receiveSize += nBytesRead;
+
if(receiveCount == reportFreq){
- reportReceiveLen(callbackObj, remoteNodeId, receiveCount, receiveSize);
+ reportReceiveLen(get_callback_obj(), remoteNodeId, receiveCount, receiveSize);
receiveCount = 0;
receiveSize = 0;
}
@@ -384,60 +399,17 @@ TCP_Transporter::doReceive() {
if(DISCONNECT_ERRNO(InetErrno, nBytesRead)){
// The remote node has closed down
doDisconnect();
- reportDisconnect(callbackObj, remoteNodeId,InetErrno);
+ report_disconnect(InetErrno);
}
}
return nBytesRead;
}
-bool
-TCP_Transporter::connectImpl(Uint32 timeOutMillis){
- struct timeval timeout = {0, 0};
- timeout.tv_sec = timeOutMillis / 1000;
- timeout.tv_usec = (timeOutMillis % 1000)*1000;
-
- bool retVal = false;
-
- if(isServer){
- if(theSocket == NDB_INVALID_SOCKET){
- startTCPServer();
- }
- if(theSocket == NDB_INVALID_SOCKET)
- {
- NdbSleep_MilliSleep(timeOutMillis);
- return false;
- }
- retVal = acceptClient(&timeout);
- } else {
- // Is client
- retVal = connectClient(&timeout);
- }
-
- if(!retVal) {
- NdbSleep_MilliSleep(timeOutMillis);
- return false;
- }
-
-#if defined NDB_OSE || defined NDB_SOFTOSE
- if(setsockopt(theSocket, SOL_SOCKET, SO_OSEOWNER,
- &theReceiverPid, sizeof(PROCESS)) != 0){
-
- ndbout << "Failed to transfer ownership of socket" << endl;
- NDB_CLOSE_SOCKET(theSocket);
- theSocket = -1;
- return false;
- }
-#endif
-
- return true;
-}
-
-
void
-TCP_Transporter::disconnectImpl() {
+TCP_Transporter::disconnectImpl() {
if(theSocket != NDB_INVALID_SOCKET){
if(NDB_CLOSE_SOCKET(theSocket) < 0){
- reportError(callbackObj, remoteNodeId, TE_ERROR_CLOSING_SOCKET);
+ report_error(TE_ERROR_CLOSING_SOCKET);
}
}
@@ -447,155 +419,3 @@ TCP_Transporter::disconnectImpl() {
theSocket = NDB_INVALID_SOCKET;
}
-
-bool
-TCP_Transporter::startTCPServer() {
-
- int bindResult, listenResult;
-
- // The server variable is the remote server when we are a client
- // htonl and htons returns the parameter in network byte order
- // INADDR_ANY tells the OS kernel to choose the IP address
- struct sockaddr_in server;
- memset((void*)&server, 0, sizeof(server));
- server.sin_family = AF_INET;
- server.sin_addr.s_addr = localHostAddress.s_addr;
- server.sin_port = htons(port);
-
- if (theSocket != NDB_INVALID_SOCKET) {
- return true; // Server socket is already initialized
- }
-
- // Create the socket
- theSocket = socket(AF_INET, SOCK_STREAM, 0);
- if (theSocket == NDB_INVALID_SOCKET) {
- reportThreadError(remoteNodeId, TE_COULD_NOT_CREATE_SOCKET);
- return false;
- }
-
- // Set the socket reuse addr to true, so we are sure we can bind the
- // socket
- int reuseAddr = 1;
- setsockopt(theSocket, SOL_SOCKET, SO_REUSEADDR,
- (char*)&reuseAddr, sizeof(reuseAddr));
-
- // Set the TCP_NODELAY option so also small packets are sent
- // as soon as possible
- int nodelay = 1;
- setsockopt(theSocket, IPPROTO_TCP, TCP_NODELAY,
- (char*)&nodelay, sizeof(nodelay));
-
- // Bind the socket
- bindResult = bind(theSocket, (struct sockaddr *) &server,
- sizeof(server));
- if (bindResult < 0) {
- reportThreadError(remoteNodeId, TE_COULD_NOT_BIND_SOCKET);
- NDB_CLOSE_SOCKET(theSocket);
- theSocket = NDB_INVALID_SOCKET;
- return false;
- }
-
- // Perform listen.
- listenResult = listen(theSocket, 1);
- if (listenResult == 1) {
- reportThreadError(remoteNodeId, TE_LISTEN_FAILED);
- NDB_CLOSE_SOCKET(theSocket);
- theSocket = NDB_INVALID_SOCKET;
- return false;
- }
-
- return true;
-}
-
-
-bool
-TCP_Transporter::acceptClient (struct timeval * timeout){
-
- struct sockaddr_in clientAddress;
-
- fd_set readset;
- FD_ZERO(&readset);
- FD_SET(theSocket, &readset);
- const int res = select(theSocket + 1, &readset, 0, 0, timeout);
- if(res == 0)
- return false;
-
- if(res < 0){
- reportThreadError(remoteNodeId, TE_ERROR_IN_SELECT_BEFORE_ACCEPT);
- return false;
- }
-
- NDB_SOCKLEN_T clientAddressLen = sizeof(clientAddress);
- const NDB_SOCKET_TYPE clientSocket = accept(theSocket,
- (struct sockaddr*)&clientAddress,
- &clientAddressLen);
- if (clientSocket == NDB_INVALID_SOCKET) {
- reportThreadError(remoteNodeId, TE_ACCEPT_RETURN_ERROR);
- return false;
- }
-
- if (clientAddress.sin_addr.s_addr != remoteHostAddress.s_addr) {
- ndbout_c("Wrong client connecting!");
- ndbout_c("connecting address: %s", inet_ntoa(clientAddress.sin_addr));
- ndbout_c("expecting address: %s", inet_ntoa(remoteHostAddress));
- // The newly connected host is not the remote host
- // we wanted to connect to. Disconnect it.
- // XXX This is not valid. We cannot disconnect it.
- NDB_CLOSE_SOCKET(clientSocket);
- return false;
- } else {
- NDB_CLOSE_SOCKET(theSocket);
- theSocket = clientSocket;
- setSocketOptions();
- setSocketNonBlocking(theSocket);
- return true;
- }
-}
-
-bool
-TCP_Transporter::connectClient (struct timeval * timeout){
-
- // Create the socket
- theSocket = socket(AF_INET, SOCK_STREAM, 0);
- if (theSocket == NDB_INVALID_SOCKET) {
- reportThreadError(remoteNodeId, TE_COULD_NOT_CREATE_SOCKET);
- return false;
- }
-
- struct sockaddr_in server;
- memset((void*)&server, 0, sizeof(server));
- server.sin_family = AF_INET;
- server.sin_addr = remoteHostAddress;
- server.sin_port = htons(port);
-
- struct sockaddr_in client;
- memset((void*)&client, 0, sizeof(client));
- client.sin_family = AF_INET;
- client.sin_addr = localHostAddress;
- client.sin_port = 0; // Any port
-
- // Bind the socket
- const int bindResult = bind(theSocket, (struct sockaddr *) &client,
- sizeof(client));
- if (bindResult < 0) {
- reportThreadError(remoteNodeId, TE_COULD_NOT_BIND_SOCKET);
- NDB_CLOSE_SOCKET(theSocket);
- theSocket = NDB_INVALID_SOCKET;
- return false;
- }
-
- const int connectRes = ::connect(theSocket, (struct sockaddr *) &server,
- sizeof(server));
- if(connectRes == 0){
- setSocketOptions();
- setSocketNonBlocking(theSocket);
- return true;
- }
-
- NDB_CLOSE_SOCKET(theSocket);
- theSocket = NDB_INVALID_SOCKET;
- return false;
-}
-
-
-
diff --git a/ndb/src/common/transporter/TCP_Transporter.hpp b/ndb/src/common/transporter/TCP_Transporter.hpp
index 30b730a5b1c..958cfde03a1 100644
--- a/ndb/src/common/transporter/TCP_Transporter.hpp
+++ b/ndb/src/common/transporter/TCP_Transporter.hpp
@@ -14,24 +14,8 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-//****************************************************************************
-//
-// AUTHOR
-// Åsa Fransson
-//
-// NAME
-// TCP_Transporter
-//
-// DESCRIPTION
-// A TCP_Transporter instance is created when TCP/IP-communication
-// shall be used (user specified). It handles connect, disconnect,
-// send and receive.
-//
-//
-//
-//***************************************************************************/
-#ifndef TCP_Transporter_H
-#define TCP_Transporter_H
+#ifndef TCP_TRANSPORTER_HPP
+#define TCP_TRANSPORTER_HPP
#include "Transporter.hpp"
#include "SendBuffer.hpp"
@@ -61,11 +45,13 @@ class TCP_Transporter : public Transporter {
friend class TransporterRegistry;
private:
// Initialize member variables
- TCP_Transporter(int sendBufferSize, int maxReceiveSize,
- int port,
- const char *rHostName,
+ TCP_Transporter(TransporterRegistry&,
+ int sendBufferSize, int maxReceiveSize,
const char *lHostName,
- NodeId rHostId, NodeId lHostId,
+ const char *rHostName,
+ int r_port,
+ NodeId lHostId,
+ NodeId rHostId,
int byteorder,
bool compression, bool checksum, bool signalId,
Uint32 reportFreq = 4096);
@@ -121,12 +107,14 @@ protected:
* A client connects to the remote server
* A server accepts any new connections
*/
- bool connectImpl(Uint32 timeOutMillis);
+ virtual bool connect_server_impl(NDB_SOCKET_TYPE sockfd);
+ virtual bool connect_client_impl(NDB_SOCKET_TYPE sockfd);
+ bool connect_common(NDB_SOCKET_TYPE sockfd);
/**
* Disconnects a TCP/IP node. Empty send and receivebuffer.
*/
- void disconnectImpl();
+ virtual void disconnectImpl();
private:
/**
@@ -134,22 +122,12 @@ private:
*/
SendBuffer m_sendBuffer;
- const bool isServer;
- const unsigned int port;
-
// Sending/Receiving socket used by both client and server
NDB_SOCKET_TYPE theSocket;
Uint32 maxReceiveSize;
/**
- * Remote host name/and address
- */
- char remoteHostName[256];
- struct in_addr remoteHostAddress;
- struct in_addr localHostAddress;
-
- /**
* Socket options
*/
int sockOptRcvBufSize;
@@ -164,43 +142,6 @@ private:
bool sendIsPossible(struct timeval * timeout);
/**
- * startTCPServer - None blocking
- *
- * create a server socket
- * bind
- * listen
- *
- * Note: Does not call accept
- */
- bool startTCPServer();
-
- /**
- * acceptClient - Blocking
- *
- * Accept a connection
- * checks if "right" client has connected
- * if so
- * close server socket
- * else
- * close newly created socket and goto begin
- */
- bool acceptClient(struct timeval * timeout);
-
- /**
- * Creates a client socket
- *
- * Note does not call connect
- */
- bool createClientSocket();
-
- /**
- * connectClient - Blocking
- *
- * connects to remote host
- */
- bool connectClient(struct timeval * timeout);
-
- /**
* Statistics
*/
Uint32 reportFreq;
diff --git a/ndb/src/common/transporter/Transporter.cpp b/ndb/src/common/transporter/Transporter.cpp
index 5ca523d5185..7a469252c00 100644
--- a/ndb/src/common/transporter/Transporter.cpp
+++ b/ndb/src/common/transporter/Transporter.cpp
@@ -15,132 +15,118 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+#include <TransporterRegistry.hpp>
+#include <TransporterCallback.hpp>
#include "Transporter.hpp"
#include "TransporterInternalDefinitions.hpp"
#include <NdbSleep.h>
-
-Transporter::Transporter(NodeId lNodeId, NodeId rNodeId,
+#include <SocketAuthenticator.hpp>
+#include <InputStream.hpp>
+#include <OutputStream.hpp>
+
+Transporter::Transporter(TransporterRegistry &t_reg,
+ const char *lHostName,
+ const char *rHostName,
+ int r_port,
+ NodeId lNodeId,
+ NodeId rNodeId,
int _byteorder,
bool _compression, bool _checksum, bool _signalId)
- : localNodeId(lNodeId), remoteNodeId(rNodeId),
- m_packer(_signalId, _checksum)
+ : m_r_port(r_port), localNodeId(lNodeId), remoteNodeId(rNodeId),
+ isServer(lNodeId < rNodeId),
+ m_packer(_signalId, _checksum),
+ m_transporter_registry(t_reg)
{
+ if (rHostName && strlen(rHostName) > 0){
+ strncpy(remoteHostName, rHostName, sizeof(remoteHostName));
+ Ndb_getInAddr(&remoteHostAddress, rHostName);
+ }
+ else
+ {
+ if (!isServer) {
+ ndbout << "Unable to setup transporter. Node " << rNodeId
+ << " must have hostname. Update configuration." << endl;
+ exit(-1);
+ }
+ remoteHostName[0]= 0;
+ }
+ strncpy(localHostName, lHostName, sizeof(localHostName));
+
+ if (strlen(lHostName) > 0)
+ Ndb_getInAddr(&localHostAddress, lHostName);
+
byteOrder = _byteorder;
compressionUsed = _compression;
checksumUsed = _checksum;
signalIdUsed = _signalId;
- _threadError = TE_NO_ERROR;
+ m_connected = false;
+ m_timeOutMillis = 1000;
- _connecting = false;
- _disconnecting = false;
- _connected = false;
- _timeOutMillis = 1000;
- theThreadPtr = NULL;
- theMutexPtr = NdbMutex_Create();
+ if (isServer)
+ m_socket_client= 0;
+ else
+ m_socket_client= new SocketClient(remoteHostName, r_port,
+ new SocketAuthSimple("ndbd", "ndbd passwd"));
}
Transporter::~Transporter(){
- NdbMutex_Destroy(theMutexPtr);
-
- if(theThreadPtr != 0){
- void * retVal;
- NdbThread_WaitFor(theThreadPtr, &retVal);
- NdbThread_Destroy(&theThreadPtr);
- }
+ if (m_socket_client)
+ delete m_socket_client;
}
-extern "C"
-void *
-runConnect_C(void * me)
-{
- runConnect(me);
- NdbThread_Exit(0);
- return NULL;
-}
-
-void *
-runConnect(void * me){
- Transporter * t = (Transporter *) me;
-
- DEBUG("Connect thread to " << t->remoteNodeId << " started");
-
- while(true){
- NdbMutex_Lock(t->theMutexPtr);
- if(t->_disconnecting){
- t->_connecting = false;
- NdbMutex_Unlock(t->theMutexPtr);
- DEBUG("Connect Thread " << t->remoteNodeId << " stop due to disconnect");
- return 0;
- }
- NdbMutex_Unlock(t->theMutexPtr);
-
- bool res = t->connectImpl(t->_timeOutMillis); // 1000 ms
- DEBUG("Waiting for " << t->remoteNodeId << "...");
- if(res){
- t->_connected = true;
- t->_connecting = false;
- t->_errorCount = 0;
- t->_threadError = TE_NO_ERROR;
- DEBUG("Connect Thread " << t->remoteNodeId << " stop due to connect");
- return 0;
- }
- }
-}
-
-void
-Transporter::doConnect() {
+bool
+Transporter::connect_server(NDB_SOCKET_TYPE sockfd) {
+ if(m_connected)
+ return true; // TODO assert(0);
- NdbMutex_Lock(theMutexPtr);
- if(_connecting || _disconnecting || _connected){
- NdbMutex_Unlock(theMutexPtr);
- return;
+ bool res = connect_server_impl(sockfd);
+ if(res){
+ m_connected = true;
+ m_errorCount = 0;
}
-
- _connecting = true;
- _threadError = TE_NO_ERROR;
+ return res;
+}
- // Start thread
+bool
+Transporter::connect_client() {
+ if(m_connected)
+ return true;
+ NDB_SOCKET_TYPE sockfd = m_socket_client->connect();
- char buf[16];
- snprintf(buf, sizeof(buf), "ndb_con_%d", remoteNodeId);
-
- if(theThreadPtr != 0){
- void * retVal;
- NdbThread_WaitFor(theThreadPtr, &retVal);
- NdbThread_Destroy(&theThreadPtr);
+ if (sockfd < 0)
+ return false;
+
+ // send info about own id
+ SocketOutputStream s_output(sockfd);
+ s_output.println("%d", localNodeId);
+ // get remote id
+ int nodeId;
+ SocketInputStream s_input(sockfd);
+ char buf[256];
+ if (s_input.gets(buf, 256) == 0) {
+ NDB_CLOSE_SOCKET(sockfd);
+ return false;
}
-
- theThreadPtr = NdbThread_Create(runConnect_C,
- (void**)this,
- 32768,
- buf,
- NDB_THREAD_PRIO_LOW);
-
- NdbSleep_MilliSleep(100); // Let thread start
-
- NdbMutex_Unlock(theMutexPtr);
+ if (sscanf(buf, "%d", &nodeId) != 1) {
+ NDB_CLOSE_SOCKET(sockfd);
+ return false;
+ }
+ bool res = connect_client_impl(sockfd);
+ if(res){
+ m_connected = true;
+ m_errorCount = 0;
+ }
+ return res;
}
void
-Transporter::doDisconnect() {
-
- NdbMutex_Lock(theMutexPtr);
- _disconnecting = true;
- while(_connecting){
- DEBUG("Waiting for connect to finish...");
-
- NdbMutex_Unlock(theMutexPtr);
- NdbSleep_MilliSleep(500);
- NdbMutex_Lock(theMutexPtr);
- }
-
- _connected = false;
-
+Transporter::doDisconnect() {
+
+ if(!m_connected)
+ return; //assert(0); TODO will fail
+
+ m_connected= false;
disconnectImpl();
- _threadError = TE_NO_ERROR;
- _disconnecting = false;
-
- NdbMutex_Unlock(theMutexPtr);
}
diff --git a/ndb/src/common/transporter/Transporter.hpp b/ndb/src/common/transporter/Transporter.hpp
index 43b26d45899..9a39f8788bc 100644
--- a/ndb/src/common/transporter/Transporter.hpp
+++ b/ndb/src/common/transporter/Transporter.hpp
@@ -19,6 +19,9 @@
#include <ndb_global.h>
+#include <SocketClient.hpp>
+
+#include <TransporterRegistry.hpp>
#include <TransporterCallback.hpp>
#include "TransporterDefinitions.hpp"
#include "Packer.hpp"
@@ -40,8 +43,9 @@ public:
* None blocking
* Use isConnected() to check status
*/
- virtual void doConnect();
-
+ bool connect_client();
+ bool connect_server(NDB_SOCKET_TYPE socket);
+
/**
* Blocking
*/
@@ -60,14 +64,17 @@ public:
*/
NodeId getRemoteNodeId() const;
-
/**
- * Set callback object
+ * Local (own) Node Id
*/
- void setCallbackObject(void * callback);
+ NodeId getLocalNodeId() const;
protected:
- Transporter(NodeId lNodeId,
+ Transporter(TransporterRegistry &,
+ const char *lHostName,
+ const char *rHostName,
+ int r_port,
+ NodeId lNodeId,
NodeId rNodeId,
int byteorder,
bool compression,
@@ -78,58 +85,59 @@ protected:
* Blocking, for max timeOut milli seconds
* Returns true if connect succeded
*/
- virtual bool connectImpl(Uint32 timeOut) = 0;
+ virtual bool connect_server_impl(NDB_SOCKET_TYPE sockfd) = 0;
+ virtual bool connect_client_impl(NDB_SOCKET_TYPE sockfd) = 0;
/**
* Blocking
*/
virtual void disconnectImpl() = 0;
- const NodeId localNodeId;
+ /**
+ * Remote host name/and address
+ */
+ char remoteHostName[256];
+ char localHostName[256];
+ struct in_addr remoteHostAddress;
+ struct in_addr localHostAddress;
+
+ const unsigned int m_r_port;
+
const NodeId remoteNodeId;
+ const NodeId localNodeId;
+ const bool isServer;
+
unsigned createIndex;
int byteOrder;
bool compressionUsed;
bool checksumUsed;
bool signalIdUsed;
- Packer m_packer;
-
+ Packer m_packer;
private:
- /**
- * Thread and mutex for connect
- */
- NdbThread* theThreadPtr;
- friend void* runConnect(void * me);
+
+ SocketClient *m_socket_client;
protected:
- /**
- * Error reporting from connect thread(s)
- */
- void reportThreadError(NodeId nodeId,
- TransporterError errorCode);
Uint32 getErrorCount();
- TransporterError getThreadError();
- void resetThreadError();
- TransporterError _threadError;
- Uint32 _timeOutMillis;
- Uint32 _errorCount;
-
-protected:
- NdbMutex* theMutexPtr;
- bool _connected; // Are we connected
- bool _connecting; // Connect thread is running
- bool _disconnecting; // We are disconnecting
-
- void * callbackObj;
+ Uint32 m_errorCount;
+ Uint32 m_timeOutMillis;
+
+protected:
+ bool m_connected; // Are we connected
+
+ TransporterRegistry &m_transporter_registry;
+ void *get_callback_obj() { return m_transporter_registry.callbackObj; };
+ void report_disconnect(int err){m_transporter_registry.report_disconnect(remoteNodeId,err);};
+ void report_error(enum TransporterError err){reportError(get_callback_obj(),remoteNodeId,err);};
};
inline
bool
Transporter::isConnected() const {
- return _connected;
+ return m_connected;
}
inline
@@ -138,42 +146,17 @@ Transporter::getRemoteNodeId() const {
return remoteNodeId;
}
-inline
-void
-Transporter::reportThreadError(NodeId nodeId, TransporterError errorCode)
-{
-#if 0
- ndbout_c("Transporter::reportThreadError (NodeId: %d, Error code: %d)",
- nodeId, errorCode);
-#endif
- _threadError = errorCode;
- _errorCount++;
-}
-
inline
-TransporterError
-Transporter::getThreadError(){
- return _threadError;
+NodeId
+Transporter::getLocalNodeId() const {
+ return remoteNodeId;
}
inline
Uint32
Transporter::getErrorCount()
{
- return _errorCount;
-}
-
-inline
-void
-Transporter::resetThreadError()
-{
- _threadError = TE_NO_ERROR;
-}
-
-inline
-void
-Transporter::setCallbackObject(void * callback) {
- callbackObj = callback;
+ return m_errorCount;
}
#endif // Define of Transporter_H
diff --git a/ndb/src/common/transporter/TransporterRegistry.cpp b/ndb/src/common/transporter/TransporterRegistry.cpp
index 3f98eeed89e..01f1f74f053 100644
--- a/ndb/src/common/transporter/TransporterRegistry.cpp
+++ b/ndb/src/common/transporter/TransporterRegistry.cpp
@@ -16,10 +16,11 @@
#include <ndb_global.h>
-#include "TransporterRegistry.hpp"
+#include <TransporterRegistry.hpp>
#include "TransporterInternalDefinitions.hpp"
#include "Transporter.hpp"
+#include <SocketAuthenticator.hpp>
#ifdef NDB_TCP_TRANSPORTER
#include "TCP_Transporter.hpp"
@@ -42,20 +43,67 @@
#include "NdbOut.hpp"
#include <NdbSleep.h>
#include <NdbTick.h>
-#define STEPPING 1
+#include <InputStream.hpp>
+#include <OutputStream.hpp>
+
+SocketServer::Session * TransporterService::newSession(NDB_SOCKET_TYPE sockfd)
+{
+ if (m_auth && !m_auth->server_authenticate(sockfd)){
+ NDB_CLOSE_SOCKET(sockfd);
+ return 0;
+ }
+
+ {
+ // read node id from client
+ int nodeId;
+ SocketInputStream s_input(sockfd);
+ char buf[256];
+ if (s_input.gets(buf, 256) == 0) {
+ NDB_CLOSE_SOCKET(sockfd);
+ return 0;
+ }
+ if (sscanf(buf, "%d", &nodeId) != 1) {
+ NDB_CLOSE_SOCKET(sockfd);
+ return 0;
+ }
+
+ //check that nodeid is valid and that there is an allocated transporter
+ if ( nodeId < 0 || nodeId >= m_transporter_registry->maxTransporters) {
+ NDB_CLOSE_SOCKET(sockfd);
+ return 0;
+ }
+ if (m_transporter_registry->theTransporters[nodeId] == 0) {
+ NDB_CLOSE_SOCKET(sockfd);
+ return 0;
+ }
+
+ //check that the transporter should be connected
+ if (m_transporter_registry->performStates[nodeId] != TransporterRegistry::CONNECTING) {
+ NDB_CLOSE_SOCKET(sockfd);
+ return 0;
+ }
+
+ Transporter *t= m_transporter_registry->theTransporters[nodeId];
+
+ // send info about own id (just as response to acknowledge connection)
+ SocketOutputStream s_output(sockfd);
+ s_output.println("%d", t->getLocalNodeId());
+
+ // setup transporter (transporter responsible for closing sockfd)
+ t->connect_server(sockfd);
+ }
+
+ return 0;
+}
TransporterRegistry::TransporterRegistry(void * callback,
unsigned _maxTransporters,
unsigned sizeOfLongSignalMemory) {
+ m_transporter_service= 0;
nodeIdSpecified = false;
maxTransporters = _maxTransporters;
sendCounter = 1;
- m_ccCount = 0;
- m_ccIndex = 0;
- m_ccStep = STEPPING;
- m_ccReady = false;
- m_nTransportersPerformConnect=0;
callbackObj=callback;
@@ -82,7 +130,7 @@ TransporterRegistry::TransporterRegistry(void * callback,
theSHMTransporters[i] = NULL;
theOSETransporters[i] = NULL;
theTransporters[i] = NULL;
- performStates[i] = PerformNothing;
+ performStates[i] = DISCONNECTED;
ioStates[i] = NoHalt;
}
theOSEReceiver = 0;
@@ -152,15 +200,15 @@ TransporterRegistry::createTransporter(TCP_TransporterConfiguration *config) {
if(theTransporters[config->remoteNodeId] != NULL)
return false;
-
-
- TCP_Transporter * t = new TCP_Transporter(config->sendBufferSize,
- config->maxReceiveSize,
- config->port,
- config->remoteHostName,
+
+ TCP_Transporter * t = new TCP_Transporter(*this,
+ config->sendBufferSize,
+ config->maxReceiveSize,
config->localHostName,
- config->remoteNodeId,
+ config->remoteHostName,
+ config->port,
localNodeId,
+ config->remoteNodeId,
config->byteOrder,
config->compression,
config->checksum,
@@ -172,13 +220,11 @@ TransporterRegistry::createTransporter(TCP_TransporterConfiguration *config) {
return false;
}
- t->setCallbackObject(callbackObj);
-
// Put the transporter in the transporter arrays
theTCPTransporters[nTCPTransporters] = t;
theTransporters[t->getRemoteNodeId()] = t;
theTransporterTypes[t->getRemoteNodeId()] = tt_TCP_TRANSPORTER;
- performStates[t->getRemoteNodeId()] = PerformNothing;
+ performStates[t->getRemoteNodeId()] = DISCONNECTED;
nTransporters++;
nTCPTransporters++;
@@ -228,12 +274,11 @@ TransporterRegistry::createTransporter(OSE_TransporterConfiguration *conf) {
delete t;
return false;
}
- t->setCallbackObject(callbackObj);
// Put the transporter in the transporter arrays
theOSETransporters[nOSETransporters] = t;
theTransporters[t->getRemoteNodeId()] = t;
theTransporterTypes[t->getRemoteNodeId()] = tt_OSE_TRANSPORTER;
- performStates[t->getRemoteNodeId()] = PerformNothing;
+ performStates[t->getRemoteNodeId()] = DISCONNECTED;
nTransporters++;
nOSETransporters++;
@@ -279,12 +324,11 @@ TransporterRegistry::createTransporter(SCI_TransporterConfiguration *config) {
delete t;
return false;
}
- t->setCallbackObject(callbackObj);
// Put the transporter in the transporter arrays
theSCITransporters[nSCITransporters] = t;
theTransporters[t->getRemoteNodeId()] = t;
theTransporterTypes[t->getRemoteNodeId()] = tt_SCI_TRANSPORTER;
- performStates[t->getRemoteNodeId()] = PerformNothing;
+ performStates[t->getRemoteNodeId()] = DISCONNECTED;
nTransporters++;
nSCITransporters++;
@@ -307,13 +351,17 @@ TransporterRegistry::createTransporter(SHM_TransporterConfiguration *config) {
if(theTransporters[config->remoteNodeId] != NULL)
return false;
- SHM_Transporter * t = new SHM_Transporter(config->localNodeId,
+ SHM_Transporter * t = new SHM_Transporter(*this,
+ "localhost",
+ "localhost",
+ config->port,
+ localNodeId,
config->remoteNodeId,
- config->shmKey,
- config->shmSize,
config->compression,
config->checksum,
- config->signalId
+ config->signalId,
+ config->shmKey,
+ config->shmSize
);
if (t == NULL)
return false;
@@ -321,12 +369,11 @@ TransporterRegistry::createTransporter(SHM_TransporterConfiguration *config) {
delete t;
return false;
}
- t->setCallbackObject(callbackObj);
// Put the transporter in the transporter arrays
theSHMTransporters[nSHMTransporters] = t;
theTransporters[t->getRemoteNodeId()] = t;
theTransporterTypes[t->getRemoteNodeId()] = tt_SHM_TRANSPORTER;
- performStates[t->getRemoteNodeId()] = PerformNothing;
+ performStates[t->getRemoteNodeId()] = DISCONNECTED;
nTransporters++;
nSHMTransporters++;
@@ -781,7 +828,7 @@ TransporterRegistry::performReceive(){
TCP_Transporter *t = theTCPTransporters[i];
const NodeId nodeId = t->getRemoteNodeId();
const NDB_SOCKET_TYPE socket = t->getSocket();
- if(performStates[nodeId] == PerformIO){
+ if(is_connected(nodeId)){
if(t->isConnected() && FD_ISSET(socket, &tcpReadset)) {
const int receiveSize = t->doReceive();
if(receiveSize > 0){
@@ -804,7 +851,7 @@ TransporterRegistry::performReceive(){
checkJobBuffer();
SCI_Transporter *t = theSCITransporters[i];
const NodeId nodeId = t->getRemoteNodeId();
- if(performStates[nodeId] == PerformIO){
+ if(is_connected(nodeId)){
if(t->isConnected() && t->checkConnected()){
Uint32 * readPtr, * eodPtr;
t->getReceivePtr(&readPtr, &eodPtr);
@@ -819,7 +866,7 @@ TransporterRegistry::performReceive(){
checkJobBuffer();
SHM_Transporter *t = theSHMTransporters[i];
const NodeId nodeId = t->getRemoteNodeId();
- if(performStates[nodeId] == PerformIO){
+ if(is_connected(nodeId)){
if(t->isConnected() && t->checkConnected()){
Uint32 * readPtr, * eodPtr;
t->getReceivePtr(&readPtr, &eodPtr);
@@ -834,13 +881,13 @@ TransporterRegistry::performReceive(){
static int x = 0;
void
TransporterRegistry::performSend(){
-
+ int i;
sendCounter = 1;
#ifdef NDB_OSE_TRANSPORTER
for (int i = 0; i < nOSETransporters; i++){
OSE_Transporter *t = theOSETransporters[i];
- if((performStates[t->getRemoteNodeId()] == PerformIO) &&
+ if((is_connected(t->getRemoteNodeId()) &&
(t->isConnected())) {
t->doSend();
}//if
@@ -858,7 +905,7 @@ TransporterRegistry::performSend(){
FD_ZERO(&writeset);
// Prepare for sending and receiving
- for (int i = 0; i < nTCPTransporters; i++) {
+ for (i = 0; i < nTCPTransporters; i++) {
TCP_Transporter * t = theTCPTransporters[i];
// If the transporter is connected
@@ -883,11 +930,11 @@ TransporterRegistry::performSend(){
if (tmp == 0) {
return;
}//if
- for (int i = 0; i < nTCPTransporters; i++) {
+ for (i = 0; i < nTCPTransporters; i++) {
TCP_Transporter *t = theTCPTransporters[i];
const NodeId nodeId = t->getRemoteNodeId();
const int socket = t->getSocket();
- if(performStates[nodeId] == PerformIO){
+ if(is_connected(nodeId)){
if(t->isConnected() && FD_ISSET(socket, &writeset)) {
t->doSend();
}//if
@@ -896,21 +943,21 @@ TransporterRegistry::performSend(){
}
#endif
#ifdef NDB_TCP_TRANSPORTER
- for (int i = x; i < nTCPTransporters; i++) {
+ for (i = x; i < nTCPTransporters; i++) {
TCP_Transporter *t = theTCPTransporters[i];
if (t &&
(t->hasDataToSend()) &&
(t->isConnected()) &&
- (performStates[t->getRemoteNodeId()] == PerformIO)) {
+ (is_connected(t->getRemoteNodeId()))) {
t->doSend();
}//if
}//for
- for (int i = 0; i < x && i < nTCPTransporters; i++) {
+ for (i = 0; i < x && i < nTCPTransporters; i++) {
TCP_Transporter *t = theTCPTransporters[i];
if (t &&
(t->hasDataToSend()) &&
(t->isConnected()) &&
- (performStates[t->getRemoteNodeId()] == PerformIO)) {
+ (is_connected(t->getRemoteNodeId()))) {
t->doSend();
}//if
}//for
@@ -921,11 +968,11 @@ TransporterRegistry::performSend(){
#ifdef NDB_SCI_TRANSPORTER
//scroll through the SCI transporters,
// get each transporter, check if connected, send data
- for (int i=0; i<nSCITransporters; i++) {
+ for (i=0; i<nSCITransporters; i++) {
SCI_Transporter *t = theSCITransporters[i];
const NodeId nodeId = t->getRemoteNodeId();
- if(performStates[nodeId] == PerformIO){
+ if(is_connected(nodeId)){
if(t->isConnected() && t->hasDataToSend()) {
t->doSend();
} //if
@@ -961,70 +1008,212 @@ TransporterRegistry::printState(){
}
#endif
-PerformState
-TransporterRegistry::performState(NodeId nodeId) {
- return performStates[nodeId];
+IOState
+TransporterRegistry::ioState(NodeId nodeId) {
+ return ioStates[nodeId];
}
-#ifdef DEBUG_TRANSPORTER
-const char *
-performStateString(PerformState state){
- switch(state){
- case PerformNothing:
- return "PerformNothing";
- break;
- case PerformIO:
- return "PerformIO";
+void
+TransporterRegistry::setIOState(NodeId nodeId, IOState state) {
+ DEBUG("TransporterRegistry::setIOState("
+ << nodeId << ", " << state << ")");
+ ioStates[nodeId] = state;
+}
+
+static void *
+run_start_clients_C(void * me)
+{
+ ((TransporterRegistry*) me)->start_clients_thread();
+ NdbThread_Exit(0);
+ return me;
+}
+
+// Run by kernel thread
+void
+TransporterRegistry::do_connect(NodeId node_id)
+{
+ PerformState &curr_state = performStates[node_id];
+ switch(curr_state){
+ case DISCONNECTED:
break;
- case PerformConnect:
- return "PerformConnect";
+ case CONNECTED:
+ return;
+ case CONNECTING:
+ return;
+ case DISCONNECTING:
break;
- case PerformDisconnect:
- return "PerformDisconnect";
+ }
+ curr_state= CONNECTING;
+}
+void
+TransporterRegistry::do_disconnect(NodeId node_id)
+{
+ PerformState &curr_state = performStates[node_id];
+ switch(curr_state){
+ case DISCONNECTED:
+ return;
+ case CONNECTED:
break;
- case RemoveTransporter:
- return "RemoveTransporter";
+ case CONNECTING:
break;
+ case DISCONNECTING:
+ return;
}
- return "Unknown";
+ curr_state= DISCONNECTING;
}
-#endif
void
-TransporterRegistry::setPerformState(NodeId nodeId, PerformState state) {
- DEBUG("TransporterRegistry::setPerformState("
- << nodeId << ", " << performStateString(state) << ")");
-
- performStates[nodeId] = state;
+TransporterRegistry::report_connect(NodeId node_id)
+{
+ performStates[node_id] = CONNECTED;
+ reportConnect(callbackObj, node_id);
+}
+
+void
+TransporterRegistry::report_disconnect(NodeId node_id, int errnum)
+{
+ performStates[node_id] = DISCONNECTED;
+ reportDisconnect(callbackObj, node_id, errnum);
}
void
-TransporterRegistry::setPerformState(PerformState state) {
- int count = 0;
- int index = 0;
- while(count < nTransporters){
- if(theTransporters[index] != 0){
- setPerformState(theTransporters[index]->getRemoteNodeId(), state);
- count ++;
+TransporterRegistry::update_connections()
+{
+ for (int i= 0, n= 0; n < nTransporters; i++){
+ Transporter * t = theTransporters[i];
+ if (!t)
+ continue;
+ n++;
+
+ const NodeId nodeId = t->getRemoteNodeId();
+ switch(performStates[nodeId]){
+ case CONNECTED:
+ case DISCONNECTED:
+ break;
+ case CONNECTING:
+ if(t->isConnected())
+ report_connect(nodeId);
+ break;
+ case DISCONNECTING:
+ if(!t->isConnected())
+ report_disconnect(nodeId, 0);
+ break;
}
- index ++;
}
}
-IOState
-TransporterRegistry::ioState(NodeId nodeId) {
- return ioStates[nodeId];
+// run as own thread
+void
+TransporterRegistry::start_clients_thread()
+{
+ while (m_run_start_clients_thread) {
+ NdbSleep_MilliSleep(100);
+ for (int i= 0, n= 0; n < nTransporters && m_run_start_clients_thread; i++){
+ Transporter * t = theTransporters[i];
+ if (!t)
+ continue;
+ n++;
+
+ const NodeId nodeId = t->getRemoteNodeId();
+ switch(performStates[nodeId]){
+ case CONNECTING:
+ if(!t->isConnected() && !t->isServer)
+ t->connect_client();
+ break;
+ case DISCONNECTING:
+ if(t->isConnected())
+ t->doDisconnect();
+ break;
+ default:
+ break;
+ }
+ }
+ }
}
-void
-TransporterRegistry::setIOState(NodeId nodeId, IOState state) {
- DEBUG("TransporterRegistry::setIOState("
- << nodeId << ", " << state << ")");
- ioStates[nodeId] = state;
+bool
+TransporterRegistry::start_clients()
+{
+ m_run_start_clients_thread= true;
+ m_start_clients_thread= NdbThread_Create(run_start_clients_C,
+ (void**)this,
+ 32768,
+ "ndb_start_clients",
+ NDB_THREAD_PRIO_LOW);
+ if (m_start_clients_thread == 0) {
+ m_run_start_clients_thread= false;
+ return false;
+ }
+ return true;
+}
+
+bool
+TransporterRegistry::stop_clients()
+{
+ if (m_start_clients_thread) {
+ m_run_start_clients_thread= false;
+ void* status;
+ int r= NdbThread_WaitFor(m_start_clients_thread, &status);
+ NdbThread_Destroy(&m_start_clients_thread);
+ }
+ return true;
+}
+
+bool
+TransporterRegistry::start_service(SocketServer& socket_server)
+{
+#if 0
+ for (int i= 0, n= 0; n < nTransporters; i++){
+ Transporter * t = theTransporters[i];
+ if (!t)
+ continue;
+ n++;
+ if (t->isServer) {
+ t->m_service = new TransporterService(new SocketAuthSimple("ndbd passwd"));
+ if(!socket_server.setup(t->m_service, t->m_r_port, 0))
+ {
+ ndbout_c("Unable to setup transporter service port: %d!\n"
+ "Please check if the port is already used,\n"
+ "(perhaps a mgmtsrvrserver is already running)",
+ m_service_port);
+ delete t->m_service;
+ return false;
+ }
+ }
+ }
+#endif
+
+ if (m_service_port != 0) {
+
+ m_transporter_service = new TransporterService(new SocketAuthSimple("ndbd", "ndbd passwd"));
+
+ if (nodeIdSpecified != true) {
+ ndbout_c("TransporterRegistry::startReceiving: localNodeId not specified");
+ return false;
+ }
+
+ //m_interface_name = "ndbd";
+ m_interface_name = 0;
+
+ if(!socket_server.setup(m_transporter_service, m_service_port, m_interface_name))
+ {
+ ndbout_c("Unable to setup transporter service port: %d!\n"
+ "Please check if the port is already used,\n"
+ "(perhaps a mgmtsrvrserver is already running)",
+ m_service_port);
+ delete m_transporter_service;
+ return false;
+ }
+ m_transporter_service->setTransporterRegistry(this);
+ } else
+ m_transporter_service= 0;
+
+ return true;
}
void
-TransporterRegistry::startReceiving(){
+TransporterRegistry::startReceiving()
+{
#ifdef NDB_OSE_TRANSPORTER
if(theOSEReceiver != NULL){
theOSEReceiver->createPhantom();
@@ -1081,99 +1270,6 @@ TransporterRegistry::stopSending(){
#endif
}
-/**
- * The old implementation did not scale with a large
- * number of nodes. (Watchdog killed NDB because
- * it took too long time to allocated threads in
- * doConnect.
- *
- * The new implementation only checks the connection
- * for a number of transporters (STEPPING), until to
- * the point where all transporters has executed
- * doConnect once. After that, the behaviour is as
- * in the old implemenation, i.e, checking the connection
- * for all transporters.
- * @todo: instead of STEPPING, maybe we should only
- * allow checkConnections to execute for a certain
- * time that somehow factors in heartbeat times and
- * watchdog times.
- *
- */
-
-void
-TransporterRegistry::checkConnections(){
- if(m_ccStep > nTransporters)
- m_ccStep = nTransporters;
-
- while(m_ccCount < m_ccStep){
- if(theTransporters[m_ccIndex] != 0){
- Transporter * t = theTransporters[m_ccIndex];
- const NodeId nodeId = t->getRemoteNodeId();
- if(t->getThreadError() != 0) {
- reportError(callbackObj, nodeId, t->getThreadError());
- t->resetThreadError();
- }
-
- switch(performStates[nodeId]){
- case PerformConnect:
- if(!t->isConnected()){
- t->doConnect();
- if(m_nTransportersPerformConnect!=nTransporters)
- m_nTransportersPerformConnect++;
-
- } else {
- performStates[nodeId] = PerformIO;
- reportConnect(callbackObj, nodeId);
- }
- break;
- case PerformDisconnect:
- {
- bool wasConnected = t->isConnected();
- t->doDisconnect();
- performStates[nodeId] = PerformNothing;
- if(wasConnected){
- reportDisconnect(callbackObj, nodeId,0);
- }
- }
- break;
- case RemoveTransporter:
- removeTransporter(nodeId);
- break;
- case PerformNothing:
- case PerformIO:
- break;
- }
- m_ccCount ++;
- }
- m_ccIndex ++;
- }
-
- if(!m_ccReady) {
- if(m_ccCount < nTransporters) {
- if(nTransporters - m_ccStep < STEPPING)
- m_ccStep += nTransporters-m_ccStep;
- else
- m_ccStep += STEPPING;
-
- // ndbout_c("count %d step %d ", m_ccCount, m_ccStep);
- }
- else {
- m_ccCount = 0;
- m_ccIndex = 0;
- m_ccStep = STEPPING;
- // ndbout_c("count %d step %d ", m_ccCount, m_ccStep);
- }
- }
- if((nTransporters == m_nTransportersPerformConnect) || m_ccReady) {
- m_ccReady = true;
- m_ccCount = 0;
- m_ccIndex = 0;
- m_ccStep = nTransporters;
- // ndbout_c("alla count %d step %d ", m_ccCount, m_ccStep);
- }
-
-}//TransporterRegistry::checkConnections()
-
NdbOut & operator <<(NdbOut & out, SignalHeader & sh){
out << "-- Signal Header --" << endl;
out << "theLength: " << sh.theLength << endl;
diff --git a/ndb/src/common/util/BaseString.cpp b/ndb/src/common/util/BaseString.cpp
index d15249adf72..8b7df485f77 100644
--- a/ndb/src/common/util/BaseString.cpp
+++ b/ndb/src/common/util/BaseString.cpp
@@ -412,3 +412,6 @@ int main()
}
#endif
+
+template class Vector<char *>;
+template class Vector<BaseString>;
diff --git a/ndb/src/common/util/ConfigValues.cpp b/ndb/src/common/util/ConfigValues.cpp
index 7fc99bc526c..8a14882550c 100644
--- a/ndb/src/common/util/ConfigValues.cpp
+++ b/ndb/src/common/util/ConfigValues.cpp
@@ -105,19 +105,19 @@ ConfigValues::getByPos(Uint32 pos, Entry * result) const {
Uint64 *
ConfigValues::get64(Uint32 index) const {
assert(index < m_int64Count);
- const Uint32 * data = m_values + (m_size << 1);
+ const Uint32 * data = m_values + (m_size << 1);
Uint64 * ptr = (Uint64*)data;
- ptr += index;
+ ptr += index;
return ptr;
}
char **
ConfigValues::getString(Uint32 index) const {
assert(index < m_stringCount);
- const Uint32 * data = m_values + (m_size << 1);
- char * ptr = (char*)data;
+ const Uint32 * data = m_values + (m_size << 1);
+ char * ptr = (char*)data;
ptr += m_dataSize;
- ptr -= (index * sizeof(char *));
+ ptr -= (index * sizeof(char *));
return (char**)ptr;
}
@@ -261,9 +261,9 @@ directory(Uint32 sz){
ConfigValuesFactory::ConfigValuesFactory(Uint32 keys, Uint32 data){
m_sectionCounter = (1 << KP_SECTION_SHIFT);
m_freeKeys = directory(keys);
- m_freeData = data;
+ m_freeData = (data + 7) & ~7;
m_currentSection = 0;
- m_cfg = create(m_freeKeys, data);
+ m_cfg = create(m_freeKeys, m_freeData);
}
ConfigValuesFactory::ConfigValuesFactory(ConfigValues * cfg){
@@ -316,7 +316,8 @@ ConfigValuesFactory::expand(Uint32 fk, Uint32 fs){
m_freeKeys = (m_freeKeys >= fk ? m_cfg->m_size : fk + m_cfg->m_size);
m_freeData = (m_freeData >= fs ? m_cfg->m_dataSize : fs + m_cfg->m_dataSize);
m_freeKeys = directory(m_freeKeys);
-
+ m_freeData = (m_freeData + 7) & ~7;
+
ConfigValues * m_tmp = m_cfg;
m_cfg = create(m_freeKeys, m_freeData);
put(* m_tmp);
@@ -333,6 +334,7 @@ ConfigValuesFactory::shrink(){
m_freeKeys = m_cfg->m_size - m_freeKeys;
m_freeData = m_cfg->m_dataSize - m_freeData;
m_freeKeys = directory(m_freeKeys);
+ m_freeData = (m_freeData + 7) & ~7;
ConfigValues * m_tmp = m_cfg;
m_cfg = create(m_freeKeys, m_freeData);
@@ -462,7 +464,7 @@ ConfigValuesFactory::put(const ConfigValues::Entry & entry){
case ConfigValues::StringType:{
Uint32 index = m_cfg->m_stringCount++;
m_cfg->m_values[pos+1] = index;
- char ** ref = m_cfg->getString(index);
+ char ** ref = m_cfg->getString(index);
* ref = strdup(entry.m_string ? entry.m_string : "");
m_freeKeys--;
m_freeData -= sizeof(char *);
@@ -578,11 +580,11 @@ ConfigValues::getPackedSize() const {
Uint32
ConfigValues::pack(void * _dst, Uint32 _len) const {
-
+ Uint32 i;
char * dst = (char*)_dst;
memcpy(dst, Magic, sizeof(Magic)); dst += sizeof(Magic);
- for(Uint32 i = 0; i < 2 * m_size; i += 2){
+ for(i = 0; i < 2 * m_size; i += 2){
Uint32 key = m_values[i];
Uint32 val = m_values[i+1];
if(key != CFV_KEY_FREE){
@@ -621,7 +623,7 @@ ConfigValues::pack(void * _dst, Uint32 _len) const {
const Uint32 * sum = (Uint32*)_dst;
const Uint32 len = ((Uint32*)dst) - sum;
Uint32 chk = 0;
- for(Uint32 i = 0; i<len; i++){
+ for(i = 0; i<len; i++){
chk ^= htonl(sum[i]);
}
diff --git a/ndb/src/common/util/Makefile.am b/ndb/src/common/util/Makefile.am
index 59d9775b8e3..678added01e 100644
--- a/ndb/src/common/util/Makefile.am
+++ b/ndb/src/common/util/Makefile.am
@@ -3,7 +3,8 @@ noinst_LTLIBRARIES = libgeneral.la
libgeneral_la_SOURCES = \
File.cpp md5_hash.cpp Properties.cpp socket_io.cpp \
- SimpleProperties.cpp Parser.cpp InputStream.cpp SocketServer.cpp \
+ SimpleProperties.cpp Parser.cpp InputStream.cpp \
+ SocketServer.cpp SocketClient.cpp SocketAuthenticator.cpp\
OutputStream.cpp NdbOut.cpp BaseString.cpp Base64.cpp \
NdbSqlUtil.cpp new.cpp \
uucode.c random.c getarg.c version.c \
diff --git a/ndb/src/common/util/NdbSqlUtil.cpp b/ndb/src/common/util/NdbSqlUtil.cpp
index e34d6d18539..9d05fc7fb02 100644
--- a/ndb/src/common/util/NdbSqlUtil.cpp
+++ b/ndb/src/common/util/NdbSqlUtil.cpp
@@ -98,11 +98,11 @@ NdbSqlUtil::m_typeList[] = {
},
{
Type::Mediumint,
- NULL // cmpMediumint
+ cmpMediumint
},
{
Type::Mediumunsigned,
- NULL // cmpMediumunsigned
+ cmpMediumunsigned
},
{
Type::Int,
@@ -130,7 +130,7 @@ NdbSqlUtil::m_typeList[] = {
},
{
Type::Decimal,
- NULL // cmpDecimal
+ NULL // cmpDecimal
},
{
Type::Char,
@@ -142,11 +142,11 @@ NdbSqlUtil::m_typeList[] = {
},
{
Type::Binary,
- NULL // cmpBinary
+ cmpBinary
},
{
Type::Varbinary,
- NULL // cmpVarbinary
+ cmpVarbinary
},
{
Type::Datetime,
@@ -154,15 +154,15 @@ NdbSqlUtil::m_typeList[] = {
},
{
Type::Timespec,
- NULL // cmpTimespec
+ cmpTimespec
},
{
Type::Blob,
- NULL // cmpDatetime
+ cmpBlob
},
{
- Type::Clob,
- cmpClob
+ Type::Text,
+ cmpText
}
};
@@ -299,9 +299,9 @@ NdbSqlUtil::cmpBlob(const Uint32* p1, const Uint32* p2, Uint32 full, Uint32 size
}
int
-NdbSqlUtil::cmpClob(const Uint32* p1, const Uint32* p2, Uint32 full, Uint32 size)
+NdbSqlUtil::cmpText(const Uint32* p1, const Uint32* p2, Uint32 full, Uint32 size)
{
- return cmp(Type::Clob, p1, p2, full, size);
+ return cmp(Type::Text, p1, p2, full, size);
}
#ifdef NDB_SQL_UTIL_TEST
diff --git a/ndb/src/common/util/Parser.cpp b/ndb/src/common/util/Parser.cpp
index 2e8120f88ce..dea128ccf66 100644
--- a/ndb/src/common/util/Parser.cpp
+++ b/ndb/src/common/util/Parser.cpp
@@ -347,3 +347,4 @@ ParserImpl::checkMandatory(Context* ctx, const Properties* props){
return true;
}
+template class Vector<const ParserRow<ParserImpl::Dummy>*>;
diff --git a/ndb/src/common/util/Properties.cpp b/ndb/src/common/util/Properties.cpp
index 3e41056ac18..80fb0027830 100644
--- a/ndb/src/common/util/Properties.cpp
+++ b/ndb/src/common/util/Properties.cpp
@@ -56,7 +56,7 @@ class PropertiesImpl {
PropertiesImpl(const PropertiesImpl &); // Not implemented
PropertiesImpl& operator=(const PropertiesImpl&); // Not implemented
public:
- PropertiesImpl(Properties *);
+ PropertiesImpl(Properties *, bool case_insensitive);
PropertiesImpl(Properties *, const PropertiesImpl &);
~PropertiesImpl();
@@ -69,6 +69,7 @@ public:
bool m_insensitive;
int (* compare)(const char *s1, const char *s2);
+ void setCaseInsensitiveNames(bool value);
void grow(int sizeToAdd);
PropertyImpl * get(const char * name) const;
@@ -113,9 +114,9 @@ Property::~Property(){
/**
* Methods for Properties
*/
-Properties::Properties(){
+Properties::Properties(bool case_insensitive){
parent = 0;
- impl = new PropertiesImpl(this);
+ impl = new PropertiesImpl(this, case_insensitive);
}
Properties::Properties(const Properties & org){
@@ -124,7 +125,7 @@ Properties::Properties(const Properties & org){
}
Properties::Properties(const Property * anArray, int arrayLen){
- impl = new PropertiesImpl(this);
+ impl = new PropertiesImpl(this, false);
put(anArray, arrayLen);
}
@@ -169,6 +170,7 @@ put(PropertiesImpl * impl, const char * name, T value, bool replace){
return tmp->put(new PropertyImpl(short_name, value));
}
+
bool
Properties::put(const char * name, Uint32 value, bool replace){
return ::put(impl, name, value, replace);
@@ -478,13 +480,12 @@ Properties::unpack(const Uint32 * buf, Uint32 bufLen){
/**
* Methods for PropertiesImpl
*/
-PropertiesImpl::PropertiesImpl(Properties * p){
+PropertiesImpl::PropertiesImpl(Properties * p, bool case_insensitive){
this->properties = p;
items = 0;
size = 25;
content = new PropertyImpl * [size];
- this->m_insensitive = false;
- this->compare = strcmp;
+ setCaseInsensitiveNames(case_insensitive);
}
PropertiesImpl::PropertiesImpl(Properties * p, const PropertiesImpl & org){
@@ -505,6 +506,15 @@ PropertiesImpl::~PropertiesImpl(){
delete [] content;
}
+void
+PropertiesImpl::setCaseInsensitiveNames(bool value){
+ m_insensitive = value;
+ if(value)
+ compare = strcasecmp;
+ else
+ compare = strcmp;
+}
+
void
PropertiesImpl::grow(int sizeToAdd){
PropertyImpl ** newContent = new PropertyImpl * [size + sizeToAdd];
@@ -522,9 +532,11 @@ PropertiesImpl::get(const char * name) const {
return 0;
}
- for(unsigned int i = 0; i<tmp->items; i++)
+ for(unsigned int i = 0; i<tmp->items; i++) {
if((* compare)(tmp->content[i]->name, short_name) == 0)
return tmp->content[i];
+ }
+
return 0;
}
@@ -1109,14 +1121,15 @@ Properties::getCopy(const char * name, Uint32 no, Properties ** value) const {
void
Properties::setCaseInsensitiveNames(bool value){
- impl->m_insensitive = value;
- if(value)
- impl->compare = strcasecmp;
- else
- impl->compare = strcmp;
+ impl->setCaseInsensitiveNames(value);
}
bool
Properties::getCaseInsensitiveNames() const {
return impl->m_insensitive;
}
+
+template bool put(PropertiesImpl *, const char *, Uint32, bool);
+template bool put(PropertiesImpl *, const char *, Uint64, bool);
+template bool put(PropertiesImpl *, const char *, const char *, bool);
+template bool put(PropertiesImpl *, const char *, const Properties*, bool);
diff --git a/ndb/src/common/util/SocketAuthenticator.cpp b/ndb/src/common/util/SocketAuthenticator.cpp
new file mode 100644
index 00000000000..aed4db39231
--- /dev/null
+++ b/ndb/src/common/util/SocketAuthenticator.cpp
@@ -0,0 +1,91 @@
+/* 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 <ndb_global.h>
+
+#include <SocketClient.hpp>
+#include <SocketAuthenticator.hpp>
+#include <InputStream.hpp>
+#include <OutputStream.hpp>
+#include <NdbOut.hpp>
+
+SocketAuthSimple::SocketAuthSimple(const char *username, const char *passwd) {
+ if (username)
+ m_username= strdup(username);
+ else
+ m_username= 0;
+ if (passwd)
+ m_passwd= strdup(passwd);
+ else
+ m_passwd= 0;
+}
+
+SocketAuthSimple::~SocketAuthSimple()
+{
+ if (m_passwd)
+ free((void*)m_passwd);
+ if (m_username)
+ free((void*)m_username);
+}
+
+bool SocketAuthSimple::client_authenticate(int sockfd)
+{
+ SocketOutputStream s_output(sockfd);
+ SocketInputStream s_input(sockfd);
+
+ if (m_username)
+ s_output.println("%s", m_username);
+ else
+ s_output.println("");
+
+ if (m_passwd)
+ s_output.println("%s", m_passwd);
+ else
+ s_output.println("");
+
+ char buf[16];
+ if (s_input.gets(buf, 16) == 0) return false;
+ if (strncmp("ok", buf, 2) == 0)
+ return true;
+
+ return false;
+}
+
+bool SocketAuthSimple::server_authenticate(int sockfd)
+{
+
+ SocketOutputStream s_output(sockfd);
+ SocketInputStream s_input(sockfd);
+
+ char buf[256];
+
+ if (s_input.gets(buf, 256) == 0) return false;
+ buf[255]= 0;
+ if (m_username)
+ free((void*)m_username);
+ m_username= strdup(buf);
+
+ if (s_input.gets(buf, 256) == 0) return false;
+ buf[255]= 0;
+ if (m_passwd)
+ free((void*)m_passwd);
+ m_passwd= strdup(buf);
+
+ s_output.println("ok");
+
+ return true;
+}
diff --git a/ndb/src/common/util/SocketClient.cpp b/ndb/src/common/util/SocketClient.cpp
new file mode 100644
index 00000000000..ec837babc24
--- /dev/null
+++ b/ndb/src/common/util/SocketClient.cpp
@@ -0,0 +1,92 @@
+/* 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 <ndb_global.h>
+#include <NdbOut.hpp>
+
+#include <SocketClient.hpp>
+#include <SocketAuthenticator.hpp>
+
+SocketClient::SocketClient(const char *server_name, unsigned short port, SocketAuthenticator *sa)
+{
+ m_auth= sa;
+ m_port= port;
+ m_server_name= strdup(server_name);
+ m_sockfd= -1;
+}
+
+SocketClient::~SocketClient()
+{
+ if (m_server_name)
+ free(m_server_name);
+ if (m_sockfd >= 0)
+ NDB_CLOSE_SOCKET(m_sockfd);
+ if (m_auth)
+ delete m_auth;
+}
+
+bool
+SocketClient::init()
+{
+ if (m_sockfd >= 0)
+ NDB_CLOSE_SOCKET(m_sockfd);
+
+ memset(&m_servaddr, 0, sizeof(m_servaddr));
+ m_servaddr.sin_family = AF_INET;
+ m_servaddr.sin_port = htons(m_port);
+ // Convert ip address presentation format to numeric format
+ if (Ndb_getInAddr(&m_servaddr.sin_addr, m_server_name))
+ return false;
+
+ m_sockfd= socket(AF_INET, SOCK_STREAM, 0);
+ if (m_sockfd == NDB_INVALID_SOCKET) {
+ return false;
+ }
+
+ return true;
+}
+
+NDB_SOCKET_TYPE
+SocketClient::connect()
+{
+ if (m_sockfd < 0)
+ {
+ if (!init()) {
+ ndbout << "SocketClient::connect() failed " << m_server_name << " " << m_port << endl;
+ return -1;
+ }
+ }
+ const int r = ::connect(m_sockfd, (struct sockaddr*) &m_servaddr, sizeof(m_servaddr));
+ if (r == -1) {
+ NDB_CLOSE_SOCKET(m_sockfd);
+ m_sockfd= -1;
+ return -1;
+ }
+
+ if (m_auth) {
+ if (!m_auth->client_authenticate(m_sockfd))
+ {
+ NDB_CLOSE_SOCKET(m_sockfd);
+ m_sockfd= -1;
+ return -1;
+ }
+ }
+ NDB_SOCKET_TYPE sockfd= m_sockfd;
+ m_sockfd= -1;
+
+ return sockfd;
+}
diff --git a/ndb/src/common/util/SocketServer.cpp b/ndb/src/common/util/SocketServer.cpp
index a0ec0aaa676..0cc06a54496 100644
--- a/ndb/src/common/util/SocketServer.cpp
+++ b/ndb/src/common/util/SocketServer.cpp
@@ -17,7 +17,7 @@
#include <ndb_global.h>
-#include "SocketServer.hpp"
+#include <SocketServer.hpp>
#include <NdbTCP.h>
#include <NdbOut.hpp>
@@ -36,10 +36,11 @@ SocketServer::SocketServer(int maxSessions) :
}
SocketServer::~SocketServer() {
- for(unsigned i = 0; i<m_sessions.size(); i++){
+ unsigned i;
+ for(i = 0; i<m_sessions.size(); i++){
delete m_sessions[i].m_session;
}
- for(unsigned i = 0; i<m_services.size(); i++){
+ for(i = 0; i<m_services.size(); i++){
delete m_services[i].m_service;
}
}
@@ -146,7 +147,6 @@ SocketServer::doAccept(){
ServiceInstance & si = m_services[i];
if(FD_ISSET(si.m_socket, &readSet)){
-
NDB_SOCKET_TYPE childSock = accept(si.m_socket, 0, 0);
if(childSock == NDB_INVALID_SOCKET){
continue;
@@ -265,10 +265,11 @@ SocketServer::checkSessions(){
void
SocketServer::stopSessions(bool wait){
- for(int i = m_sessions.size() - 1; i>=0; i--)
+ int i;
+ for(i = m_sessions.size() - 1; i>=0; i--)
m_sessions[i].m_session->m_stop = true;
- for(int i = m_services.size() - 1; i>=0; i--)
+ for(i = m_services.size() - 1; i>=0; i--)
m_services[i].m_service->stopSessions();
if(wait){
@@ -303,3 +304,6 @@ sessionThread_C(void* _sc){
NdbThread_Exit(0);
return 0;
}
+
+template class MutexVector<SocketServer::ServiceInstance>;
+template class MutexVector<SocketServer::SessionInstance>;
diff --git a/ndb/src/common/util/socket_io.cpp b/ndb/src/common/util/socket_io.cpp
index 97bb4863a67..b2f4ef91031 100644
--- a/ndb/src/common/util/socket_io.cpp
+++ b/ndb/src/common/util/socket_io.cpp
@@ -93,8 +93,8 @@ readln_socket(NDB_SOCKET_TYPE socket, int timeout_millis,
FD_ZERO(&readset);
FD_SET(socket, &readset);
- timeout.tv_sec = 1;
- timeout.tv_usec = 0; // 1 s
+ timeout.tv_sec = (timeout_millis / 1000);
+ timeout.tv_usec = (timeout_millis % 1000) * 1000;
const int selectRes = select(socket + 1, &readset, 0, 0, &timeout);
if(selectRes != 1){
return -1;
diff --git a/ndb/src/cw/cpcd/APIService.cpp b/ndb/src/cw/cpcd/APIService.cpp
index caf19ddba0e..46b043c7004 100644
--- a/ndb/src/cw/cpcd/APIService.cpp
+++ b/ndb/src/cw/cpcd/APIService.cpp
@@ -382,3 +382,5 @@ CPCDAPISession::listProcesses(Parser_t::Context & /* unused */,
m_cpcd.m_processes.unlock();
}
+
+template class Vector<ParserRow<CPCDAPISession> const*>;
diff --git a/ndb/src/cw/cpcd/CPCD.cpp b/ndb/src/cw/cpcd/CPCD.cpp
index f2878b7dea1..44db10422b9 100644
--- a/ndb/src/cw/cpcd/CPCD.cpp
+++ b/ndb/src/cw/cpcd/CPCD.cpp
@@ -351,8 +351,9 @@ CPCD::loadProcessList(){
sess.loadFile();
loadingProcessList = false;
+ size_t i;
Vector<int> temporary;
- for(size_t i = 0; i<m_processes.size(); i++){
+ for(i = 0; i<m_processes.size(); i++){
Process * proc = m_processes[i];
proc->readPid();
if(proc->m_processType == TEMPORARY){
@@ -360,7 +361,7 @@ CPCD::loadProcessList(){
}
}
- for(size_t i = 0; i<temporary.size(); i++){
+ for(i = 0; i<temporary.size(); i++){
RequestStatus rs;
undefineProcess(&rs, temporary[i]);
}
@@ -430,3 +431,5 @@ CPCD::report(int id, CPCEvent::EventType t){
}
m_subscribers.unlock();
}
+
+template class MutexVector<EventSubscriber*>;
diff --git a/ndb/src/cw/cpcd/Makefile.am b/ndb/src/cw/cpcd/Makefile.am
index 6345bae9bbe..1f7b0d88448 100644
--- a/ndb/src/cw/cpcd/Makefile.am
+++ b/ndb/src/cw/cpcd/Makefile.am
@@ -1,5 +1,5 @@
-ndbtools_PROGRAMS = ndb_cpcd
+ndbbin_PROGRAMS = ndb_cpcd
ndb_cpcd_SOURCES = main.cpp CPCD.cpp Process.cpp APIService.cpp Monitor.cpp common.cpp
diff --git a/ndb/src/cw/cpcd/Monitor.cpp b/ndb/src/cw/cpcd/Monitor.cpp
index 2935cd0a648..141de926d4d 100644
--- a/ndb/src/cw/cpcd/Monitor.cpp
+++ b/ndb/src/cw/cpcd/Monitor.cpp
@@ -75,3 +75,5 @@ void
CPCD::Monitor::signal() {
NdbCondition_Signal(m_changeCondition);
}
+
+template class MutexVector<CPCD::Process*>;
diff --git a/ndb/src/cw/cpcd/Process.cpp b/ndb/src/cw/cpcd/Process.cpp
index 74426306a88..0a986f63fda 100644
--- a/ndb/src/cw/cpcd/Process.cpp
+++ b/ndb/src/cw/cpcd/Process.cpp
@@ -15,8 +15,6 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include <ndb_global.h>
-#include <signal.h>
-
#include <BaseString.hpp>
#include <InputStream.hpp>
@@ -209,54 +207,50 @@ int
set_ulimit(const BaseString & pair){
#ifdef HAVE_GETRLIMIT
errno = 0;
- do {
- Vector<BaseString> list;
- pair.split(list, ":");
- if(list.size() != 2){
- break;
- }
-
- int res;
- rlim_t value = RLIM_INFINITY;
- if(!(list[1].trim() == "unlimited")){
- value = atoi(list[1].c_str());
- }
-
- struct rlimit rlp;
+ Vector<BaseString> list;
+ pair.split(list, ":");
+ if(list.size() != 2){
+ logger.error("Unable to process ulimit: split >%s< list.size()=%d",
+ pair.c_str(), list.size());
+ return -1;
+ }
+
+ int res;
+ rlim_t value = RLIM_INFINITY;
+ if(!(list[1].trim() == "unlimited")){
+ value = atoi(list[1].c_str());
+ }
+
+ struct rlimit rlp;
#define _RLIMIT_FIX(x) { res = getrlimit(x,&rlp); if(!res){ rlp.rlim_cur = value; res = setrlimit(x, &rlp); }}
-
- if(list[0].trim() == "c"){
- _RLIMIT_FIX(RLIMIT_CORE);
- } else if(list[0] == "d"){
- _RLIMIT_FIX(RLIMIT_DATA);
- } else if(list[0] == "f"){
- _RLIMIT_FIX(RLIMIT_FSIZE);
- } else if(list[0] == "n"){
- _RLIMIT_FIX(RLIMIT_NOFILE);
- } else if(list[0] == "s"){
- _RLIMIT_FIX(RLIMIT_STACK);
- } else if(list[0] == "t"){
- _RLIMIT_FIX(RLIMIT_CPU);
- } else {
- errno = EINVAL;
- break;
- }
- if(!res)
- break;
-
- return 0;
- } while(false);
- logger.error("Unable to process ulimit: %s(%s)",
- pair.c_str(), strerror(errno));
- return -1;
-#else
- return 0; // Maybe it's ok anyway...
+
+ if(list[0].trim() == "c"){
+ _RLIMIT_FIX(RLIMIT_CORE);
+ } else if(list[0] == "d"){
+ _RLIMIT_FIX(RLIMIT_DATA);
+ } else if(list[0] == "f"){
+ _RLIMIT_FIX(RLIMIT_FSIZE);
+ } else if(list[0] == "n"){
+ _RLIMIT_FIX(RLIMIT_NOFILE);
+ } else if(list[0] == "s"){
+ _RLIMIT_FIX(RLIMIT_STACK);
+ } else if(list[0] == "t"){
+ _RLIMIT_FIX(RLIMIT_CPU);
+ } else {
+ errno = EINVAL;
+ }
+ if(res){
+ logger.error("Unable to process ulimit: %s res=%d error=%d(%s)",
+ pair.c_str(), res, errno, strerror(errno));
+ return -1;
+ }
#endif
+ return 0;
}
void
CPCD::Process::do_exec() {
-
+ size_t i;
setup_environment(m_env.c_str());
char **argv = BaseString::argify(m_path.c_str(), m_args.c_str());
@@ -272,7 +266,7 @@ CPCD::Process::do_exec() {
Vector<BaseString> ulimit;
m_ulimit.split(ulimit);
- for(size_t i = 0; i<ulimit.size(); i++){
+ for(i = 0; i<ulimit.size(); i++){
if(ulimit[i].trim().length() > 0 && set_ulimit(ulimit[i]) != 0){
_exit(1);
}
@@ -286,7 +280,7 @@ CPCD::Process::do_exec() {
BaseString * redirects[] = { &m_stdin, &m_stdout, &m_stderr };
int fds[3];
- for(int i = 0; i<3; i++){
+ for(i = 0; i<3; i++){
if(redirects[i]->empty()){
#ifndef DEBUG
dup2(fd, i);
@@ -319,7 +313,7 @@ CPCD::Process::do_exec() {
}
/* Close all filedescriptors */
- for(int i = STDERR_FILENO+1; i < getdtablesize(); i++)
+ for(i = STDERR_FILENO+1; i < getdtablesize(); i++)
close(i);
execv(m_path.c_str(), argv);
diff --git a/ndb/src/cw/cpcd/main.cpp b/ndb/src/cw/cpcd/main.cpp
index 11f6238d5f7..913c31de1f7 100644
--- a/ndb/src/cw/cpcd/main.cpp
+++ b/ndb/src/cw/cpcd/main.cpp
@@ -15,7 +15,6 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include <ndb_global.h> /* Needed for mkdir(2) */
-#include <signal.h>
#include "CPCD.hpp"
#include "APIService.hpp"
diff --git a/ndb/src/kernel/Makefile.am b/ndb/src/kernel/Makefile.am
index b2aa5f2e074..60284f6a369 100644
--- a/ndb/src/kernel/Makefile.am
+++ b/ndb/src/kernel/Makefile.am
@@ -4,7 +4,7 @@ include $(top_srcdir)/ndb/config/common.mk.am
ndbbin_PROGRAMS = ndbd
-ndbd_SOURCES = Main.cpp SimBlockList.cpp
+ndbd_SOURCES = main.cpp SimBlockList.cpp
include $(top_srcdir)/ndb/config/type_kernel.mk.am
diff --git a/ndb/src/kernel/blocks/ERROR_codes.txt b/ndb/src/kernel/blocks/ERROR_codes.txt
index 92dbfd067f7..af575de4f62 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 5036
+Next DBLQH 5040
Next DBDICT 6006
Next DBDIH 7173
Next DBTC 8035
@@ -190,6 +190,10 @@ Delay execution of ABORTREQ signal 2 seconds to generate time-out.
5035: Delay ACC_CONTOPCONT
+5038: Drop LQHKEYREQ + set 5039
+5039: Drop ABORT + set 5003
+
+
ERROR CODES FOR TESTING TIME-OUT HANDLING IN DBTC
-------------------------------------------------
8040:
diff --git a/ndb/src/kernel/blocks/backup/Backup.cpp b/ndb/src/kernel/blocks/backup/Backup.cpp
index 4342a9d6d94..52a543dbcdc 100644
--- a/ndb/src/kernel/blocks/backup/Backup.cpp
+++ b/ndb/src/kernel/blocks/backup/Backup.cpp
@@ -3332,7 +3332,8 @@ Backup::execBACKUP_FRAGMENT_REQ(Signal* signal)
req->transId1 = 0;
req->transId2 = (BACKUP << 20) + (getOwnNodeId() << 8);
- for(unsigned int i = 0; i<parallelism; i++) {
+ Uint32 i;
+ for(i = 0; i<parallelism; i++) {
jam();
req->clientOpPtr[i] = filePtr.i;
}//for
@@ -3350,7 +3351,7 @@ Backup::execBACKUP_FRAGMENT_REQ(Signal* signal)
signal->theData[7] = 0;
Uint32 dataPos = 8;
- for(Uint32 i = 0; i<table.noOfAttributes; i++) {
+ for(i = 0; i<table.noOfAttributes; i++) {
jam();
AttributePtr attr;
table.attributes.getPtr(attr, i);
diff --git a/ndb/src/kernel/blocks/backup/Backup.hpp b/ndb/src/kernel/blocks/backup/Backup.hpp
index 77669e759d3..1e2100251be 100644
--- a/ndb/src/kernel/blocks/backup/Backup.hpp
+++ b/ndb/src/kernel/blocks/backup/Backup.hpp
@@ -696,6 +696,7 @@ Uint32 *
Backup::OperationRecord::newVariableKey(Uint32 sz){
attrLeft--;
attrSzLeft = 0;
+ attrSzTotal += sz;
dst = &dst_VariableData->Data[0];
dst_VariableData->Sz = htonl(sz);
@@ -712,7 +713,7 @@ Backup::OperationRecord::finished(){
return false;
}
- attrLen[opNoDone] = attrSzTotal;
+ attrLen[opNoDone] = attrSzTotal + sz_FixedKeys;
opNoDone++;
scanStop = dst = (Uint32 *)dst_VariableData;
diff --git a/ndb/src/kernel/blocks/backup/BackupInit.cpp b/ndb/src/kernel/blocks/backup/BackupInit.cpp
index 36ce1857144..d8cbb36df62 100644
--- a/ndb/src/kernel/blocks/backup/BackupInit.cpp
+++ b/ndb/src/kernel/blocks/backup/BackupInit.cpp
@@ -213,3 +213,6 @@ Backup::~Backup()
BLOCK_FUNCTIONS(Backup);
+template class ArrayPool<Backup::Page32>;
+template class ArrayPool<Backup::Attribute>;
+template class ArrayPool<Backup::Fragment>;
diff --git a/ndb/src/kernel/blocks/backup/restore/Restore.cpp b/ndb/src/kernel/blocks/backup/restore/Restore.cpp
index 24d2cfbfe35..f0ca54884be 100644
--- a/ndb/src/kernel/blocks/backup/restore/Restore.cpp
+++ b/ndb/src/kernel/blocks/backup/restore/Restore.cpp
@@ -34,6 +34,7 @@ Uint64 Twiddle64(Uint64 in); // Byte shift 64-bit data
bool
BackupFile::Twiddle(const AttributeDesc* attr_desc, AttributeData* attr_data, Uint32 arraySize){
+ Uint32 i;
if(m_hostByteOrder)
return true;
@@ -47,17 +48,17 @@ BackupFile::Twiddle(const AttributeDesc* attr_desc, AttributeData* attr_data, Ui
return true;
case 16:
- for(unsigned i = 0; i<arraySize; i++){
+ for(i = 0; i<arraySize; i++){
attr_data->u_int16_value[i] = Twiddle16(attr_data->u_int16_value[i]);
}
return true;
case 32:
- for(unsigned i = 0; i<arraySize; i++){
+ for(i = 0; i<arraySize; i++){
attr_data->u_int32_value[i] = Twiddle32(attr_data->u_int32_value[i]);
}
return true;
case 64:
- for(unsigned i = 0; i<arraySize; i++){
+ for(i = 0; i<arraySize; i++){
attr_data->u_int64_value[i] = Twiddle64(attr_data->u_int64_value[i]);
}
return true;
@@ -333,8 +334,8 @@ RestoreDataIterator::getNextTuple(int & res)
Uint32 *buf_ptr = (Uint32*)_buf_ptr, *ptr = buf_ptr;
ptr += m_currentTable->m_nullBitmaskSize;
-
- for(Uint32 i= 0; i < m_currentTable->m_fixedKeys.size(); i++){
+ Uint32 i;
+ for(i= 0; i < m_currentTable->m_fixedKeys.size(); i++){
assert(ptr < buf_ptr + dataLength);
const Uint32 attrId = m_currentTable->m_fixedKeys[i]->attrId;
@@ -355,7 +356,7 @@ RestoreDataIterator::getNextTuple(int & res)
ptr += sz;
}
- for(Uint32 i = 0; i < m_currentTable->m_fixedAttribs.size(); i++){
+ for(i = 0; i < m_currentTable->m_fixedAttribs.size(); i++){
assert(ptr < buf_ptr + dataLength);
const Uint32 attrId = m_currentTable->m_fixedAttribs[i]->attrId;
@@ -377,7 +378,7 @@ RestoreDataIterator::getNextTuple(int & res)
ptr += sz;
}
- for(Uint32 i = 0; i < m_currentTable->m_variableAttribs.size(); i++){
+ for(i = 0; i < m_currentTable->m_variableAttribs.size(); i++){
const Uint32 attrId = m_currentTable->m_variableAttribs[i]->attrId;
AttributeData * attr_data = m_tuple.getData(attrId);
@@ -936,3 +937,8 @@ operator<<(NdbOut& ndbout, const TableS & table){
} // for
return ndbout;
}
+
+template class Vector<TableS*>;
+template class Vector<AttributeS*>;
+template class Vector<AttributeDesc*>;
+
diff --git a/ndb/src/kernel/blocks/backup/restore/Restore.hpp b/ndb/src/kernel/blocks/backup/restore/Restore.hpp
index e9149e38e44..5a705740c69 100644
--- a/ndb/src/kernel/blocks/backup/restore/Restore.hpp
+++ b/ndb/src/kernel/blocks/backup/restore/Restore.hpp
@@ -301,9 +301,10 @@ public:
}
~LogEntry()
{
- for(Uint32 i= 0; i< m_values.size(); i++)
+ Uint32 i;
+ for(i= 0; i< m_values.size(); i++)
delete m_values[i];
- for(Uint32 i= 0; i< m_values_e.size(); i++)
+ for(i= 0; i< m_values_e.size(); i++)
delete m_values_e[i];
}
Uint32 size() const { return m_values.size(); }
diff --git a/ndb/src/kernel/blocks/backup/restore/main.cpp b/ndb/src/kernel/blocks/backup/restore/main.cpp
index 99deeb3115c..23805173484 100644
--- a/ndb/src/kernel/blocks/backup/restore/main.cpp
+++ b/ndb/src/kernel/blocks/backup/restore/main.cpp
@@ -250,8 +250,8 @@ main(int argc, const char** argv)
return -1;
}
-
- for(Uint32 i= 0; i < g_consumers.size(); i++)
+ Uint32 i;
+ for(i= 0; i < g_consumers.size(); i++)
{
if (!g_consumers[i]->init())
{
@@ -261,7 +261,7 @@ main(int argc, const char** argv)
}
- for(Uint32 i = 0; i<metaData.getNoOfTables(); i++)
+ for(i = 0; i<metaData.getNoOfTables(); i++)
{
if (checkSysTable(metaData[i]->getTableName()))
{
@@ -345,7 +345,7 @@ main(int argc, const char** argv)
return -1;
}
logIter.validateFooter(); //not implemented
- for (Uint32 i= 0; i < g_consumers.size(); i++)
+ for (i= 0; i < g_consumers.size(); i++)
g_consumers[i]->endOfLogEntrys();
}
}
@@ -353,3 +353,4 @@ main(int argc, const char** argv)
return 1;
} // main
+template class Vector<BackupConsumer*>;
diff --git a/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp b/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp
index 694007c8508..0f25391fccb 100644
--- a/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp
+++ b/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp
@@ -114,6 +114,8 @@ Cmvmi::Cmvmi(const Configuration & conf) :
}
setNodeInfo(nodeId).m_type = nodeType;
}
+
+ setNodeInfo(getOwnNodeId()).m_connected = true;
}
Cmvmi::~Cmvmi()
@@ -360,7 +362,7 @@ void Cmvmi::execCLOSE_COMREQ(Signal* signal)
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
globalTransporterRegistry.setIOState(i, HaltIO);
- globalTransporterRegistry.setPerformState(i, PerformDisconnect);
+ globalTransporterRegistry.do_disconnect(i);
/**
* Cancel possible event subscription
@@ -388,7 +390,7 @@ void Cmvmi::execOPEN_COMREQ(Signal* signal)
const Uint32 len = signal->getLength();
if(len == 2){
- globalTransporterRegistry.setPerformState(tStartingNode, PerformConnect);
+ globalTransporterRegistry.do_connect(tStartingNode);
globalTransporterRegistry.setIOState(tStartingNode, HaltIO);
//-----------------------------------------------------
@@ -403,7 +405,7 @@ void Cmvmi::execOPEN_COMREQ(Signal* signal)
jam();
if (i != getOwnNodeId() && getNodeInfo(i).m_type == tData2){
jam();
- globalTransporterRegistry.setPerformState(i, PerformConnect);
+ globalTransporterRegistry.do_connect(i);
globalTransporterRegistry.setIOState(i, HaltIO);
signal->theData[0] = EventReport::CommunicationOpened;
@@ -454,34 +456,21 @@ void Cmvmi::execDISCONNECT_REP(Signal *signal)
const NodeInfo::NodeType type = getNodeInfo(hostId).getType();
ndbrequire(type != NodeInfo::INVALID);
- if (globalTransporterRegistry.performState(hostId) != PerformDisconnect) {
+ if(type == NodeInfo::DB || globalData.theStartLevel == NodeState::SL_STARTED){
jam();
-
- // -------------------------------------------------------------------
- // We do not report the disconnection when disconnection is already ongoing.
- // This reporting should be looked into but this secures that we avoid
- // crashes due to too quick re-reporting of disconnection.
- // -------------------------------------------------------------------
- if(type == NodeInfo::DB || globalData.theStartLevel == NodeState::SL_STARTED){
- jam();
- DisconnectRep * const rep = (DisconnectRep *)&signal->theData[0];
- rep->nodeId = hostId;
- rep->err = errNo;
- sendSignal(QMGR_REF, GSN_DISCONNECT_REP, signal,
- DisconnectRep::SignalLength, JBA);
- globalTransporterRegistry.setPerformState(hostId, PerformDisconnect);
- } else if(globalData.theStartLevel == NodeState::SL_CMVMI ||
- globalData.theStartLevel == NodeState::SL_STARTING) {
- /**
- * Someone disconnected during cmvmi period
- */
- if(type == NodeInfo::MGM){
- jam();
- globalTransporterRegistry.setPerformState(hostId, PerformConnect);
- } else {
- globalTransporterRegistry.setPerformState(hostId, PerformDisconnect);
- }
- }
+ DisconnectRep * const rep = (DisconnectRep *)&signal->theData[0];
+ rep->nodeId = hostId;
+ rep->err = errNo;
+ sendSignal(QMGR_REF, GSN_DISCONNECT_REP, signal,
+ DisconnectRep::SignalLength, JBA);
+ } else if((globalData.theStartLevel == NodeState::SL_CMVMI ||
+ globalData.theStartLevel == NodeState::SL_STARTING)
+ && type == NodeInfo::MGM) {
+ /**
+ * Someone disconnected during cmvmi period
+ */
+ jam();
+ globalTransporterRegistry.do_connect(hostId);
}
signal->theData[0] = EventReport::Disconnected;
@@ -491,7 +480,6 @@ void Cmvmi::execDISCONNECT_REP(Signal *signal)
void Cmvmi::execCONNECT_REP(Signal *signal){
const Uint32 hostId = signal->theData[0];
-
jamEntry();
const NodeInfo::NodeType type = (NodeInfo::NodeType)getNodeInfo(hostId).m_type;
@@ -520,7 +508,8 @@ void Cmvmi::execCONNECT_REP(Signal *signal){
/**
* Dont allow api nodes to connect
*/
- globalTransporterRegistry.setPerformState(hostId, PerformDisconnect);
+ abort();
+ globalTransporterRegistry.do_disconnect(hostId);
}
}
@@ -754,8 +743,8 @@ Cmvmi::execSTART_ORD(Signal* signal) {
*/
for(unsigned int i = 1; i < MAX_NODES; i++ ){
if (getNodeInfo(i).m_type == NodeInfo::MGM){
- if(globalTransporterRegistry.performState(i) != PerformIO){
- globalTransporterRegistry.setPerformState(i, PerformConnect);
+ if(!globalTransporterRegistry.is_connected(i)){
+ globalTransporterRegistry.do_connect(i);
globalTransporterRegistry.setIOState(i, NoHalt);
}
}
@@ -781,7 +770,7 @@ Cmvmi::execSTART_ORD(Signal* signal) {
// without any connected nodes.
for(unsigned int i = 1; i < MAX_NODES; i++ ){
if (i != getOwnNodeId() && getNodeInfo(i).m_type != NodeInfo::MGM){
- globalTransporterRegistry.setPerformState(i, PerformDisconnect);
+ globalTransporterRegistry.do_disconnect(i);
globalTransporterRegistry.setIOState(i, HaltIO);
}
}
@@ -1060,29 +1049,10 @@ Cmvmi::execDUMP_STATE_ORD(Signal* signal)
if(nodeTypeStr == 0)
continue;
- const char* actionStr = "";
- switch (globalTransporterRegistry.performState(i)){
- case PerformNothing:
- actionStr = "does nothing";
- break;
- case PerformIO:
- actionStr = "is connected";
- break;
- case PerformConnect:
- actionStr = "is trying to connect";
- break;
- case PerformDisconnect:
- actionStr = "is trying to disconnect";
- break;
- case RemoveTransporter:
- actionStr = "will be removed";
- break;
- }
-
infoEvent("Connection to %d (%s) %s",
i,
nodeTypeStr,
- actionStr);
+ globalTransporterRegistry.getPerformStateString(i));
}
}
@@ -1100,14 +1070,15 @@ Cmvmi::execDUMP_STATE_ORD(Signal* signal)
}
if (dumpState->args[0] == DumpStateOrd::CmvmiTestLongSigWithDelay) {
+ unsigned i;
Uint32 loopCount = dumpState->args[1];
const unsigned len0 = 11;
const unsigned len1 = 123;
Uint32 sec0[len0];
Uint32 sec1[len1];
- for (unsigned i = 0; i < len0; i++)
+ for (i = 0; i < len0; i++)
sec0[i] = i;
- for (unsigned i = 0; i < len1; i++)
+ for (i = 0; i < len1; i++)
sec1[i] = 16 * i;
Uint32* sig = signal->getDataPtrSend();
sig[0] = reference();
@@ -1160,6 +1131,7 @@ static LinearSectionPtr g_test[3];
void
Cmvmi::execTESTSIG(Signal* signal){
+ Uint32 i;
/**
* Test of SafeCounter
*/
@@ -1184,14 +1156,14 @@ Cmvmi::execTESTSIG(Signal* signal){
getOwnNodeId(),
true);
ndbout_c("-- Fixed section --");
- for(Uint32 i = 0; i<signal->length(); i++){
+ for(i = 0; i<signal->length(); i++){
fprintf(stdout, "H'0x%.8x ", signal->theData[i]);
if(((i + 1) % 6) == 0)
fprintf(stdout, "\n");
}
fprintf(stdout, "\n");
- for(Uint32 i = 0; i<signal->header.m_noOfSections; i++){
+ for(i = 0; i<signal->header.m_noOfSections; i++){
SegmentedSectionPtr ptr;
ndbout_c("-- Section %d --", i);
signal->getSection(ptr, i);
@@ -1204,7 +1176,7 @@ Cmvmi::execTESTSIG(Signal* signal){
/**
* Validate length:s
*/
- for(Uint32 i = 0; i<signal->header.m_noOfSections; i++){
+ for(i = 0; i<signal->header.m_noOfSections; i++){
SegmentedSectionPtr ptr;
signal->getSection(ptr, i);
ndbrequire(ptr.p != 0);
@@ -1249,7 +1221,7 @@ Cmvmi::execTESTSIG(Signal* signal){
case 4:{
LinearSectionPtr ptr[3];
const Uint32 secs = signal->getNoOfSections();
- for(Uint32 i = 0; i<secs; i++){
+ for(i = 0; i<secs; i++){
SegmentedSectionPtr sptr;
signal->getSection(sptr, i);
ptr[i].sz = sptr.sz;
@@ -1298,7 +1270,7 @@ Cmvmi::execTESTSIG(Signal* signal){
case 8:{
LinearSectionPtr ptr[3];
const Uint32 secs = signal->getNoOfSections();
- for(Uint32 i = 0; i<secs; i++){
+ for(i = 0; i<secs; i++){
SegmentedSectionPtr sptr;
signal->getSection(sptr, i);
ptr[i].sz = sptr.sz;
@@ -1332,7 +1304,7 @@ Cmvmi::execTESTSIG(Signal* signal){
sendNextLinearFragment(signal, fragSend);
}
- for(Uint32 i = 0; i<secs; i++){
+ for(i = 0; i<secs; i++){
delete[] ptr[i].p;
}
break;
@@ -1364,7 +1336,7 @@ Cmvmi::execTESTSIG(Signal* signal){
const Uint32 secs = signal->getNoOfSections();
memset(g_test, 0, sizeof(g_test));
- for(Uint32 i = 0; i<secs; i++){
+ for(i = 0; i<secs; i++){
SegmentedSectionPtr sptr;
signal->getSection(sptr, i);
g_test[i].sz = sptr.sz;
@@ -1408,7 +1380,7 @@ Cmvmi::execTESTSIG(Signal* signal){
case 14:{
Uint32 count = signal->theData[8];
signal->theData[10] = count * rg.m_nodes.count();
- for(Uint32 i = 0; i<count; i++){
+ for(i = 0; i<count; i++){
sendSignal(rg, GSN_TESTSIG, signal, signal->length(), JBB);
}
return;
diff --git a/ndb/src/kernel/blocks/dbacc/Dbacc.hpp b/ndb/src/kernel/blocks/dbacc/Dbacc.hpp
index 6ba2d083e58..cc3e646f219 100644
--- a/ndb/src/kernel/blocks/dbacc/Dbacc.hpp
+++ b/ndb/src/kernel/blocks/dbacc/Dbacc.hpp
@@ -218,6 +218,7 @@ ndbout << "Ptr: " << ptr.p->word32 << " \tIndex: " << tmp_string << " \tValue: "
#define ZREL_FRAG 6
#define ZREL_DIR 7
#define ZREPORT_MEMORY_USAGE 8
+#define ZLCP_OP_WRITE_RT_BREAK 9
/* ------------------------------------------------------------------------- */
/* ERROR CODES */
@@ -1190,6 +1191,8 @@ private:
void zpagesize_error(const char* where);
void reportMemoryUsage(Signal* signal, int gth);
+ void lcp_write_op_to_undolog(Signal* signal);
+ void reenable_expand_after_redo_log_exection_complete(Signal*);
// Initialisation
@@ -1559,7 +1562,7 @@ private:
Uint32 cexcPrevforward;
Uint32 clocalkey[32];
Uint32 ckeys[2048];
-
+
Uint32 c_errorInsert3000_TableId;
Uint32 cSrUndoRecords[5];
};
diff --git a/ndb/src/kernel/blocks/dbacc/DbaccInit.cpp b/ndb/src/kernel/blocks/dbacc/DbaccInit.cpp
index 90e914987c3..b22fd6ce641 100644
--- a/ndb/src/kernel/blocks/dbacc/DbaccInit.cpp
+++ b/ndb/src/kernel/blocks/dbacc/DbaccInit.cpp
@@ -94,7 +94,8 @@ void Dbacc::initRecords()
page8 = (Page8*)allocRecord("Page8",
sizeof(Page8),
- cpagesize);
+ cpagesize,
+ false);
rootfragmentrec = (Rootfragmentrec*)allocRecord("Rootfragmentrec",
sizeof(Rootfragmentrec),
@@ -114,7 +115,8 @@ void Dbacc::initRecords()
undopage = (Undopage*)allocRecord("Undopage",
sizeof(Undopage),
- cundopagesize);
+ cundopagesize,
+ false);
// Initialize BAT for interface to file system
diff --git a/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp b/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp
index 933ee2cf8e1..9cfac0ad2a2 100644
--- a/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp
+++ b/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp
@@ -46,13 +46,17 @@ Dbacc::remainingUndoPages(){
ndbrequire(HeadPage>=TailPage);
Uint32 UsedPages = HeadPage - TailPage;
- Uint32 Remaining = cundopagesize - UsedPages;
+ Int32 Remaining = cundopagesize - UsedPages;
// There can not be more than cundopagesize remaining
- ndbrequire(Remaining<=cundopagesize);
-
+ if (Remaining <= 0){
+ // No more undolog, crash node
+ progError(__LINE__,
+ ERR_NO_MORE_UNDOLOG,
+ "There are more than 1Mbyte undolog writes outstanding");
+ }
return Remaining;
-}//Dbacc::remainingUndoPages()
+}
void
Dbacc::updateLastUndoPageIdWritten(Signal* signal, Uint32 aNewValue){
@@ -193,6 +197,17 @@ void Dbacc::execCONTINUEB(Signal* signal)
return;
}
+ case ZLCP_OP_WRITE_RT_BREAK:
+ {
+ operationRecPtr.i= signal->theData[1];
+ fragrecptr.i= signal->theData[2];
+ lcpConnectptr.i= signal->theData[3];
+ ptrCheckGuard(operationRecPtr, coprecsize, operationrec);
+ ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
+ ptrCheckGuard(lcpConnectptr, clcpConnectsize, lcpConnectrec);
+ lcp_write_op_to_undolog(signal);
+ return;
+ }
default:
ndbrequire(false);
break;
@@ -742,6 +757,7 @@ void Dbacc::initialiseDirRec(Signal* signal)
DirectoryarrayPtr idrDirptr;
ndbrequire(cdirarraysize > 0);
for (idrDirptr.i = 0; idrDirptr.i < cdirarraysize; idrDirptr.i++) {
+ refresh_watch_dog();
ptrAss(idrDirptr, directoryarray);
for (Uint32 i = 0; i <= 255; i++) {
idrDirptr.p->pagep[i] = RNIL;
@@ -761,6 +777,7 @@ void Dbacc::initialiseDirRangeRec(Signal* signal)
ndbrequire(cdirrangesize > 0);
for (idrDirRangePtr.i = 0; idrDirRangePtr.i < cdirrangesize; idrDirRangePtr.i++) {
+ refresh_watch_dog();
ptrAss(idrDirRangePtr, dirRange);
idrDirRangePtr.p->dirArray[0] = idrDirRangePtr.i + 1;
for (Uint32 i = 1; i < 256; i++) {
@@ -783,6 +800,7 @@ void Dbacc::initialiseFragRec(Signal* signal)
ndbrequire(cfragmentsize > 0);
for (regFragPtr.i = 0; regFragPtr.i < cfragmentsize; regFragPtr.i++) {
jam();
+ refresh_watch_dog();
ptrAss(regFragPtr, fragmentrec);
initFragGeneral(regFragPtr);
regFragPtr.p->nextfreefrag = regFragPtr.i + 1;
@@ -861,6 +879,7 @@ void Dbacc::initialiseOperationRec(Signal* signal)
{
ndbrequire(coprecsize > 0);
for (operationRecPtr.i = 0; operationRecPtr.i < coprecsize; operationRecPtr.i++) {
+ refresh_watch_dog();
ptrAss(operationRecPtr, operationrec);
operationRecPtr.p->transactionstate = IDLE;
operationRecPtr.p->operation = ZUNDEFINED_OP;
@@ -883,6 +902,7 @@ void Dbacc::initialiseOverflowRec(Signal* signal)
ndbrequire(coverflowrecsize > 0);
for (iorOverflowRecPtr.i = 0; iorOverflowRecPtr.i < coverflowrecsize; iorOverflowRecPtr.i++) {
+ refresh_watch_dog();
ptrAss(iorOverflowRecPtr, overflowRecord);
iorOverflowRecPtr.p->nextfreeoverrec = iorOverflowRecPtr.i + 1;
}//for
@@ -943,6 +963,7 @@ void Dbacc::initialiseRootfragRec(Signal* signal)
{
ndbrequire(crootfragmentsize > 0);
for (rootfragrecptr.i = 0; rootfragrecptr.i < crootfragmentsize; rootfragrecptr.i++) {
+ refresh_watch_dog();
ptrAss(rootfragrecptr, rootfragmentrec);
rootfragrecptr.p->nextroot = rootfragrecptr.i + 1;
rootfragrecptr.p->fragmentptr[0] = RNIL;
@@ -998,6 +1019,7 @@ void Dbacc::initialiseTableRec(Signal* signal)
{
ndbrequire(ctablesize > 0);
for (tabptr.i = 0; tabptr.i < ctablesize; tabptr.i++) {
+ refresh_watch_dog();
ptrAss(tabptr, tabrec);
for (Uint32 i = 0; i < NO_OF_FRAG_PER_NODE; i++) {
tabptr.p->fragholder[i] = RNIL;
@@ -2324,13 +2346,14 @@ void Dbacc::execACC_COMMITREQ(Signal* signal)
fragrecptr.p->slack += operationRecPtr.p->insertDeleteLen;
if (fragrecptr.p->slack > fragrecptr.p->slackCheck) { /* TIME FOR JOIN BUCKETS PROCESS */
if (fragrecptr.p->expandCounter > 0) {
- if (fragrecptr.p->expandFlag == 0) {
+ if (fragrecptr.p->expandFlag < 2) {
jam();
- fragrecptr.p->expandFlag = 1;
signal->theData[0] = fragrecptr.i;
signal->theData[1] = fragrecptr.p->p;
signal->theData[2] = fragrecptr.p->maxp;
- sendSignal(cownBlockref, GSN_SHRINKCHECK2, signal, 3, JBB);
+ signal->theData[3] = fragrecptr.p->expandFlag;
+ fragrecptr.p->expandFlag = 2;
+ sendSignal(cownBlockref, GSN_SHRINKCHECK2, signal, 4, JBB);
}//if
}//if
}//if
@@ -2344,7 +2367,7 @@ void Dbacc::execACC_COMMITREQ(Signal* signal)
if (fragrecptr.p->slack >= (Uint32)(1 << 31)) { /* IT MEANS THAT IF SLACK < ZERO */
if (fragrecptr.p->expandFlag == 0) {
jam();
- fragrecptr.p->expandFlag = 1;
+ fragrecptr.p->expandFlag = 2;
signal->theData[0] = fragrecptr.i;
signal->theData[1] = fragrecptr.p->p;
signal->theData[2] = fragrecptr.p->maxp;
@@ -6316,9 +6339,16 @@ Uint32 Dbacc::checkScanExpand(Signal* signal)
void Dbacc::execEXPANDCHECK2(Signal* signal)
{
+ jamEntry();
+
+ if(refToBlock(signal->getSendersBlockRef()) == DBLQH){
+ jam();
+ reenable_expand_after_redo_log_exection_complete(signal);
+ return;
+ }
+
DirectoryarrayPtr newDirptr;
- jamEntry();
fragrecptr.i = signal->theData[0];
tresult = 0; /* 0= FALSE,1= TRUE,> ZLIMIT_OF_ERROR =ERRORCODE */
Uint32 tmp = 1;
@@ -6375,6 +6405,7 @@ void Dbacc::execEXPANDCHECK2(Signal* signal)
return;
}//if
}//if
+
/*--------------------------------------------------------------------------*/
/* WE START BY FINDING THE PAGE, THE PAGE INDEX AND THE PAGE DIRECTORY*/
/* OF THE NEW BUCKET WHICH SHALL RECEIVE THE ELEMENT WHICH HAVE A 1 IN*/
@@ -6428,6 +6459,7 @@ void Dbacc::execEXPANDCHECK2(Signal* signal)
} else {
ptrCheckGuard(expPageptr, cpagesize, page8);
}//if
+
fragrecptr.p->expReceivePageptr = expPageptr.i;
fragrecptr.p->expReceiveIndex = texpReceivedBucket & ((1 << fragrecptr.p->k) - 1);
/*--------------------------------------------------------------------------*/
@@ -6455,7 +6487,7 @@ void Dbacc::execEXPANDCHECK2(Signal* signal)
endofexpLab(signal);
return;
}//Dbacc::execEXPANDCHECK2()
-
+
void Dbacc::endofexpLab(Signal* signal)
{
fragrecptr.p->p++;
@@ -6478,7 +6510,7 @@ void Dbacc::endofexpLab(Signal* signal)
/* IT IS STILL NECESSARY TO EXPAND THE FRAGMENT EVEN MORE. START IT FROM HERE */
/* WITHOUT WAITING FOR NEXT COMMIT ON THE FRAGMENT. */
/* --------------------------------------------------------------------------------- */
- fragrecptr.p->expandFlag = 1;
+ fragrecptr.p->expandFlag = 2;
signal->theData[0] = fragrecptr.i;
signal->theData[1] = fragrecptr.p->p;
signal->theData[2] = fragrecptr.p->maxp;
@@ -6487,6 +6519,47 @@ void Dbacc::endofexpLab(Signal* signal)
return;
}//Dbacc::endofexpLab()
+void Dbacc::reenable_expand_after_redo_log_exection_complete(Signal* signal){
+
+ tabptr.i = signal->theData[0];
+ Uint32 fragId = signal->theData[1];
+
+ ptrCheckGuard(tabptr, ctablesize, tabrec);
+ ndbrequire(getrootfragmentrec(signal, rootfragrecptr, fragId));
+#if 0
+ ndbout_c("reenable expand check for table %d fragment: %d",
+ tabptr.i, fragId);
+#endif
+
+ for (Uint32 i = 0; i < 2; i++) {
+ fragrecptr.i = rootfragrecptr.p->fragmentptr[i];
+ ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
+ switch(fragrecptr.p->expandFlag){
+ case 0:
+ /**
+ * Hmm... this means that it's alreay has been reenabled...
+ */
+ ndbassert(false);
+ continue;
+ case 1:
+ /**
+ * Nothing is going on start expand check
+ */
+ case 2:
+ /**
+ * A shrink is running, do expand check anyway
+ * (to reset expandFlag)
+ */
+ fragrecptr.p->expandFlag = 2;
+ signal->theData[0] = fragrecptr.i;
+ signal->theData[1] = fragrecptr.p->p;
+ signal->theData[2] = fragrecptr.p->maxp;
+ sendSignal(cownBlockref, GSN_EXPANDCHECK2, signal, 3, JBB);
+ break;
+ }
+ }
+}
+
void Dbacc::execDEBUG_SIG(Signal* signal)
{
jamEntry();
@@ -6882,9 +6955,10 @@ void Dbacc::execSHRINKCHECK2(Signal* signal)
jamEntry();
fragrecptr.i = signal->theData[0];
- tresult = 0; /* 0= FALSE,1= TRUE,> ZLIMIT_OF_ERROR =ERRORCODE */
+ Uint32 oldFlag = signal->theData[3];
ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
- fragrecptr.p->expandFlag = 0;
+ fragrecptr.p->expandFlag = oldFlag;
+ tresult = 0; /* 0= FALSE,1= TRUE,> ZLIMIT_OF_ERROR =ERRORCODE */
if (fragrecptr.p->slack <= fragrecptr.p->slackCheck) {
jam();
/* TIME FOR JOIN BUCKETS PROCESS */
@@ -6965,6 +7039,7 @@ void Dbacc::execSHRINKCHECK2(Signal* signal)
jam();
fragrecptr.p->p--;
}//if
+
/*--------------------------------------------------------------------------*/
/* WE START BY FINDING THE NECESSARY INFORMATION OF THE BUCKET TO BE */
/* REMOVED WHICH WILL SEND ITS ELEMENTS TO THE RECEIVING BUCKET. */
@@ -7157,11 +7232,13 @@ void Dbacc::endofshrinkbucketLab(Signal* signal)
/* SHRINKING BELOW 2^K - 1 (NOW 63). THIS WAS A BUG THAT */
/* WAS REMOVED 2000-05-12. */
/*--------------------------------------------------------------*/
- fragrecptr.p->expandFlag = 1;
signal->theData[0] = fragrecptr.i;
signal->theData[1] = fragrecptr.p->p;
signal->theData[2] = fragrecptr.p->maxp;
- sendSignal(cownBlockref, GSN_SHRINKCHECK2, signal, 3, JBB);
+ signal->theData[3] = fragrecptr.p->expandFlag;
+ ndbrequire(fragrecptr.p->expandFlag < 2);
+ fragrecptr.p->expandFlag = 2;
+ sendSignal(cownBlockref, GSN_SHRINKCHECK2, signal, 4, JBB);
}//if
}//if
}//if
@@ -7697,32 +7774,70 @@ void Dbacc::execACC_LCPREQ(Signal* signal)
fragrecptr.p->lcpMaxOverDirIndex = fragrecptr.p->lastOverIndex;
fragrecptr.p->createLcp = ZTRUE;
operationRecPtr.i = fragrecptr.p->lockOwnersList;
- while (operationRecPtr.i != RNIL) {
+ lcp_write_op_to_undolog(signal);
+}
+
+void
+Dbacc::lcp_write_op_to_undolog(Signal* signal)
+{
+ bool delay_continueb= false;
+ Uint32 i, j;
+ for (i= 0; i < 16; i++) {
jam();
- ptrCheckGuard(operationRecPtr, coprecsize, operationrec);
+ if (remainingUndoPages() <= ZMIN_UNDO_PAGES_AT_COMMIT) {
+ jam();
+ delay_continueb= true;
+ break;
+ }
+ for (j= 0; j < 32; j++) {
+ if (operationRecPtr.i == RNIL) {
+ jam();
+ break;
+ }
+ jam();
+ ptrCheckGuard(operationRecPtr, coprecsize, operationrec);
- if ((operationRecPtr.p->operation == ZINSERT) ||
- (operationRecPtr.p->elementIsDisappeared == ZTRUE)){
+ if ((operationRecPtr.p->operation == ZINSERT) ||
+ (operationRecPtr.p->elementIsDisappeared == ZTRUE)){
/*******************************************************************
* Only log inserts and elements that are marked as dissapeared.
* All other operations update the element header and that is handled
* when pages are written to disk
********************************************************************/
- undopageptr.i = (cundoposition>>ZUNDOPAGEINDEXBITS) & (cundopagesize-1);
- ptrAss(undopageptr, undopage);
- theadundoindex = cundoposition & ZUNDOPAGEINDEX_MASK;
- tundoindex = theadundoindex + ZUNDOHEADSIZE;
-
- writeUndoOpInfo(signal);/* THE INFORMATION ABOUT ELEMENT HEADER, STORED*/
- /* IN OP REC, IS WRITTEN AT UNDO PAGES */
- cundoElemIndex = 0;/* DEFAULT VALUE USED BY WRITE_UNDO_HEADER SUBROTINE */
- writeUndoHeader(signal, RNIL, UndoHeader::ZOP_INFO); /* WRITE THE HEAD OF THE UNDO ELEMENT */
- checkUndoPages(signal); /* SEND UNDO PAGE TO DISK WHEN A GROUP OF */
- /* UNDO PAGES,CURRENTLY 8, IS FILLED */
- }//if
+ undopageptr.i = (cundoposition>>ZUNDOPAGEINDEXBITS) & (cundopagesize-1);
+ ptrAss(undopageptr, undopage);
+ theadundoindex = cundoposition & ZUNDOPAGEINDEX_MASK;
+ tundoindex = theadundoindex + ZUNDOHEADSIZE;
- operationRecPtr.i = operationRecPtr.p->nextLockOwnerOp;
- }//while
+ writeUndoOpInfo(signal);/* THE INFORMATION ABOUT ELEMENT HEADER, STORED*/
+ /* IN OP REC, IS WRITTEN AT UNDO PAGES */
+ cundoElemIndex = 0;/* DEFAULT VALUE USED BY WRITE_UNDO_HEADER SUBROTINE */
+ writeUndoHeader(signal, RNIL, UndoHeader::ZOP_INFO); /* WRITE THE HEAD OF THE UNDO ELEMENT */
+ checkUndoPages(signal); /* SEND UNDO PAGE TO DISK WHEN A GROUP OF */
+ /* UNDO PAGES,CURRENTLY 8, IS FILLED */
+ }
+ operationRecPtr.i = operationRecPtr.p->nextLockOwnerOp;
+ }
+ if (operationRecPtr.i == RNIL) {
+ jam();
+ break;
+ }
+ }
+ if (operationRecPtr.i != RNIL) {
+ jam();
+ signal->theData[0]= ZLCP_OP_WRITE_RT_BREAK;
+ signal->theData[1]= operationRecPtr.i;
+ signal->theData[2]= fragrecptr.i;
+ signal->theData[3]= lcpConnectptr.i;
+ if (delay_continueb) {
+ jam();
+ sendSignalWithDelay(cownBlockref, GSN_CONTINUEB, signal, 10, 4);
+ } else {
+ jam();
+ sendSignal(cownBlockref, GSN_CONTINUEB, signal, 4, JBB);
+ }
+ return;
+ }
signal->theData[0] = fragrecptr.p->lcpLqhPtr;
sendSignal(lcpConnectptr.p->lcpUserblockref, GSN_ACC_LCPSTARTED,
@@ -7735,8 +7850,7 @@ void Dbacc::execACC_LCPREQ(Signal* signal)
signal->theData[0] = lcpConnectptr.i;
signal->theData[1] = fragrecptr.i;
sendSignal(cownBlockref, GSN_ACC_SAVE_PAGES, signal, 2, JBB);
- return;
-}//Dbacc::execACC_LCPREQ()
+}
/* ******************--------------------------------------------------------------- */
/* ACC_SAVE_PAGES A GROUP OF PAGES IS ALLOCATED. THE PAGES AND OVERFLOW */
@@ -8595,12 +8709,6 @@ void Dbacc::checkUndoPages(Signal* signal)
* RECORDS IN
*/
Uint16 nextUndoPageId = tundoPageId + 1;
- if (nextUndoPageId > (clastUndoPageIdWritten + cundopagesize)){
- // No more undolog, crash node
- progError(__LINE__,
- ERR_NO_MORE_UNDOLOG,
- "There are more than 1Mbyte undolog writes outstanding");
- }
updateUndoPositionPage(signal, nextUndoPageId << ZUNDOPAGEINDEXBITS);
if ((tundoPageId & (ZWRITE_UNDOPAGESIZE - 1)) == (ZWRITE_UNDOPAGESIZE - 1)) {
@@ -9146,7 +9254,14 @@ void Dbacc::initFragAdd(Signal* signal,
ndbrequire(req->kValue == 6);
regFragPtr.p->k = req->kValue; /* TK_SIZE = 6 IN THIS VERSION */
regFragPtr.p->expandCounter = 0;
- regFragPtr.p->expandFlag = 0;
+
+ /**
+ * Only allow shrink during SR
+ * - to make sure we don't run out of pages during REDO log execution
+ *
+ * Is later restored to 0 by LQH at end of REDO log execution
+ */
+ regFragPtr.p->expandFlag = (getNodeState().getSystemRestartInProgress()?1:0);
regFragPtr.p->p = 0;
regFragPtr.p->maxp = (1 << req->kValue) - 1;
regFragPtr.p->minloadfactor = minLoadFactor;
@@ -9199,8 +9314,8 @@ void Dbacc::initFragGeneral(FragmentrecPtr regFragPtr)
for (Uint32 i = 0; i < ZWRITEPAGESIZE; i++) {
regFragPtr.p->datapages[i] = RNIL;
}//for
- for (Uint32 i = 0; i < 4; i++) {
- regFragPtr.p->longKeyPageArray[i] = RNIL;
+ for (Uint32 j = 0; j < 4; j++) {
+ regFragPtr.p->longKeyPageArray[j] = RNIL;
}//for
}//Dbacc::initFragGeneral()
diff --git a/ndb/src/kernel/blocks/dbdict/Dbdict.cpp b/ndb/src/kernel/blocks/dbdict/Dbdict.cpp
index 2ef9e721e22..7126842459e 100644
--- a/ndb/src/kernel/blocks/dbdict/Dbdict.cpp
+++ b/ndb/src/kernel/blocks/dbdict/Dbdict.cpp
@@ -75,7 +75,6 @@
#include <signaldata/AlterTab.hpp>
#include <signaldata/CreateFragmentation.hpp>
#include <signaldata/CreateTab.hpp>
-#include "../dbtc/Dbtc.hpp"
#include <NdbSleep.h>
#define ZNOT_FOUND 626
@@ -254,6 +253,7 @@ Dbdict::packTableIntoPagesImpl(SimpleProperties::Writer & w,
w.add(DictTabInfo::FragmentTypeVal, tablePtr.p->fragmentType);
w.add(DictTabInfo::FragmentKeyTypeVal, tablePtr.p->fragmentKeyType);
w.add(DictTabInfo::TableTypeVal, tablePtr.p->tableType);
+ w.add(DictTabInfo::FragmentCount, tablePtr.p->fragmentCount);
if (tablePtr.p->primaryTableId != RNIL){
TableRecordPtr primTab;
@@ -1313,6 +1313,7 @@ void Dbdict::initTableRecords()
TableRecordPtr tablePtr;
while (1) {
jam();
+ refresh_watch_dog();
c_tableRecordPool.seize(tablePtr);
if (tablePtr.i == RNIL) {
jam();
@@ -1373,6 +1374,7 @@ void Dbdict::initTriggerRecords()
TriggerRecordPtr triggerPtr;
while (1) {
jam();
+ refresh_watch_dog();
c_triggerRecordPool.seize(triggerPtr);
if (triggerPtr.i == RNIL) {
jam();
@@ -3599,30 +3601,37 @@ Dbdict::execCREATE_FRAGMENTATION_CONF(Signal* signal){
SegmentedSectionPtr fragDataPtr;
signal->getSection(fragDataPtr, CreateFragmentationConf::FRAGMENTS);
-
signal->header.m_noOfSections = 0;
/**
- * Correct table
+ * Get table
*/
TableRecordPtr tabPtr;
c_tableRecordPool.getPtr(tabPtr, createTabPtr.p->m_tablePtrI);
+ /**
+ * Save fragment count
+ */
+ tabPtr.p->fragmentCount = conf->noOfFragments;
+
+ /**
+ * Update table version
+ */
PageRecordPtr pagePtr;
c_pageRecordArray.getPtr(pagePtr, c_schemaRecord.schemaPage);
SchemaFile::TableEntry * tabEntry = getTableEntry(pagePtr.p, tabPtr.i);
+ tabPtr.p->tableVersion = tabEntry->m_tableVersion + 1;
+
/**
- * Update table version
+ * Pack
*/
- tabPtr.p->tableVersion = tabEntry->m_tableVersion + 1;
-
SimplePropertiesSectionWriter w(getSectionSegmentPool());
packTableIntoPagesImpl(w, tabPtr);
SegmentedSectionPtr spDataPtr;
w.getPtr(spDataPtr);
-
+
signal->setSection(spDataPtr, CreateTabReq::DICT_TAB_INFO);
signal->setSection(fragDataPtr, CreateTabReq::FRAGMENTATION);
@@ -3749,6 +3758,10 @@ Dbdict::createTab_reply(Signal* signal,
ref->senderRef = reference();
ref->senderData = createTabPtr.p->m_senderData;
ref->errorCode = createTabPtr.p->m_errorCode;
+ ref->masterNodeId = c_masterNodeId;
+ ref->status = 0;
+ ref->errorKey = 0;
+ ref->errorLine = 0;
//@todo check api failed
sendSignal(createTabPtr.p->m_senderRef, GSN_CREATE_TABLE_REF, signal,
@@ -4252,7 +4265,9 @@ Dbdict::execDIADDTABCONF(Signal* signal){
/**
* No local fragment (i.e. no LQHFRAGREQ)
*/
- sendSignal(DBDIH_REF, GSN_TAB_COMMITREQ, signal, 3, JBB);
+ execute(signal, createTabPtr.p->m_callback, 0);
+ return;
+ //sendSignal(DBDIH_REF, GSN_TAB_COMMITREQ, signal, 3, JBB);
}
}
@@ -4637,6 +4652,7 @@ void Dbdict::handleTabInfoInit(SimpleProperties::Reader & it,
tablePtr.p->fragmentKeyType = (DictTabInfo::FragmentKeyType)tableDesc.FragmentKeyType;
tablePtr.p->tableType = (DictTabInfo::TableType)tableDesc.TableType;
tablePtr.p->kValue = tableDesc.TableKValue;
+ tablePtr.p->fragmentCount = tableDesc.FragmentCount;
tablePtr.p->frmLen = tableDesc.FrmLen;
memcpy(tablePtr.p->frmData, tableDesc.FrmData, tableDesc.FrmLen);
@@ -5080,8 +5096,20 @@ Dbdict::execPREP_DROP_TAB_REF(Signal* signal){
Uint32 nodeId = refToNode(prep->senderRef);
dropTabPtr.p->m_coordinatorData.m_signalCounter.clearWaitingFor(nodeId);
-
- dropTabPtr.p->setErrorCode((Uint32)prep->errorCode);
+
+ Uint32 block = refToBlock(prep->senderRef);
+ if((prep->errorCode == PrepDropTabRef::NoSuchTable && block == DBLQH) ||
+ (prep->errorCode == PrepDropTabRef::NF_FakeErrorREF)){
+ jam();
+ /**
+ * Ignore errors:
+ * 1) no such table and LQH, it might not exists in different LQH's
+ * 2) node failure...
+ */
+ } else {
+ dropTabPtr.p->setErrorCode((Uint32)prep->errorCode);
+ }
+
if(!dropTabPtr.p->m_coordinatorData.m_signalCounter.done()){
jam();
return;
@@ -5112,6 +5140,19 @@ void
Dbdict::execDROP_TAB_REF(Signal* signal){
jamEntry();
+ DropTabRef * const req = (DropTabRef*)signal->getDataPtr();
+
+ Uint32 block = refToBlock(req->senderRef);
+ ndbrequire(req->errorCode == DropTabRef::NF_FakeErrorREF ||
+ (req->errorCode == DropTabRef::NoSuchTable &&
+ (block == DBTUP || block == DBACC || block == DBLQH)));
+
+ if(block != DBDICT){
+ jam();
+ ndbrequire(refToNode(req->senderRef) == getOwnNodeId());
+ dropTab_localDROP_TAB_CONF(signal);
+ return;
+ }
ndbrequire(false);
}
@@ -5619,7 +5660,7 @@ void Dbdict::execGET_TABINFOREQ(Signal* signal)
signal->getSection(ssPtr,GetTabInfoReq::TABLE_NAME);
SimplePropertiesSectionReader r0(ssPtr, getSectionSegmentPool());
r0.reset(); // undo implicit first()
- if(r0.getWords((Uint32*)tableName, len))
+ if(r0.getWords((Uint32*)tableName, ((len + 3)/4)))
memcpy(keyRecord.tableName, tableName, len);
else {
jam();
@@ -5734,6 +5775,7 @@ void
Dbdict::execLIST_TABLES_REQ(Signal* signal)
{
jamEntry();
+ Uint32 i;
ListTablesReq * req = (ListTablesReq*)signal->getDataPtr();
Uint32 senderRef = req->senderRef;
Uint32 senderData = req->senderData;
@@ -5747,7 +5789,7 @@ Dbdict::execLIST_TABLES_REQ(Signal* signal)
conf->senderData = senderData;
conf->counter = 0;
Uint32 pos = 0;
- for (Uint32 i = 0; i < c_tableRecordPool.getSize(); i++) {
+ for (i = 0; i < c_tableRecordPool.getSize(); i++) {
TableRecordPtr tablePtr;
c_tableRecordPool.getPtr(tablePtr, i);
// filter
@@ -5827,12 +5869,12 @@ Dbdict::execLIST_TABLES_REQ(Signal* signal)
conf->counter++;
pos = 0;
}
- Uint32 i = 0;
- while (i < size) {
+ Uint32 k = 0;
+ while (k < size) {
char* p = (char*)&conf->tableData[pos];
for (Uint32 j = 0; j < 4; j++) {
- if (i < size)
- *p++ = tablePtr.p->tableName[i++];
+ if (k < size)
+ *p++ = tablePtr.p->tableName[k++];
else
*p++ = 0;
}
@@ -5846,7 +5888,7 @@ Dbdict::execLIST_TABLES_REQ(Signal* signal)
}
}
// XXX merge with above somehow
- for (Uint32 i = 0; i < c_triggerRecordPool.getSize(); i++) {
+ for (i = 0; i < c_triggerRecordPool.getSize(); i++) {
if (reqListIndexes)
break;
TriggerRecordPtr triggerPtr;
@@ -5890,12 +5932,12 @@ Dbdict::execLIST_TABLES_REQ(Signal* signal)
conf->counter++;
pos = 0;
}
- Uint32 i = 0;
- while (i < size) {
+ Uint32 k = 0;
+ while (k < size) {
char* p = (char*)&conf->tableData[pos];
for (Uint32 j = 0; j < 4; j++) {
- if (i < size)
- *p++ = triggerPtr.p->triggerName[i++];
+ if (k < size)
+ *p++ = triggerPtr.p->triggerName[k++];
else
*p++ = 0;
}
@@ -6132,6 +6174,7 @@ Dbdict::createIndex_slavePrepare(Signal* signal, OpCreateIndexPtr opPtr)
void
Dbdict::createIndex_toCreateTable(Signal* signal, OpCreateIndexPtr opPtr)
{
+ Uint32 k;
jam();
const CreateIndxReq* const req = &opPtr.p->m_request;
// signal data writer
@@ -6201,7 +6244,7 @@ Dbdict::createIndex_toCreateTable(Signal* signal, OpCreateIndexPtr opPtr)
}
// hash index attributes must currently be in table order
Uint32 prevAttrId = RNIL;
- for (Uint32 k = 0; k < opPtr.p->m_attrList.sz; k++) {
+ for (k = 0; k < opPtr.p->m_attrList.sz; k++) {
jam();
bool found = false;
for (Uint32 tAttr = tablePtr.p->firstAttribute; tAttr != RNIL; ) {
@@ -6212,16 +6255,6 @@ Dbdict::createIndex_toCreateTable(Signal* signal, OpCreateIndexPtr opPtr)
jam();
found = true;
const Uint32 a = aRec->attributeDescriptor;
- bool isNullable = AttributeDescriptor::getNullable(a);
- // We do not allow more than one NULLable attribute for hash index
- if (isNullable &&
- indexPtr.p->isHashIndex() &&
- (opPtr.p->m_attrList.sz > 1)) {
- jam();
- opPtr.p->m_errorCode = CreateIndxRef::AttributeNullable;
- opPtr.p->m_errorLine = __LINE__;
- return;
- }
if (indexPtr.p->isHashIndex()) {
const Uint32 s1 = AttributeDescriptor::getSize(a);
const Uint32 s2 = AttributeDescriptor::getArraySize(a);
@@ -6261,7 +6294,7 @@ Dbdict::createIndex_toCreateTable(Signal* signal, OpCreateIndexPtr opPtr)
// write index key attributes
AttributeRecordPtr aRecPtr;
c_attributeRecordPool.getPtr(aRecPtr, tablePtr.p->firstAttribute);
- for (Uint32 k = 0; k < opPtr.p->m_attrList.sz; k++) {
+ for (k = 0; k < opPtr.p->m_attrList.sz; k++) {
jam();
for (Uint32 tAttr = tablePtr.p->firstAttribute; tAttr != RNIL; ) {
AttributeRecord* aRec = c_attributeRecordPool.getPtr(tAttr);
diff --git a/ndb/src/kernel/blocks/dbdict/Dbdict.hpp b/ndb/src/kernel/blocks/dbdict/Dbdict.hpp
index 68214785234..de1d9757b2a 100644
--- a/ndb/src/kernel/blocks/dbdict/Dbdict.hpp
+++ b/ndb/src/kernel/blocks/dbdict/Dbdict.hpp
@@ -230,7 +230,7 @@ public:
Uint32 frmLen;
char frmData[MAX_FRM_DATA_SIZE];
-
+ Uint32 fragmentCount;
};
typedef Ptr<TableRecord> TableRecordPtr;
diff --git a/ndb/src/kernel/blocks/dbdih/Dbdih.hpp b/ndb/src/kernel/blocks/dbdih/Dbdih.hpp
index e029af70574..14fa262f871 100644
--- a/ndb/src/kernel/blocks/dbdih/Dbdih.hpp
+++ b/ndb/src/kernel/blocks/dbdih/Dbdih.hpp
@@ -269,7 +269,7 @@ public:
};
struct NodeRecord {
- NodeRecord() { m_nodefailSteps.clear();}
+ NodeRecord();
enum NodeStatus {
NOT_IN_CLUSTER = 0,
@@ -943,6 +943,7 @@ private:
void ndbStartReqLab(Signal *, BlockReference ref);
void nodeRestartStartRecConfLab(Signal *);
void dihCopyCompletedLab(Signal *);
+ void release_connect(ConnectRecordPtr ptr);
void copyTableNode(Signal *,
CopyTableNode* ctn,
NodeRecordPtr regNodePtr);
@@ -1127,7 +1128,6 @@ private:
void setAllowNodeStart(Uint32 nodeId, bool newState);
bool getNodeCopyCompleted(Uint32 nodeId);
void setNodeCopyCompleted(Uint32 nodeId, bool newState);
- void initNodeState(NodeRecordPtr regNodePtr);
bool checkNodeAlive(Uint32 nodeId);
// Initialisation
diff --git a/ndb/src/kernel/blocks/dbdih/DbdihInit.cpp b/ndb/src/kernel/blocks/dbdih/DbdihInit.cpp
index df47237ae59..7ca45ef4b43 100644
--- a/ndb/src/kernel/blocks/dbdih/DbdihInit.cpp
+++ b/ndb/src/kernel/blocks/dbdih/DbdihInit.cpp
@@ -50,17 +50,18 @@ void Dbdih::initData()
nodeRecord = (NodeRecord*)
allocRecord("NodeRecord", sizeof(NodeRecord), MAX_NDB_NODES);
- for(Uint32 i = 0; i<MAX_NDB_NODES; i++){
+ Uint32 i;
+ for(i = 0; i<MAX_NDB_NODES; i++){
new (&nodeRecord[i]) NodeRecord();
}
takeOverRecord = (TakeOverRecord*)allocRecord("TakeOverRecord",
sizeof(TakeOverRecord),
MAX_NDB_NODES);
- for(Uint32 i = 0; i<MAX_NDB_NODES; i++)
+ for(i = 0; i<MAX_NDB_NODES; i++)
new (&takeOverRecord[i]) TakeOverRecord();
- for(Uint32 i = 0; i<MAX_NDB_NODES; i++)
+ for(i = 0; i<MAX_NDB_NODES; i++)
new (&takeOverRecord[i]) TakeOverRecord();
waitGCPProxyPool.setSize(ZPROXY_FILE_SIZE);
@@ -254,6 +255,7 @@ Dbdih::Dbdih(const class Configuration & config):
addRecSignal(GSN_UPDATE_TOCONF, &Dbdih::execUPDATE_TOCONF);
addRecSignal(GSN_PREP_DROP_TAB_REQ, &Dbdih::execPREP_DROP_TAB_REQ);
+ addRecSignal(GSN_WAIT_DROP_TAB_REF, &Dbdih::execWAIT_DROP_TAB_REF);
addRecSignal(GSN_WAIT_DROP_TAB_CONF, &Dbdih::execWAIT_DROP_TAB_CONF);
addRecSignal(GSN_DROP_TAB_REQ, &Dbdih::execDROP_TAB_REQ);
diff --git a/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp b/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp
index 0ce1f1e4bbe..0a8abe59aed 100644
--- a/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp
+++ b/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp
@@ -1401,6 +1401,7 @@ void Dbdih::ndbStartReqLab(Signal* signal, BlockReference ref)
void Dbdih::execREAD_NODESCONF(Signal* signal)
{
+ unsigned i;
ReadNodesConf * const readNodes = (ReadNodesConf *)&signal->theData[0];
jamEntry();
Uint32 nodeArray[MAX_NDB_NODES];
@@ -1408,9 +1409,10 @@ void Dbdih::execREAD_NODESCONF(Signal* signal)
csystemnodes = readNodes->noOfNodes;
cmasterNodeId = readNodes->masterNodeId;
int index = 0;
- for (unsigned i = 1; i < MAX_NDB_NODES; i++){
+ NdbNodeBitmask tmp; tmp.assign(2, readNodes->allNodes);
+ for (i = 1; i < MAX_NDB_NODES; i++){
jam();
- if(NodeBitmask::get(readNodes->allNodes, i)){
+ if(tmp.get(i)){
jam();
nodeArray[index] = i;
if(NodeBitmask::get(readNodes->inactiveNodes, i) == false){
@@ -1420,6 +1422,32 @@ void Dbdih::execREAD_NODESCONF(Signal* signal)
index++;
}//if
}//for
+
+ if(cstarttype == NodeState::ST_SYSTEM_RESTART ||
+ cstarttype == NodeState::ST_NODE_RESTART){
+
+ for(i = 1; i<MAX_NDB_NODES; i++){
+ const Uint32 stat = Sysfile::getNodeStatus(i, SYSFILE->nodeStatus);
+ if(stat == Sysfile::NS_NotDefined && !tmp.get(i)){
+ jam();
+ continue;
+ }
+
+ if(tmp.get(i) && stat != Sysfile::NS_NotDefined){
+ jam();
+ continue;
+ }
+ char buf[255];
+ snprintf(buf, sizeof(buf),
+ "Illegal configuration change."
+ " Initial start needs to be performed "
+ " when changing no of storage nodes (node %d)", i);
+ progError(__LINE__,
+ ERR_INVALID_CONFIG,
+ buf);
+ }
+ }
+
ndbrequire(csystemnodes >= 1 && csystemnodes < MAX_NDB_NODES);
if (cstarttype == NodeState::ST_INITIAL_START) {
jam();
@@ -1534,11 +1562,12 @@ void Dbdih::execSTART_MECONF(Signal* signal)
StartMeConf * const startMe = (StartMeConf *)&signal->theData[0];
Uint32 nodeId = startMe->startingNodeId;
const Uint32 startWord = startMe->startWord;
+ Uint32 i;
CRASH_INSERTION(7130);
ndbrequire(nodeId == cownNodeId);
arrGuard(startWord + StartMeConf::DATA_SIZE, sizeof(cdata)/4);
- for(Uint32 i = 0; i < StartMeConf::DATA_SIZE; i++)
+ for(i = 0; i < StartMeConf::DATA_SIZE; i++)
cdata[startWord+i] = startMe->data[i];
if(startWord + StartMeConf::DATA_SIZE < Sysfile::SYSFILE_SIZE32){
@@ -1556,12 +1585,12 @@ void Dbdih::execSTART_MECONF(Signal* signal)
* But dont copy lastCompletedGCI:s
*/
Uint32 tempGCP[MAX_NDB_NODES];
- for(Uint32 i = 0; i < MAX_NDB_NODES; i++)
+ for(i = 0; i < MAX_NDB_NODES; i++)
tempGCP[i] = SYSFILE->lastCompletedGCI[i];
- for(Uint32 i = 0; i < Sysfile::SYSFILE_SIZE32; i++)
+ for(i = 0; i < Sysfile::SYSFILE_SIZE32; i++)
sysfileData[i] = cdata[i];
- for(Uint32 i = 0; i < MAX_NDB_NODES; i++)
+ for(i = 0; i < MAX_NDB_NODES; i++)
SYSFILE->lastCompletedGCI[i] = tempGCP[i];
setNodeActiveStatus();
@@ -1981,9 +2010,11 @@ void Dbdih::execSTART_INFOREQ(Signal* signal)
(ERROR_INSERTED(7124))) {
jam();
StartInfoRef *const ref =(StartInfoRef*)&signal->theData[0];
+ ref->startingNodeId = startNode;
ref->sendingNodeId = cownNodeId;
ref->errorCode = ZNODE_START_DISALLOWED_ERROR;
- sendSignal(cmasterdihref, GSN_START_INFOREF, signal, 2, JBB);
+ sendSignal(cmasterdihref, GSN_START_INFOREF, signal,
+ StartInfoRef::SignalLength, JBB);
return;
}//if
setNodeStatus(startNode, NodeRecord::STARTING);
@@ -2053,7 +2084,7 @@ void Dbdih::execINCL_NODEREQ(Signal* signal)
Sysfile::ActiveStatus TsaveState = nodePtr.p->activeStatus;
Uint32 TnodeGroup = nodePtr.p->nodeGroup;
- initNodeState(nodePtr);
+ new (nodePtr.p) NodeRecord();
nodePtr.p->nodeGroup = TnodeGroup;
nodePtr.p->activeStatus = TsaveState;
nodePtr.p->nodeStatus = NodeRecord::ALIVE;
@@ -3448,10 +3479,37 @@ void Dbdih::selectMasterCandidateAndSend(Signal* signal)
}//if
}//for
ndbrequire(masterCandidateId != 0);
+ setNodeGroups();
signal->theData[0] = masterCandidateId;
signal->theData[1] = gci;
sendSignal(cntrlblockref, GSN_DIH_RESTARTCONF, signal, 2, JBB);
- setNodeGroups();
+
+ Uint32 node_groups[MAX_NDB_NODES];
+ memset(node_groups, 0, sizeof(node_groups));
+ for (nodePtr.i = 1; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) {
+ jam();
+ const Uint32 ng = Sysfile::getNodeGroup(nodePtr.i, SYSFILE->nodeGroups);
+ if(ng != NO_NODE_GROUP_ID){
+ ndbrequire(ng < MAX_NDB_NODES);
+ node_groups[ng]++;
+ }
+ }
+
+ for (nodePtr.i = 0; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) {
+ jam();
+ Uint32 count = node_groups[nodePtr.i];
+ if(count != 0 && count != cnoReplicas){
+ char buf[255];
+ snprintf(buf, sizeof(buf),
+ "Illegal configuration change."
+ " Initial start needs to be performed "
+ " when changing no of replicas (%d != %d)",
+ node_groups[nodePtr.i], cnoReplicas);
+ progError(__LINE__,
+ ERR_INVALID_CONFIG,
+ buf);
+ }
+ }
}//Dbdih::selectMasterCandidate()
/* ------------------------------------------------------------------------- */
@@ -3599,6 +3657,7 @@ void Dbdih::writeInitGcpLab(Signal* signal, FileRecordPtr filePtr)
/*---------------------------------------------------------------------------*/
void Dbdih::execNODE_FAILREP(Signal* signal)
{
+ Uint32 i;
Uint32 failedNodes[MAX_NDB_NODES];
jamEntry();
NodeFailRep * const nodeFail = (NodeFailRep *)&signal->theData[0];
@@ -3611,7 +3670,7 @@ void Dbdih::execNODE_FAILREP(Signal* signal)
// The first step is to convert from a bit mask to an array of failed nodes.
/*-------------------------------------------------------------------------*/
Uint32 index = 0;
- for (Uint32 i = 1; i < MAX_NDB_NODES; i++) {
+ for (i = 1; i < MAX_NDB_NODES; i++) {
jam();
if(NodeBitmask::get(nodeFail->theNodes, i)){
jam();
@@ -3629,7 +3688,7 @@ void Dbdih::execNODE_FAILREP(Signal* signal)
// We also set certain state variables ensuring that the node no longer is
// used in transactions and also mark that we received this signal.
/*-------------------------------------------------------------------------*/
- for (Uint32 i = 0; i < noOfFailedNodes; i++) {
+ for (i = 0; i < noOfFailedNodes; i++) {
jam();
NodeRecordPtr TNodePtr;
TNodePtr.i = failedNodes[i];
@@ -3671,7 +3730,7 @@ void Dbdih::execNODE_FAILREP(Signal* signal)
const bool masterTakeOver = (oldMasterId != newMasterId);
- for(Uint32 i = 0; i < noOfFailedNodes; i++) {
+ for(i = 0; i < noOfFailedNodes; i++) {
NodeRecordPtr failedNodePtr;
failedNodePtr.i = failedNodes[i];
ptrCheckGuard(failedNodePtr, MAX_NDB_NODES, nodeRecord);
@@ -6071,13 +6130,9 @@ void Dbdih::execDIRELEASEREQ(Signal* signal)
ptrCheckGuard(connectPtr, cconnectFileSize, connectRecord);
ndbrequire(connectPtr.p->connectState != ConnectRecord::FREE);
ndbrequire(connectPtr.p->userblockref == userRef);
- connectPtr.p->connectState = ConnectRecord::FREE;
signal->theData[0] = connectPtr.p->userpointer;
sendSignal(connectPtr.p->userblockref, GSN_DIRELEASECONF, signal, 1, JBB);
- connectPtr.p->nfConnect = cfirstconnect;
- cfirstconnect = connectPtr.i;
- connectPtr.p->userblockref = ZNIL;
- connectPtr.p->userpointer = RNIL;
+ release_connect(connectPtr);
}//Dbdih::execDIRELEASEREQ()
/*
@@ -6514,11 +6569,16 @@ Dbdih::sendAddFragreq(Signal* signal, ConnectRecordPtr connectPtr,
DiAddTabConf::SignalLength, JBB);
// Release
- connectPtr.p->userblockref = ZNIL;
- connectPtr.p->userpointer = RNIL;
- connectPtr.p->connectState = ConnectRecord::FREE;
- connectPtr.p->nfConnect = cfirstconnect;
- cfirstconnect = connectPtr.i;
+ release_connect(connectPtr);
+}
+void
+Dbdih::release_connect(ConnectRecordPtr ptr)
+{
+ ptr.p->userblockref = ZNIL;
+ ptr.p->userpointer = RNIL;
+ ptr.p->connectState = ConnectRecord::FREE;
+ ptr.p->nfConnect = cfirstconnect;
+ cfirstconnect = ptr.i;
}
void
@@ -6555,11 +6615,7 @@ Dbdih::execADD_FRAGREF(Signal* signal){
}
// Release
- connectPtr.p->userblockref = ZNIL;
- connectPtr.p->userpointer = RNIL;
- connectPtr.p->connectState = ConnectRecord::FREE;
- connectPtr.p->nfConnect = cfirstconnect;
- cfirstconnect = connectPtr.i;
+ release_connect(connectPtr);
}
/*
@@ -6568,10 +6624,10 @@ Dbdih::execADD_FRAGREF(Signal* signal){
*/
void Dbdih::addtabrefuseLab(Signal* signal, ConnectRecordPtr connectPtr, Uint32 errorCode)
{
- connectPtr.p->connectState = ConnectRecord::INUSE;
signal->theData[0] = connectPtr.p->userpointer;
signal->theData[1] = errorCode;
sendSignal(connectPtr.p->userblockref, GSN_DIADDTABREF, signal, 2, JBB);
+ release_connect(connectPtr);
return;
}//Dbdih::addtabrefuseLab()
@@ -6882,8 +6938,9 @@ void Dbdih::releaseFragments(TabRecordPtr tabPtr)
void Dbdih::initialiseFragstore()
{
+ Uint32 i;
FragmentstorePtr fragPtr;
- for (Uint32 i = 0; i < cfragstoreFileSize; i++) {
+ for (i = 0; i < cfragstoreFileSize; i++) {
fragPtr.i = i;
ptrCheckGuard(fragPtr, cfragstoreFileSize, fragmentstore);
initFragstore(fragPtr);
@@ -6892,7 +6949,8 @@ void Dbdih::initialiseFragstore()
fragPtr.i = 0;
cfirstfragstore = RNIL;
cremainingfrags = 0;
- for (Uint32 i = 0; i < noOfChunks; i++) {
+ for (i = 0; i < noOfChunks; i++) {
+ refresh_watch_dog();
ptrCheckGuard(fragPtr, cfragstoreFileSize, fragmentstore);
fragPtr.p->nextFragmentChunk = cfirstfragstore;
cfirstfragstore = fragPtr.i;
@@ -10231,11 +10289,12 @@ void Dbdih::allocStoredReplica(FragmentstorePtr fragPtr,
ReplicaRecordPtr& newReplicaPtr,
Uint32 nodeId)
{
+ Uint32 i;
ReplicaRecordPtr arrReplicaPtr;
ReplicaRecordPtr arrPrevReplicaPtr;
seizeReplicaRec(newReplicaPtr);
- for (Uint32 i = 0; i < MAX_LCP_STORED; i++) {
+ for (i = 0; i < MAX_LCP_STORED; i++) {
newReplicaPtr.p->maxGciCompleted[i] = 0;
newReplicaPtr.p->maxGciStarted[i] = 0;
newReplicaPtr.p->lcpId[i] = 0;
@@ -10243,7 +10302,7 @@ void Dbdih::allocStoredReplica(FragmentstorePtr fragPtr,
}//for
newReplicaPtr.p->noCrashedReplicas = 0;
newReplicaPtr.p->initialGci = currentgcp;
- for (Uint32 i = 0; i < 8; i++) {
+ for (i = 0; i < 8; i++) {
newReplicaPtr.p->replicaLastGci[i] = (Uint32)-1;
newReplicaPtr.p->createGci[i] = 0;
}//for
@@ -10354,7 +10413,8 @@ void Dbdih::checkEscalation()
{
Uint32 TnodeGroup[MAX_NDB_NODES];
NodeRecordPtr nodePtr;
- for (Uint32 i = 0; i < MAX_NDB_NODES; i++) {
+ Uint32 i;
+ for (i = 0; i < MAX_NDB_NODES; i++) {
TnodeGroup[i] = ZFALSE;
}//for
for (nodePtr.i = 1; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) {
@@ -10366,7 +10426,7 @@ void Dbdih::checkEscalation()
TnodeGroup[nodePtr.p->nodeGroup] = ZTRUE;
}
}
- for (Uint32 i = 0; i < cnoOfNodeGroups; i++) {
+ for (i = 0; i < cnoOfNodeGroups; i++) {
jam();
if (TnodeGroup[i] == ZFALSE) {
jam();
@@ -10900,27 +10960,6 @@ void Dbdih::initFragstore(FragmentstorePtr fragPtr)
fragPtr.p->distributionKey = 0;
}//Dbdih::initFragstore()
-void Dbdih::initNodeState(NodeRecordPtr nodePtr)
-{
- nodePtr.p->gcpstate = NodeRecord::READY;
-
- nodePtr.p->activeStatus = Sysfile::NS_NotDefined;
- nodePtr.p->recNODE_FAILREP = ZFALSE;
- nodePtr.p->nodeGroup = ZNIL;
- nodePtr.p->dbtcFailCompleted = ZTRUE;
- nodePtr.p->dbdictFailCompleted = ZTRUE;
- nodePtr.p->dbdihFailCompleted = ZTRUE;
- nodePtr.p->dblqhFailCompleted = ZTRUE;
- nodePtr.p->noOfStartedChkpt = 0;
- nodePtr.p->noOfQueuedChkpt = 0;
- nodePtr.p->lcpStateAtTakeOver = (MasterLCPConf::State)255;
-
- nodePtr.p->activeTabptr = RNIL;
- nodePtr.p->nodeStatus = NodeRecord::NOT_IN_CLUSTER;
- nodePtr.p->useInTransactions = false;
- nodePtr.p->copyCompleted = false;
-}//Dbdih::initNodeState()
-
/*************************************************************************/
/* */
/* MODULE: INIT_RESTART_INFO */
@@ -10929,7 +10968,8 @@ void Dbdih::initNodeState(NodeRecordPtr nodePtr)
/*************************************************************************/
void Dbdih::initRestartInfo()
{
- for (int i = 0; i < MAX_NDB_NODES; i++) {
+ Uint32 i;
+ for (i = 0; i < MAX_NDB_NODES; i++) {
SYSFILE->lastCompletedGCI[i] = 0;
}//for
NodeRecordPtr nodePtr;
@@ -10950,10 +10990,10 @@ void Dbdih::initRestartInfo()
SYSFILE->oldestRestorableGCI = 1;
SYSFILE->newestRestorableGCI = 1;
SYSFILE->systemRestartBits = 0;
- for (Uint32 i = 0; i < NodeBitmask::Size; i++) {
+ for (i = 0; i < NodeBitmask::Size; i++) {
SYSFILE->lcpActive[0] = 0;
}//for
- for (Uint32 i = 0; i < Sysfile::TAKE_OVER_SIZE; i++) {
+ for (i = 0; i < Sysfile::TAKE_OVER_SIZE; i++) {
SYSFILE->takeOver[i] = 0;
}//for
Sysfile::setInitialStartOngoing(SYSFILE->systemRestartBits);
@@ -11032,10 +11072,11 @@ void Dbdih::initTable(TabRecordPtr tabPtr)
tabPtr.p->tabFile[1] = RNIL;
tabPtr.p->m_dropTab.tabUserRef = 0;
tabPtr.p->m_dropTab.tabUserPtr = RNIL;
- for (Uint32 i = 0; i < MAX_NDB_NODES; i++) {
+ Uint32 i;
+ for (i = 0; i < MAX_NDB_NODES; i++) {
tabPtr.p->startFid[i] = RNIL;
}//for
- for (Uint32 i = 0; i < 8; i++) {
+ for (i = 0; i < 8; i++) {
tabPtr.p->pageRef[i] = RNIL;
}//for
tabPtr.p->tableType = DictTabInfo::UndefTableType;
@@ -11100,6 +11141,7 @@ void Dbdih::initialiseRecordsLab(Signal* signal,
jam();
/******** INTIALIZING API CONNECT RECORDS ********/
for (apiConnectptr.i = 0; apiConnectptr.i < capiConnectFileSize; apiConnectptr.i++) {
+ refresh_watch_dog();
ptrAss(apiConnectptr, apiConnectRecord);
apiConnectptr.p->nextApi = RNIL;
}//for
@@ -11111,6 +11153,7 @@ void Dbdih::initialiseRecordsLab(Signal* signal,
jam();
/****** CONNECT ******/
for (connectPtr.i = 0; connectPtr.i < cconnectFileSize; connectPtr.i++) {
+ refresh_watch_dog();
ptrAss(connectPtr, connectRecord);
connectPtr.p->userpointer = RNIL;
connectPtr.p->userblockref = ZNIL;
@@ -11165,7 +11208,7 @@ void Dbdih::initialiseRecordsLab(Signal* signal,
NodeRecordPtr nodePtr;
for (nodePtr.i = 0; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) {
ptrAss(nodePtr, nodeRecord);
- initNodeState(nodePtr);
+ new (nodePtr.p) NodeRecord();
}//for
break;
}
@@ -11175,6 +11218,7 @@ void Dbdih::initialiseRecordsLab(Signal* signal,
jam();
/******* PAGE RECORD ******/
for (pagePtr.i = 0; pagePtr.i < cpageFileSize; pagePtr.i++) {
+ refresh_watch_dog();
ptrAss(pagePtr, pageRecord);
pagePtr.p->nextfreepage = pagePtr.i + 1;
}//for
@@ -11191,6 +11235,7 @@ void Dbdih::initialiseRecordsLab(Signal* signal,
/******* REPLICA RECORD ******/
for (initReplicaPtr.i = 0; initReplicaPtr.i < creplicaFileSize;
initReplicaPtr.i++) {
+ refresh_watch_dog();
ptrAss(initReplicaPtr, replicaRecord);
initReplicaPtr.p->lcpIdStarted = 0;
initReplicaPtr.p->lcpOngoingFlag = false;
@@ -11210,6 +11255,7 @@ void Dbdih::initialiseRecordsLab(Signal* signal,
/********* TAB-DESCRIPTOR ********/
for (loopTabptr.i = 0; loopTabptr.i < ctabFileSize; loopTabptr.i++) {
ptrAss(loopTabptr, tabRecord);
+ refresh_watch_dog();
initTable(loopTabptr);
}//for
break;
@@ -11367,6 +11413,7 @@ void Dbdih::makeNodeGroups(Uint32 nodeArray[])
Uint32 tmngNodeGroup;
Uint32 tmngReplica;
Uint32 tmngLimit;
+ Uint32 i;
/**-----------------------------------------------------------------------
* ASSIGN ALL ACTIVE NODES INTO NODE GROUPS. HOT SPARE NODES ARE ASSIGNED
@@ -11376,7 +11423,7 @@ void Dbdih::makeNodeGroups(Uint32 nodeArray[])
tmngReplica = 0;
tmngLimit = csystemnodes - cnoHotSpare;
ndbrequire(tmngLimit < MAX_NDB_NODES);
- for (Uint32 i = 0; i < tmngLimit; i++) {
+ for (i = 0; i < tmngLimit; i++) {
NodeGroupRecordPtr NGPtr;
jam();
tmngNode = nodeArray[i];
@@ -11396,14 +11443,14 @@ void Dbdih::makeNodeGroups(Uint32 nodeArray[])
}//for
cnoOfNodeGroups = tmngNodeGroup;
ndbrequire(csystemnodes < MAX_NDB_NODES);
- for (Uint32 i = tmngLimit + 1; i < csystemnodes; i++) {
+ for (i = tmngLimit + 1; i < csystemnodes; i++) {
jam();
tmngNode = nodeArray[i];
mngNodeptr.i = tmngNode;
ptrCheckGuard(mngNodeptr, MAX_NDB_NODES, nodeRecord);
mngNodeptr.p->nodeGroup = ZNIL;
}//for
- for(int i = 0; i < MAX_NDB_NODES; i++){
+ for(i = 0; i < MAX_NDB_NODES; i++){
jam();
Sysfile::setNodeGroup(i, SYSFILE->nodeGroups, NO_NODE_GROUP_ID);
}//for
@@ -11521,7 +11568,7 @@ void Dbdih::makePrnList(ReadNodesConf * readNodes, Uint32 nodeArray[])
jam();
nodePtr.i = nodeArray[i];
ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRecord);
- initNodeState(nodePtr);
+ new (nodePtr.p) NodeRecord();
if (NodeBitmask::get(readNodes->inactiveNodes, nodePtr.i) == false){
jam();
nodePtr.p->nodeStatus = NodeRecord::ALIVE;
@@ -11690,12 +11737,13 @@ Uint32 Dbdih::readPageWord(RWFragment* rf)
void Dbdih::readReplica(RWFragment* rf, ReplicaRecordPtr readReplicaPtr)
{
+ Uint32 i;
readReplicaPtr.p->procNode = readPageWord(rf);
readReplicaPtr.p->initialGci = readPageWord(rf);
readReplicaPtr.p->noCrashedReplicas = readPageWord(rf);
readReplicaPtr.p->nextLcp = readPageWord(rf);
- for (Uint32 i = 0; i < MAX_LCP_STORED; i++) {
+ for (i = 0; i < MAX_LCP_STORED; i++) {
readReplicaPtr.p->maxGciCompleted[i] = readPageWord(rf);
readReplicaPtr.p->maxGciStarted[i] = readPageWord(rf);
readReplicaPtr.p->lcpId[i] = readPageWord(rf);
@@ -11703,13 +11751,13 @@ void Dbdih::readReplica(RWFragment* rf, ReplicaRecordPtr readReplicaPtr)
}//for
const Uint32 noCrashedReplicas = readReplicaPtr.p->noCrashedReplicas;
ndbrequire(noCrashedReplicas < 8);
- for (Uint32 i = 0; i < noCrashedReplicas; i++) {
+ for (i = 0; i < noCrashedReplicas; i++) {
readReplicaPtr.p->createGci[i] = readPageWord(rf);
readReplicaPtr.p->replicaLastGci[i] = readPageWord(rf);
ndbrequire(readReplicaPtr.p->createGci[i] != 0xF1F1F1F1);
ndbrequire(readReplicaPtr.p->replicaLastGci[i] != 0xF1F1F1F1);
}//for
- for(Uint32 i = noCrashedReplicas; i<8; i++){
+ for(i = noCrashedReplicas; i<8; i++){
readReplicaPtr.p->createGci[i] = readPageWord(rf);
readReplicaPtr.p->replicaLastGci[i] = readPageWord(rf);
// They are not initialized...
@@ -11732,7 +11780,7 @@ void Dbdih::readReplica(RWFragment* rf, ReplicaRecordPtr readReplicaPtr)
/* WE ALSO HAVE TO INVALIDATE ANY LOCAL CHECKPOINTS THAT HAVE BEEN */
/* INVALIDATED BY MOVING BACK THE RESTART GCI. */
/* ---------------------------------------------------------------------- */
- for (Uint32 i = 0; i < MAX_LCP_STORED; i++) {
+ for (i = 0; i < MAX_LCP_STORED; i++) {
jam();
if ((readReplicaPtr.p->lcpStatus[i] == ZVALID) &&
(readReplicaPtr.p->maxGciStarted[i] > SYSFILE->newestRestorableGCI)) {
@@ -11764,6 +11812,7 @@ void Dbdih::readReplica(RWFragment* rf, ReplicaRecordPtr readReplicaPtr)
void Dbdih::readReplicas(RWFragment* rf, FragmentstorePtr fragPtr)
{
+ Uint32 i;
ReplicaRecordPtr newReplicaPtr;
Uint32 noStoredReplicas = fragPtr.p->noStoredReplicas;
Uint32 noOldStoredReplicas = fragPtr.p->noOldStoredReplicas;
@@ -11775,7 +11824,7 @@ void Dbdih::readReplicas(RWFragment* rf, FragmentstorePtr fragPtr)
fragPtr.p->noOldStoredReplicas = 0;
Uint32 replicaIndex = 0;
ndbrequire(noStoredReplicas + noOldStoredReplicas <= MAX_REPLICAS);
- for (Uint32 i = 0; i < noStoredReplicas; i++) {
+ for (i = 0; i < noStoredReplicas; i++) {
seizeReplicaRec(newReplicaPtr);
readReplica(rf, newReplicaPtr);
if (checkNodeAlive(newReplicaPtr.p->procNode)) {
@@ -11790,7 +11839,7 @@ void Dbdih::readReplicas(RWFragment* rf, FragmentstorePtr fragPtr)
}//if
}//for
fragPtr.p->fragReplicas = noStoredReplicas;
- for (Uint32 i = 0; i < noOldStoredReplicas; i++) {
+ for (i = 0; i < noOldStoredReplicas; i++) {
jam();
seizeReplicaRec(newReplicaPtr);
readReplica(rf, newReplicaPtr);
@@ -12640,11 +12689,11 @@ void Dbdih::setNodeRestartInfoBits()
NodeRecordPtr nodePtr;
Uint32 tsnrNodeGroup;
Uint32 tsnrNodeActiveStatus;
-
- for(int i = 1; i < MAX_NDB_NODES; i++){
+ Uint32 i;
+ for(i = 1; i < MAX_NDB_NODES; i++){
Sysfile::setNodeStatus(i, SYSFILE->nodeStatus, Sysfile::NS_Active);
}//for
- for(Uint32 i = 1; i < Sysfile::NODE_GROUPS_SIZE; i++){
+ for(i = 1; i < Sysfile::NODE_GROUPS_SIZE; i++){
SYSFILE->nodeGroups[i] = 0;
}//for
NdbNodeBitmask::clear(SYSFILE->lcpActive);
@@ -12786,13 +12835,14 @@ void Dbdih::writeReplicas(RWFragment* wf, Uint32 replicaStartIndex)
writePageWord(wf, wfReplicaPtr.p->initialGci);
writePageWord(wf, wfReplicaPtr.p->noCrashedReplicas);
writePageWord(wf, wfReplicaPtr.p->nextLcp);
- for (Uint32 i = 0; i < MAX_LCP_STORED; i++) {
+ Uint32 i;
+ for (i = 0; i < MAX_LCP_STORED; i++) {
writePageWord(wf, wfReplicaPtr.p->maxGciCompleted[i]);
writePageWord(wf, wfReplicaPtr.p->maxGciStarted[i]);
writePageWord(wf, wfReplicaPtr.p->lcpId[i]);
writePageWord(wf, wfReplicaPtr.p->lcpStatus[i]);
}//if
- for (Uint32 i = 0; i < 8; i++) {
+ for (i = 0; i < 8; i++) {
writePageWord(wf, wfReplicaPtr.p->createGci[i]);
writePageWord(wf, wfReplicaPtr.p->replicaLastGci[i]);
}//if
@@ -13003,7 +13053,7 @@ Dbdih::execDUMP_STATE_ORD(Signal* signal)
}
if(signal->theData[0] == 7012){
- char buf[c_lcpState.m_participatingDIH.TextLength+1];
+ char buf[8*_NDB_NODE_BITMASK_SIZE+1];
infoEvent("ParticipatingDIH = %s", c_lcpState.m_participatingDIH.getText(buf));
infoEvent("ParticipatingLQH = %s", c_lcpState.m_participatingLQH.getText(buf));
infoEvent("m_LCP_COMPLETE_REP_Counter_DIH = %s",
@@ -13020,8 +13070,8 @@ Dbdih::execDUMP_STATE_ORD(Signal* signal)
jam();
ptrAss(nodePtr, nodeRecord);
if(nodePtr.p->nodeStatus == NodeRecord::ALIVE){
-
- for(Uint32 i = 0; i<nodePtr.p->noOfStartedChkpt; i++){
+ Uint32 i;
+ for(i = 0; i<nodePtr.p->noOfStartedChkpt; i++){
infoEvent("Node %d: started: table=%d fragment=%d replica=%d",
nodePtr.i,
nodePtr.p->startedChkpt[i].tableId,
@@ -13029,7 +13079,7 @@ Dbdih::execDUMP_STATE_ORD(Signal* signal)
nodePtr.p->startedChkpt[i].replicaPtr);
}
- for(Uint32 i = 0; i<nodePtr.p->noOfQueuedChkpt; i++){
+ for(i = 0; i<nodePtr.p->noOfQueuedChkpt; i++){
infoEvent("Node %d: queued: table=%d fragment=%d replica=%d",
nodePtr.i,
nodePtr.p->queuedChkpt[i].tableId,
@@ -13360,6 +13410,25 @@ Dbdih::checkPrepDropTabComplete(Signal* signal, TabRecordPtr tabPtr){
}
void
+Dbdih::execWAIT_DROP_TAB_REF(Signal* signal){
+ jamEntry();
+ WaitDropTabRef * ref = (WaitDropTabRef*)signal->getDataPtr();
+
+ TabRecordPtr tabPtr;
+ tabPtr.i = ref->tableId;
+ ptrCheckGuard(tabPtr, ctabFileSize, tabRecord);
+
+ ndbrequire(tabPtr.p->tabStatus == TabRecord::TS_DROPPING);
+ Uint32 nodeId = refToNode(ref->senderRef);
+
+ ndbrequire(ref->errorCode == WaitDropTabRef::NoSuchTable ||
+ ref->errorCode == WaitDropTabRef::NF_FakeErrorREF);
+
+ tabPtr.p->m_prepDropTab.waitDropTabCount.clearWaitingFor(nodeId);
+ checkPrepDropTabComplete(signal, tabPtr);
+}
+
+void
Dbdih::execWAIT_DROP_TAB_CONF(Signal* signal){
jamEntry();
WaitDropTabConf * conf = (WaitDropTabConf*)signal->getDataPtr();
@@ -14137,3 +14206,25 @@ bool Dbdih::isActiveMaster()
{
return ((reference() == cmasterdihref) && (cmasterState == MASTER_ACTIVE));
}//Dbdih::isActiveMaster()
+
+Dbdih::NodeRecord::NodeRecord(){
+ m_nodefailSteps.clear();
+ gcpstate = NodeRecord::READY;
+
+ activeStatus = Sysfile::NS_NotDefined;
+ recNODE_FAILREP = ZFALSE;
+ nodeGroup = ZNIL;
+ dbtcFailCompleted = ZTRUE;
+ dbdictFailCompleted = ZTRUE;
+ dbdihFailCompleted = ZTRUE;
+ dblqhFailCompleted = ZTRUE;
+ noOfStartedChkpt = 0;
+ noOfQueuedChkpt = 0;
+ lcpStateAtTakeOver = (MasterLCPConf::State)255;
+
+ activeTabptr = RNIL;
+ nodeStatus = NodeRecord::NOT_IN_CLUSTER;
+ useInTransactions = false;
+ copyCompleted = false;
+ allowNodeStart = true;
+}
diff --git a/ndb/src/kernel/blocks/dblqh/Dblqh.hpp b/ndb/src/kernel/blocks/dblqh/Dblqh.hpp
index 824f74c59af..9fcb6faf3e3 100644
--- a/ndb/src/kernel/blocks/dblqh/Dblqh.hpp
+++ b/ndb/src/kernel/blocks/dblqh/Dblqh.hpp
@@ -410,7 +410,6 @@
*/
class Dblqh: public SimulatedBlock {
public:
-
enum LcpCloseState {
LCP_IDLE = 0,
LCP_RUNNING = 1, // LCP is running
@@ -1990,7 +1989,6 @@ public:
UintR nextTcLogQueue;
UintR nextTc;
UintR nextTcConnectrec;
- Uint16 nodeAfterNext[2];
UintR prevHashRec;
UintR prevLogTcrec;
UintR prevTc;
@@ -2027,6 +2025,7 @@ public:
Uint16 nextReplica;
Uint16 primKeyLen;
Uint16 save1;
+ Uint16 nodeAfterNext[3];
Uint8 activeCreat;
Uint8 apiVersionNo;
@@ -2765,6 +2764,11 @@ private:
/* ------------------------------------------------------------------------- */
UintR cfirstCompletedFragSr;
+ /**
+ * List of fragment that the log execution is completed for
+ */
+ Uint32 c_redo_log_complete_frags;
+
/* ------------------------------------------------------------------------- */
/*USED DURING SYSTEM RESTART, INDICATES THE OLDEST GCI THAT CAN BE RESTARTED */
/*FROM AFTER THIS SYSTEM RESTART. USED TO FIND THE LOG TAIL. */
@@ -2859,8 +2863,9 @@ private:
/* ------------------------------------------------------------------------- */
UintR preComputedRequestInfoMask;
UintR ctransidHash[1024];
-
-
+
+ Uint32 c_diskless;
+
public:
/**
*
diff --git a/ndb/src/kernel/blocks/dblqh/DblqhInit.cpp b/ndb/src/kernel/blocks/dblqh/DblqhInit.cpp
index d5f40ec143c..4bb31185cfe 100644
--- a/ndb/src/kernel/blocks/dblqh/DblqhInit.cpp
+++ b/ndb/src/kernel/blocks/dblqh/DblqhInit.cpp
@@ -65,6 +65,7 @@ void Dblqh::initData()
cLqhTimeOutCount = 0;
cLqhTimeOutCheckCount = 0;
cbookedAccOps = 0;
+ c_redo_log_complete_frags = RNIL;
}//Dblqh::initData()
void Dblqh::initRecords()
@@ -120,7 +121,8 @@ void Dblqh::initRecords()
logPageRecord = (LogPageRecord*)allocRecord("LogPageRecord",
sizeof(LogPageRecord),
- clogPageFileSize);
+ clogPageFileSize,
+ false);
pageRefRecord = (PageRefRecord*)allocRecord("PageRefRecord",
sizeof(PageRefRecord),
@@ -322,6 +324,31 @@ Dblqh::Dblqh(const class Configuration & conf):
addRecSignal(GSN_TUX_ADD_ATTRREF, &Dblqh::execTUX_ADD_ATTRREF);
initData();
+
+#ifdef VM_TRACE
+ {
+ void* tmp[] = {
+ &addfragptr,
+ &attrinbufptr,
+ &databufptr,
+ &fragptr,
+ &gcpPtr,
+ &lcpPtr,
+ &lcpLocptr,
+ &logPartPtr,
+ &logFilePtr,
+ &lfoPtr,
+ &logPagePtr,
+ &pageRefPtr,
+ &scanptr,
+ &tabptr,
+ &tcConnectptr,
+ &tcNodeFailptr,
+ };
+ init_globals_list(tmp, sizeof(tmp)/sizeof(tmp[0]));
+ }
+#endif
+
}//Dblqh::Dblqh()
Dblqh::~Dblqh()
diff --git a/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp b/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp
index 1abf4b3a7e9..6b4a78380be 100644
--- a/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp
+++ b/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp
@@ -60,10 +60,55 @@
// seen only when we debug the product
#ifdef VM_TRACE
#define DEBUG(x) ndbout << "DBLQH: "<< x << endl;
+NdbOut &
+operator<<(NdbOut& out, Dblqh::TcConnectionrec::TransactionState state){
+ out << (int)state;
+ return out;
+}
+
+NdbOut &
+operator<<(NdbOut& out, Dblqh::TcConnectionrec::LogWriteState state){
+ out << (int)state;
+ return out;
+}
+
+NdbOut &
+operator<<(NdbOut& out, Dblqh::TcConnectionrec::ListState state){
+ out << (int)state;
+ return out;
+}
+
+NdbOut &
+operator<<(NdbOut& out, Dblqh::TcConnectionrec::AbortState state){
+ out << (int)state;
+ return out;
+}
+
+NdbOut &
+operator<<(NdbOut& out, Dblqh::ScanRecord::ScanState state){
+ out << (int)state;
+ return out;
+}
+
+NdbOut &
+operator<<(NdbOut& out, Dblqh::LogFileOperationRecord::LfoState state){
+ out << (int)state;
+ return out;
+}
+
+NdbOut &
+operator<<(NdbOut& out, Dblqh::ScanRecord::ScanType state){
+ out << (int)state;
+ return out;
+}
+
#else
#define DEBUG(x)
#endif
+//#define MARKER_TRACE 1
+//#define TRACE_SCAN_TAKEOVER 1
+
const Uint32 NR_ScanNo = 0;
void Dblqh::execACC_COM_BLOCK(Signal* signal)
@@ -847,6 +892,8 @@ void Dblqh::execREAD_CONFIG_REQ(Signal* signal)
ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_LQH_SCAN, &cscanrecFileSize));
cmaxAccOps = cscanrecFileSize * MAX_PARALLEL_SCANS_PER_FRAG;
+ ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_DB_DISCLESS, &c_diskless));
+
initRecords();
initialiseRecordsLab(signal, 0, ref, senderData);
@@ -957,7 +1004,7 @@ void Dblqh::execLQHFRAGREQ(Signal* signal)
} else {
fragptr.p->tableFragptr = fragptr.i;
}
-
+
if (tempTable) {
//--------------------------------------------
// reqinfo bit 3-4 = 2 means temporary table
@@ -2416,6 +2463,9 @@ Dblqh::execREMOVE_MARKER_ORD(Signal* signal)
CommitAckMarkerPtr removedPtr;
m_commitAckMarkerHash.release(removedPtr, key);
ndbrequire(removedPtr.i != RNIL);
+#ifdef MARKER_TRACE
+ ndbout_c("Rem marker[%.8x %.8x]", key.transid1, key.transid2);
+#endif
}
@@ -3140,6 +3190,13 @@ void Dblqh::execLQHKEYREQ(Signal* signal)
noFreeRecordLab(signal, lqhKeyReq, ZNO_TC_CONNECT_ERROR);
return;
}//if
+
+ if(ERROR_INSERTED(5038) &&
+ refToNode(signal->getSendersBlockRef()) != getOwnNodeId()){
+ jam();
+ SET_ERROR_INSERT_VALUE(5039);
+ return;
+ }
c_Counters.operations++;
@@ -3208,10 +3265,17 @@ void Dblqh::execLQHKEYREQ(Signal* signal)
const NodeId tcNodeId = refToNode(sig5);
markerPtr.p->tcNodeId = tcNodeId;
+ CommitAckMarkerPtr tmp;
+#ifdef VM_TRACE
+#ifdef MARKER_TRACE
+ ndbout_c("Add marker[%.8x %.8x]", markerPtr.p->transid1, markerPtr.p->transid2);
+#endif
+ ndbrequire(!m_commitAckMarkerHash.find(tmp, * markerPtr.p));
+#endif
m_commitAckMarkerHash.add(markerPtr);
regTcPtr->commitAckMarker = markerPtr.i;
- }
-
+ }
+
regTcPtr->reqinfo = Treqinfo;
regTcPtr->lastReplicaNo = LqhKeyReq::getLastReplicaNo(Treqinfo);
regTcPtr->lockType = LqhKeyReq::getLockType(Treqinfo);
@@ -3510,6 +3574,7 @@ void Dblqh::prepareContinueAfterBlockedLab(Signal* signal)
/* -------------------------------------------------------------------------- */
/* ALSO AFTER NORMAL PROCEDURE WE CONTINUE HERE */
/* -------------------------------------------------------------------------- */
+ Uint32 tc_ptr_i = tcConnectptr.i;
TcConnectionrec * const regTcPtr = tcConnectptr.p;
if (regTcPtr->indTakeOver == ZTRUE) {
jam();
@@ -3520,7 +3585,10 @@ void Dblqh::prepareContinueAfterBlockedLab(Signal* signal)
key.scanNumber = KeyInfo20::getScanNo(regTcPtr->tcScanInfo);
key.fragPtrI = fragptr.i;
c_scanTakeOverHash.find(scanptr, key);
- ndbassert(scanptr.i != RNIL);
+#ifdef TRACE_SCAN_TAKEOVER
+ if(scanptr.i == RNIL)
+ ndbout_c("not finding (%d %d)", key.scanNumber, key.fragPtrI);
+#endif
}
if (scanptr.i == RNIL) {
jam();
@@ -3610,14 +3678,14 @@ void Dblqh::prepareContinueAfterBlockedLab(Signal* signal)
EXECUTE_DIRECT(refToBlock(regTcPtr->tcAccBlockref), GSN_ACCKEYREQ,
signal, 7 + regTcPtr->primKeyLen);
if (signal->theData[0] < RNIL) {
- signal->theData[0] = tcConnectptr.i;
+ signal->theData[0] = tc_ptr_i;
execACCKEYCONF(signal);
return;
} else if (signal->theData[0] == RNIL) {
;
} else {
ndbrequire(signal->theData[0] == (UintR)-1);
- signal->theData[0] = tcConnectptr.i;
+ signal->theData[0] = tc_ptr_i;
execACCKEYREF(signal);
}//if
return;
@@ -5632,9 +5700,7 @@ void Dblqh::execABORT(Signal* signal)
BlockReference tcBlockref = signal->theData[1];
Uint32 transid1 = signal->theData[2];
Uint32 transid2 = signal->theData[3];
- if (ERROR_INSERTED(5003)) {
- systemErrorLab(signal);
- }
+ CRASH_INSERTION(5003);
if (ERROR_INSERTED(5015)) {
CLEAR_ERROR_INSERT_VALUE;
sendSignalWithDelay(cownref, GSN_ABORT, signal, 2000, 4);
@@ -5644,6 +5710,21 @@ void Dblqh::execABORT(Signal* signal)
transid2,
tcOprec) != ZOK) {
jam();
+
+ if(ERROR_INSERTED(5039) &&
+ refToNode(signal->getSendersBlockRef()) != getOwnNodeId()){
+ jam();
+ SET_ERROR_INSERT_VALUE(5040);
+ return;
+ }
+
+ if(ERROR_INSERTED(5040) &&
+ refToNode(signal->getSendersBlockRef()) != getOwnNodeId()){
+ jam();
+ SET_ERROR_INSERT_VALUE(5003);
+ return;
+ }
+
/* ------------------------------------------------------------------------- */
// SEND ABORTED EVEN IF NOT FOUND.
//THE TRANSACTION MIGHT NEVER HAVE ARRIVED HERE.
@@ -5676,7 +5757,23 @@ void Dblqh::execABORT(Signal* signal)
}//if
regTcPtr->abortState = TcConnectionrec::ABORT_FROM_TC;
regTcPtr->activeCreat = ZFALSE;
+
+ const Uint32 commitAckMarker = regTcPtr->commitAckMarker;
+ if(commitAckMarker != RNIL){
+ jam();
+#ifdef MARKER_TRACE
+ {
+ CommitAckMarkerPtr tmp;
+ m_commitAckMarkerHash.getPtr(tmp, commitAckMarker);
+ ndbout_c("Ab2 marker[%.8x %.8x]", tmp.p->transid1, tmp.p->transid2);
+ }
+#endif
+ m_commitAckMarkerHash.release(commitAckMarker);
+ regTcPtr->commitAckMarker = RNIL;
+ }
+
abortStateHandlerLab(signal);
+
return;
}//Dblqh::execABORT()
@@ -5815,10 +5912,18 @@ void Dblqh::execACCKEYREF(Signal* signal)
* Only primary replica can get ZTUPLE_ALREADY_EXIST || ZNO_TUPLE_FOUND
*
* Unless it's a simple or dirty read
+ *
+ * NOT TRUE!
+ * 1) op1 - primary insert ok
+ * 2) op1 - backup insert fail (log full or what ever)
+ * 3) op1 - delete ok @ primary
+ * 4) op1 - delete fail @ backup
+ *
+ * -> ZNO_TUPLE_FOUND is possible
*/
ndbrequire
(tcPtr->seqNoReplica == 0 ||
- (errCode != ZTUPLE_ALREADY_EXIST && errCode != ZNO_TUPLE_FOUND) ||
+ errCode != ZTUPLE_ALREADY_EXIST ||
(tcPtr->operation == ZREAD && (tcPtr->dirtyOp || tcPtr->opSimple)));
}
tcPtr->abortState = TcConnectionrec::ABORT_FROM_LQH;
@@ -5925,10 +6030,15 @@ void Dblqh::abortStateHandlerLab(Signal* signal)
break;
case TcConnectionrec::STOPPED:
jam();
-/* ------------------------------------------------------------------------- */
-/*WE ARE CURRENTLY QUEUED FOR ACCESS TO THE FRAGMENT BY A LOCAL CHECKPOINT. */
-/* ------------------------------------------------------------------------- */
+ /* ---------------------------------------------------------------------
+ * WE ARE CURRENTLY QUEUED FOR ACCESS TO THE FRAGMENT BY A LCP
+ * Since nothing has been done, just release operation
+ * i.e. no prepare log record has been written
+ * so no abort log records needs to be written
+ */
releaseWaitQueue(signal);
+ continueAfterLogAbortWriteLab(signal);
+ return;
break;
case TcConnectionrec::WAIT_AI_AFTER_ABORT:
jam();
@@ -6034,7 +6144,13 @@ void Dblqh::abortCommonLab(Signal* signal)
* There is no NR ongoing and we have a marker
*/
jam();
-
+#ifdef MARKER_TRACE
+ {
+ CommitAckMarkerPtr tmp;
+ m_commitAckMarkerHash.getPtr(tmp, commitAckMarker);
+ ndbout_c("Abo marker[%.8x %.8x]", tmp.p->transid1, tmp.p->transid2);
+ }
+#endif
m_commitAckMarkerHash.release(commitAckMarker);
regTcPtr->commitAckMarker = RNIL;
}
@@ -6307,12 +6423,13 @@ void Dblqh::execNODE_FAILREP(Signal* signal)
UintR TfoundNodes = 0;
UintR TnoOfNodes;
UintR Tdata[MAX_NDB_NODES];
+ Uint32 i;
NodeFailRep * const nodeFail = (NodeFailRep *)&signal->theData[0];
TnoOfNodes = nodeFail->noOfNodes;
UintR index = 0;
- for (Uint32 i = 1; i < MAX_NDB_NODES; i++) {
+ for (i = 1; i < MAX_NDB_NODES; i++) {
jam();
if(NodeBitmask::get(nodeFail->theNodes, i)){
jam();
@@ -6326,7 +6443,7 @@ void Dblqh::execNODE_FAILREP(Signal* signal)
ndbrequire(index == TnoOfNodes);
ndbrequire(cnoOfNodes - 1 < MAX_NDB_NODES);
- for (Uint32 i = 0; i < TnoOfNodes; i++) {
+ for (i = 0; i < TnoOfNodes; i++) {
const Uint32 nodeId = Tdata[i];
lcpPtr.p->m_EMPTY_LCP_REQ.clear(nodeId);
@@ -6524,7 +6641,7 @@ Dblqh::scanMarkers(Signal* signal,
}
const Uint32 RT_BREAK = 256;
- for(Uint32 i = 0; i<RT_BREAK || iter.bucket == startBucket; i++){
+ for(i = 0; i<RT_BREAK || iter.bucket == startBucket; i++){
jam();
if(iter.curr.i == RNIL){
@@ -6793,7 +6910,8 @@ void Dblqh::execSCAN_NEXTREQ(Signal* signal)
if (findTransaction(transid1, transid2, senderData) != ZOK){
jam();
- DEBUG("Received SCAN_NEXTREQ in LQH with close flag when closed");
+ DEBUG(senderData <<
+ " Received SCAN_NEXTREQ in LQH with close flag when closed");
ndbrequire(nextReq->closeFlag == ZTRUE);
return;
}
@@ -6833,6 +6951,10 @@ void Dblqh::execSCAN_NEXTREQ(Signal* signal)
return;
}//if
+ if(ERROR_INSERTED(5036)){
+ return;
+ }
+
scanptr.i = tcConnectptr.p->tcScanRec;
ndbrequire(scanptr.i != RNIL);
c_scanRecordPool.getPtr(scanptr);
@@ -6849,6 +6971,10 @@ void Dblqh::execSCAN_NEXTREQ(Signal* signal)
if(ERROR_INSERTED(5034)){
CLEAR_ERROR_INSERT_VALUE;
}
+ if(ERROR_INSERTED(5036)){
+ CLEAR_ERROR_INSERT_VALUE;
+ return;
+ }
closeScanRequestLab(signal);
return;
}//if
@@ -7134,7 +7260,7 @@ void Dblqh::execSCAN_FRAGREQ(Signal* signal)
ScanFragRef * ref;
const Uint32 transid1 = scanFragReq->transId1;
const Uint32 transid2 = scanFragReq->transId2;
- Uint32 errorCode;
+ Uint32 errorCode= 0;
Uint32 senderData;
Uint32 hashIndex;
TcConnectionrecPtr nextHashptr;
@@ -7862,27 +7988,10 @@ void Dblqh::scanTupkeyConfLab(Signal* signal)
}//if
if (scanptr.p->scanKeyinfoFlag) {
jam();
- DatabufPtr TdataBuf;
- TdataBuf.i = tcConnectptr.p->firstTupkeybuf;
- const Uint32 keyLen = tcConnectptr.p->primKeyLen;
- const Uint32 dataBufSz = cdatabufFileSize;
-
- /**
- * Note that this code requires signal->theData to be big enough for
- * a entire key
- */
- ndbrequire(keyLen * 4 <= sizeof(signal->theData));
- KeyInfo20 * keyInfo = (KeyInfo20*)&signal->theData[0];
- for(Uint32 i = 0; i < keyLen; i += 4){
- ptrCheckGuard(TdataBuf, dataBufSz, databuf);
- keyInfo->keyData[i + 0] = TdataBuf.p->data[0];
- keyInfo->keyData[i + 1] = TdataBuf.p->data[1];
- keyInfo->keyData[i + 2] = TdataBuf.p->data[2];
- keyInfo->keyData[i + 3] = TdataBuf.p->data[3];
- TdataBuf.i = TdataBuf.p->nextDatabuf;
- }
sendKeyinfo20(signal, scanptr.p, tcConnectptr.p);
releaseOprec(signal);
+
+ tdata4 += tcConnectptr.p->primKeyLen;// Inform API about keyinfo len aswell
}//if
ndbrequire(scanptr.p->scanCompletedOperations < MAX_PARALLEL_OP_PER_SCAN);
scanptr.p->scanOpLength[scanptr.p->scanCompletedOperations] = tdata4;
@@ -8200,7 +8309,7 @@ Uint32 Dblqh::initScanrec(const ScanFragReq* scanFragReq)
scanptr.p->scanLocalref[1] = 0;
scanptr.p->scanLocalFragid = 0;
scanptr.p->scanTcWaiting = ZTRUE;
- scanptr.p->scanNumber = ZNIL;
+ scanptr.p->scanNumber = ~0;
for (Uint32 i = 0; i < scanConcurrentOperations; i++) {
jam();
@@ -8256,6 +8365,11 @@ Uint32 Dblqh::initScanrec(const ScanFragReq* scanFragReq)
ScanRecordPtr tmp;
ndbrequire(!c_scanTakeOverHash.find(tmp, * scanptr.p));
#endif
+#ifdef TRACE_SCAN_TAKEOVER
+ ndbout_c("adding (%d %d) table: %d fragId: %d frag.i: %d tableFragptr: %d",
+ scanptr.p->scanNumber, scanptr.p->fragPtrI,
+ tabptr.i, scanFragReq->fragmentNo, fragptr.i, fragptr.p->tableFragptr);
+#endif
c_scanTakeOverHash.add(scanptr);
}
return ZOK;
@@ -8318,7 +8432,8 @@ void Dblqh::initScanTc(Signal* signal,
tcConnectptr.p->opExec = 1;
tcConnectptr.p->operation = ZREAD;
tcConnectptr.p->listState = TcConnectionrec::NOT_IN_LIST;
-
+ tcConnectptr.p->commitAckMarker = RNIL;
+
tabptr.p->usageCount++;
}//Dblqh::initScanTc()
@@ -8345,6 +8460,9 @@ void Dblqh::finishScanrec(Signal* signal)
if(scanptr.p->scanKeyinfoFlag){
jam();
ScanRecordPtr tmp;
+#ifdef TRACE_SCAN_TAKEOVER
+ ndbout_c("removing (%d %d)", scanptr.p->scanNumber, scanptr.p->fragPtrI);
+#endif
c_scanTakeOverHash.remove(tmp, * scanptr.p);
ndbrequire(tmp.p == scanptr.p);
}
@@ -8388,6 +8506,9 @@ void Dblqh::finishScanrec(Signal* signal)
ndbrequire(!c_scanTakeOverHash.find(tmp, * restart.p));
#endif
c_scanTakeOverHash.add(restart);
+#ifdef TRACE_SCAN_TAKEOVER
+ ndbout_c("adding-r (%d %d)", restart.p->scanNumber, restart.p->fragPtrI);
+#endif
}
scanptr = restart;
@@ -8422,78 +8543,131 @@ void Dblqh::sendKeyinfo20(Signal* signal,
ndbrequire(scanP->scanCompletedOperations < MAX_PARALLEL_OP_PER_SCAN);
KeyInfo20 * keyInfo = (KeyInfo20 *)&signal->theData[0];
+ DatabufPtr TdataBuf;
+ TdataBuf.i = tcConP->firstTupkeybuf;
+ Uint32 keyLen = tcConP->primKeyLen;
+ const Uint32 dataBufSz = cdatabufFileSize;
+
+ /**
+ * Note that this code requires signal->theData to be big enough for
+ * a entire key
+ */
+ ndbrequire(keyLen * 4 <= sizeof(signal->theData));
+ const BlockReference ref = scanP->scanApiBlockref;
const Uint32 scanOp = scanP->scanCompletedOperations;
+ const Uint32 nodeId = refToNode(ref);
+ const bool connectedToNode = getNodeInfo(nodeId).m_connected;
+ const Uint32 type = getNodeInfo(nodeId).m_type;
+ const bool is_api = (type >= NodeInfo::API && type <= NodeInfo::REP);
+ const bool old_dest = (getNodeInfo(nodeId).m_version < MAKE_VERSION(3,5,0));
+ const bool longable = true; // TODO is_api && !old_dest;
+
+ Uint32 * dst = keyInfo->keyData;
+ dst += nodeId == getOwnNodeId() ? 0 : KeyInfo20::DataLength;
+
+ /**
+ * Copy keydata from data buffer into signal
+ *
+ */
+ for(Uint32 i = 0; i < keyLen; i += 4){
+ ptrCheckGuard(TdataBuf, dataBufSz, databuf);
+ * dst++ = TdataBuf.p->data[0];
+ * dst++ = TdataBuf.p->data[1];
+ * dst++ = TdataBuf.p->data[2];
+ * dst++ = TdataBuf.p->data[3];
+ TdataBuf.i = TdataBuf.p->nextDatabuf;
+ }
+
keyInfo->clientOpPtr = scanP->scanApiOpPtr[scanOp];
- keyInfo->keyLen = tcConP->primKeyLen;
+ keyInfo->keyLen = keyLen;
keyInfo->scanInfo_Node = KeyInfo20::setScanInfo(scanOp,
scanP->scanNumber)+
(getOwnNodeId() << 16);
-
keyInfo->transId1 = tcConP->transid[0];
keyInfo->transId2 = tcConP->transid[1];
-
- const BlockReference ref = scanP->scanApiBlockref;
- const Uint32 keyLen = tcConP->primKeyLen;
- if(refToNode(ref) == getOwnNodeId()){
+
+ Uint32 * src = signal->theData+25;
+ if(connectedToNode){
jam();
- EXECUTE_DIRECT(refToBlock(ref), GSN_KEYINFO20, signal, 5 + keyLen);
+
+ if(nodeId != getOwnNodeId()){
+ jam();
+
+ if(keyLen <= KeyInfo20::DataLength || !longable) {
+ while(keyLen > KeyInfo20::DataLength){
+ jam();
+ MEMCOPY_NO_WORDS(keyInfo->keyData, src, KeyInfo20::DataLength);
+ sendSignal(ref, GSN_KEYINFO20, signal, 25, JBB);
+ src += KeyInfo20::DataLength;;
+ keyLen -= KeyInfo20::DataLength;
+ } while(keyLen >= KeyInfo20::DataLength);
+
+ MEMCOPY_NO_WORDS(keyInfo->keyData, src, keyLen);
+ sendSignal(ref, GSN_KEYINFO20, signal,
+ KeyInfo20::HeaderLength+keyLen, JBB);
+ return;
+ }
+
+ LinearSectionPtr ptr[3];
+ ptr[0].p = src;
+ ptr[0].sz = keyLen;
+ sendSignal(ref, GSN_KEYINFO20, signal, KeyInfo20::HeaderLength,
+ JBB, ptr, 1);
+ return;
+ }
+
+ EXECUTE_DIRECT(refToBlock(ref), GSN_KEYINFO20, signal,
+ KeyInfo20::HeaderLength + keyLen);
jamEntry();
return;
- }
-
- bool connectedToNode = getNodeInfo(refToNode(ref)).m_connected;
-
- if (ERROR_INSERTED(5029)){
- // Use error insert to turn routing on
- jam();
- connectedToNode = false;
}
- if (connectedToNode){
- jam();
- Uint32 keyLenLeft = keyLen;
- Uint32 keyDataIndex = 20;
- for(; keyLenLeft > 20; keyLenLeft -= 20, keyDataIndex += 20){
- jam();
- sendSignal(ref, GSN_KEYINFO20, signal, 25, JBB);
- for(Uint32 i = 0; i<20; i++)
- keyInfo->keyData[i] = keyInfo->keyData[keyDataIndex + i];
- }//for
- sendSignal(ref, GSN_KEYINFO20, signal, 5 + keyLenLeft, JBB);
- } else {
- /**
- * If this node does not have a direct connection
- * to the receiving node we want to send the signals
- * routed via the control node
- */
+ /**
+ * If this node does not have a direct connection
+ * to the receiving node we want to send the signals
+ * routed via the node that controls this read
+ */
+ Uint32 routeBlockref = tcConP->clientBlockref;
+
+ if(keyLen < KeyInfo20::DataLength || !longable){
jam();
- Uint32 keyLenLeft = keyLen;
- Uint32 keyDataIndex = 19;
- BlockReference routeBlockref = tcConP->clientBlockref;
- for(; keyLenLeft > 19; keyLenLeft -= 19, keyDataIndex += 19){
- jam();
- // store final destination, but save original value
- Uint32 saveOne = keyInfo->keyData[19];
- keyInfo->keyData[19] = ref;
+ while (keyLen > (KeyInfo20::DataLength - 1)) {
+ jam();
+ MEMCOPY_NO_WORDS(keyInfo->keyData, src, KeyInfo20::DataLength - 1);
+ keyInfo->keyData[KeyInfo20::DataLength-1] = ref;
sendSignal(routeBlockref, GSN_KEYINFO20_R, signal, 25, JBB);
- keyInfo->keyData[19] = saveOne;
- for(Uint32 i = 0; i<19; i++){
- keyInfo->keyData[i] = keyInfo->keyData[keyDataIndex + i];
- }
- }//for
- keyInfo->keyData[keyLenLeft] = ref;
- sendSignal(routeBlockref, GSN_KEYINFO20_R, signal, 5 + keyLenLeft + 1, JBB);
- }
+ src += KeyInfo20::DataLength - 1;
+ keyLen -= KeyInfo20::DataLength - 1;
+ }
-}//Dblqh::sendKeyinfo20()
+ MEMCOPY_NO_WORDS(keyInfo->keyData, src, keyLen);
+ keyInfo->keyData[keyLen] = ref;
+ sendSignal(routeBlockref, GSN_KEYINFO20_R, signal,
+ KeyInfo20::HeaderLength+keyLen+1, JBB);
+ return;
+ }
+ keyInfo->keyData[0] = ref;
+ LinearSectionPtr ptr[3];
+ ptr[0].p = src;
+ ptr[0].sz = keyLen;
+ sendSignal(routeBlockref, GSN_KEYINFO20_R, signal,
+ KeyInfo20::HeaderLength+1, JBB, ptr, 1);
+ return;
+}
+
/* ------------------------------------------------------------------------
* ------- SEND SCAN_FRAGCONF TO TC THAT CONTROLS THE SCAN -------
*
* ------------------------------------------------------------------------ */
void Dblqh::sendScanFragConf(Signal* signal, Uint32 scanCompleted)
{
+ if(ERROR_INSERTED(5037)){
+ CLEAR_ERROR_INSERT_VALUE;
+ return;
+ }
+
scanptr.p->scanTcWaiting = ZFALSE;
ScanFragConf * conf = (ScanFragConf*)&signal->theData[0];
@@ -8868,7 +9042,7 @@ void Dblqh::execTRANSID_AI(Signal* signal)
ndbrequire(tcConnectptr.p->transactionState == TcConnectionrec::COPY_TUPKEY);
Uint32 * src = &signal->theData[3];
while(length > 22){
- if (saveTupattrbuf(signal, &signal->theData[3], 22) == ZOK) {
+ if (saveTupattrbuf(signal, src, 22) == ZOK) {
;
} else {
jam();
@@ -9832,9 +10006,11 @@ void Dblqh::execLCP_HOLDOPCONF(Signal* signal)
return;
} else {
jam();
+
/* NO MORE HOLDOPS NEEDED */
lcpLocptr.p->lcpLocstate = LcpLocRecord::HOLDOP_READY;
checkLcpHoldop(signal);
+
if (lcpPtr.p->lcpState == LcpRecord::LCP_WAIT_ACTIVE_FINISH) {
if (fragptr.p->activeList == RNIL) {
jam();
@@ -9852,6 +10028,7 @@ void Dblqh::execLCP_HOLDOPCONF(Signal* signal)
}//if
}//if
}//if
+
/* ----------------------- */
/* ELSE */
/* ------------------------------------------------------------------------
@@ -9924,7 +10101,6 @@ void Dblqh::execTUP_LCPSTARTED(Signal* signal)
void Dblqh::lcpStartedLab(Signal* signal)
{
checkLcpStarted(signal);
-
if (lcpPtr.p->lcpState == LcpRecord::LCP_STARTED) {
jam();
/* ----------------------------------------------------------------------
@@ -9943,7 +10119,7 @@ void Dblqh::lcpStartedLab(Signal* signal)
sendAccContOp(signal); /* START OPERATIONS IN ACC */
moveAccActiveFrag(signal); /* MOVE FROM ACC BLOCKED LIST TO ACTIVE LIST
ON FRAGMENT */
- }//if
+ }
/*---------------*/
/* ELSE */
/*-------------------------------------------------------------------------*/
@@ -10004,32 +10180,27 @@ void Dblqh::execLQH_RESTART_OP(Signal* signal)
lcpPtr.i = signal->theData[1];
ptrCheckGuard(lcpPtr, clcpFileSize, lcpRecord);
- if (fragptr.p->fragStatus == Fragrecord::BLOCKED) {
- if (lcpPtr.p->lcpState == LcpRecord::LCP_STARTED) {
- jam();
- /***********************************************************************/
- /* THIS SIGNAL CAN ONLY BE RECEIVED WHEN FRAGMENT IS BLOCKED AND
- * THE LOCAL CHECKPOINT HAS BEEN STARTED. THE BLOCKING WILL BE
- * REMOVED AS SOON AS ALL OPERATIONS HAVE BEEN STARTED.
- ***********************************************************************/
- restartOperationsLab(signal);
- return;
- } else {
- jam();
- if (lcpPtr.p->lcpState == LcpRecord::LCP_BLOCKED_COMP) {
- jam();
- /*******************************************************************>
- * THE CHECKPOINT IS COMPLETED BUT HAS NOT YET STARTED UP
- * ALL OPERATIONS AGAIN.
- * WE PERFORM THIS START-UP BEFORE CONTINUING WITH THE NEXT
- * FRAGMENT OF THE LOCAL CHECKPOINT TO AVOID ANY STRANGE ERRORS.
- *******************************************************************> */
- restartOperationsLab(signal);
- return;
- }//if
- }//if
- }//if
- ndbrequire(false);
+ ndbrequire(fragptr.p->fragStatus == Fragrecord::BLOCKED);
+ if (lcpPtr.p->lcpState == LcpRecord::LCP_STARTED) {
+ jam();
+ /***********************************************************************/
+ /* THIS SIGNAL CAN ONLY BE RECEIVED WHEN FRAGMENT IS BLOCKED AND
+ * THE LOCAL CHECKPOINT HAS BEEN STARTED. THE BLOCKING WILL BE
+ * REMOVED AS SOON AS ALL OPERATIONS HAVE BEEN STARTED.
+ ***********************************************************************/
+ restartOperationsLab(signal);
+ } else if (lcpPtr.p->lcpState == LcpRecord::LCP_BLOCKED_COMP) {
+ jam();
+ /*******************************************************************>
+ * THE CHECKPOINT IS COMPLETED BUT HAS NOT YET STARTED UP
+ * ALL OPERATIONS AGAIN.
+ * WE PERFORM THIS START-UP BEFORE CONTINUING WITH THE NEXT
+ * FRAGMENT OF THE LOCAL CHECKPOINT TO AVOID ANY STRANGE ERRORS.
+ *******************************************************************> */
+ restartOperationsLab(signal);
+ } else {
+ ndbrequire(false);
+ }
}//Dblqh::execLQH_RESTART_OP()
void Dblqh::restartOperationsLab(Signal* signal)
@@ -10082,13 +10253,13 @@ void Dblqh::restartOperationsAfterStopLab(Signal* signal)
* WHEN ARRIVING HERE THE OPERATION IS ALREADY SET IN THE ACTIVE LIST.
* THUS WE CAN IMMEDIATELY CALL THE METHODS THAT EXECUTE FROM WHERE
* THE OPERATION WAS STOPPED.
- *------------------------------------------------------------------------- */
+ *------------------------------------------------------------------------ */
switch (tcConnectptr.p->transactionState) {
case TcConnectionrec::STOPPED:
jam();
/*-----------------------------------------------------------------------
* STOPPED BEFORE TRYING TO SEND ACCKEYREQ
- *----------------------------------------------------------------------- */
+ *---------------------------------------------------------------------- */
prepareContinueAfterBlockedLab(signal);
return;
break;
@@ -10096,7 +10267,7 @@ void Dblqh::restartOperationsAfterStopLab(Signal* signal)
jam();
/* ----------------------------------------------------------------------
* STOPPED BEFORE TRYING TO SEND ACC_COMMITREQ
- * ---------------------------------------------------------------------- */
+ * --------------------------------------------------------------------- */
releaseActiveFrag(signal);
commitContinueAfterBlockedLab(signal);
return;
@@ -10105,7 +10276,7 @@ void Dblqh::restartOperationsAfterStopLab(Signal* signal)
jam();
/* ----------------------------------------------------------------------
* STOPPED BEFORE TRYING TO SEND ACC_ABORTREQ
- * ---------------------------------------------------------------------- */
+ * --------------------------------------------------------------------- */
abortContinueAfterBlockedLab(signal, true);
return;
break;
@@ -10113,7 +10284,7 @@ void Dblqh::restartOperationsAfterStopLab(Signal* signal)
jam();
/* ----------------------------------------------------------------------
* STOPPED BEFORE TRYING TO SEND NEXT_SCANREQ DURING COPY FRAGMENT
- * ---------------------------------------------------------------------- */
+ * --------------------------------------------------------------------- */
continueCopyAfterBlockedLab(signal);
return;
break;
@@ -10121,7 +10292,7 @@ void Dblqh::restartOperationsAfterStopLab(Signal* signal)
jam();
/* ----------------------------------------------------------------------
* STOPPED BEFORE TRYING TO SEND NEXT_SCANREQ DURING COPY FRAGMENT
- * ---------------------------------------------------------------------- */
+ * --------------------------------------------------------------------- */
continueFirstCopyAfterBlockedLab(signal);
return;
break;
@@ -10129,7 +10300,7 @@ void Dblqh::restartOperationsAfterStopLab(Signal* signal)
jam();
/* ----------------------------------------------------------------------
* STOPPED BEFORE TRYING TO SEND NEXT_SCANREQ DURING SCAN
- * ---------------------------------------------------------------------- */
+ * --------------------------------------------------------------------- */
tcConnectptr.p->transactionState = TcConnectionrec::SCAN_STATE_USED;
continueFirstScanAfterBlockedLab(signal);
return;
@@ -10138,7 +10309,7 @@ void Dblqh::restartOperationsAfterStopLab(Signal* signal)
jam();
/* ----------------------------------------------------------------------
* STOPPED BEFORE TRYING TO SEND NEXT_SCANREQ DURING SCAN
- * ---------------------------------------------------------------------- */
+ * --------------------------------------------------------------------- */
tcConnectptr.p->transactionState = TcConnectionrec::SCAN_STATE_USED;
continueAfterCheckLcpStopBlocked(signal);
return;
@@ -10147,7 +10318,7 @@ void Dblqh::restartOperationsAfterStopLab(Signal* signal)
jam();
/* ----------------------------------------------------------------------
* STOPPED BEFORE TRYING TO SEND NEXT_SCANREQ DURING SCAN
- * ---------------------------------------------------------------------- */
+ * --------------------------------------------------------------------- */
tcConnectptr.p->transactionState = TcConnectionrec::SCAN_STATE_USED;
continueScanAfterBlockedLab(signal);
return;
@@ -10157,7 +10328,7 @@ void Dblqh::restartOperationsAfterStopLab(Signal* signal)
/* ----------------------------------------------------------------------
* STOPPED BEFORE TRYING TO SEND NEXT_SCANREQ DURING RELEASE
* LOCKS IN SCAN
- * ---------------------------------------------------------------------- */
+ * --------------------------------------------------------------------- */
tcConnectptr.p->transactionState = TcConnectionrec::SCAN_STATE_USED;
continueScanReleaseAfterBlockedLab(signal);
return;
@@ -10166,7 +10337,7 @@ void Dblqh::restartOperationsAfterStopLab(Signal* signal)
jam();
/* ----------------------------------------------------------------------
* STOPPED BEFORE TRYING TO SEND NEXT_SCANREQ DURING CLOSE OF SCAN
- * ---------------------------------------------------------------------- */
+ * --------------------------------------------------------------------- */
continueCloseScanAfterBlockedLab(signal);
return;
break;
@@ -10174,7 +10345,7 @@ void Dblqh::restartOperationsAfterStopLab(Signal* signal)
jam();
/* ----------------------------------------------------------------------
* STOPPED BEFORE TRYING TO SEND NEXT_SCANREQ DURING CLOSE OF COPY
- * ---------------------------------------------------------------------- */
+ * --------------------------------------------------------------------- */
continueCloseCopyAfterBlockedLab(signal);
return;
break;
@@ -10300,7 +10471,12 @@ void Dblqh::contChkpNextFragLab(Signal* signal)
* ----------------------------------------------------------------------- */
if (fragptr.p->fragStatus == Fragrecord::BLOCKED) {
jam();
+ /**
+ * LCP of fragment complete
+ * but restarting of operations isn't
+ */
lcpPtr.p->lcpState = LcpRecord::LCP_BLOCKED_COMP;
+ //restartOperationsLab(signal);
return;
}//if
@@ -10471,6 +10647,8 @@ void Dblqh::execEND_LCPCONF(Signal* signal)
clcpCompletedState = LCP_IDLE;
}//if
}//if
+ lcpPtr.i = 0;
+ ptrAss(lcpPtr, lcpRecord);
sendLCP_COMPLETE_REP(signal, lcpPtr.p->currentFragment.lcpFragOrd.lcpId);
}//Dblqh::execEND_LCPCONF()
@@ -10577,25 +10755,25 @@ void Dblqh::checkLcpStarted(Signal* signal)
terrorCode = ZOK;
clsLcpLocptr.i = lcpPtr.p->firstLcpLocAcc;
+ int i = 0;
do {
ptrCheckGuard(clsLcpLocptr, clcpLocrecFileSize, lcpLocRecord);
- if (clsLcpLocptr.p->lcpLocstate != LcpLocRecord::ACC_STARTED) {
- ndbrequire((clsLcpLocptr.p->lcpLocstate == LcpLocRecord::ACC_COMPLETED) ||
- (clsLcpLocptr.p->lcpLocstate == LcpLocRecord::ACC_WAIT_STARTED));
+ if (clsLcpLocptr.p->lcpLocstate == LcpLocRecord::ACC_WAIT_STARTED){
return;
}//if
clsLcpLocptr.i = clsLcpLocptr.p->nextLcpLoc;
+ i++;
} while (clsLcpLocptr.i != RNIL);
+ i = 0;
clsLcpLocptr.i = lcpPtr.p->firstLcpLocTup;
do {
ptrCheckGuard(clsLcpLocptr, clcpLocrecFileSize, lcpLocRecord);
- if (clsLcpLocptr.p->lcpLocstate != LcpLocRecord::TUP_STARTED) {
- ndbrequire((clsLcpLocptr.p->lcpLocstate == LcpLocRecord::TUP_COMPLETED) ||
- (clsLcpLocptr.p->lcpLocstate == LcpLocRecord::TUP_WAIT_STARTED));
+ if (clsLcpLocptr.p->lcpLocstate == LcpLocRecord::TUP_WAIT_STARTED){
return;
}//if
clsLcpLocptr.i = clsLcpLocptr.p->nextLcpLoc;
+ i++;
} while (clsLcpLocptr.i != RNIL);
lcpPtr.p->lcpState = LcpRecord::LCP_STARTED;
}//Dblqh::checkLcpStarted()
@@ -10753,18 +10931,28 @@ void Dblqh::sendAccContOp(Signal* signal)
{
LcpLocRecordPtr sacLcpLocptr;
+ int count = 0;
sacLcpLocptr.i = lcpPtr.p->firstLcpLocAcc;
do {
ptrCheckGuard(sacLcpLocptr, clcpLocrecFileSize, lcpLocRecord);
sacLcpLocptr.p->accContCounter = 0;
-/* ------------------------------------------------------------------------- */
-/*SEND START OPERATIONS TO ACC AGAIN */
-/* ------------------------------------------------------------------------- */
- signal->theData[0] = lcpPtr.p->lcpAccptr;
- signal->theData[1] = sacLcpLocptr.p->locFragid;
- sendSignal(fragptr.p->accBlockref, GSN_ACC_CONTOPREQ, signal, 2, JBA);
+ if(sacLcpLocptr.p->lcpLocstate == LcpLocRecord::ACC_STARTED){
+ /* ------------------------------------------------------------------- */
+ /*SEND START OPERATIONS TO ACC AGAIN */
+ /* ------------------------------------------------------------------- */
+ signal->theData[0] = lcpPtr.p->lcpAccptr;
+ signal->theData[1] = sacLcpLocptr.p->locFragid;
+ sendSignal(fragptr.p->accBlockref, GSN_ACC_CONTOPREQ, signal, 2, JBA);
+ count++;
+ } else if(sacLcpLocptr.p->lcpLocstate == LcpLocRecord::ACC_COMPLETED){
+ signal->theData[0] = sacLcpLocptr.i;
+ sendSignal(reference(), GSN_ACC_CONTOPCONF, signal, 1, JBB);
+ } else {
+ ndbrequire(false);
+ }
sacLcpLocptr.i = sacLcpLocptr.p->nextLcpLoc;
} while (sacLcpLocptr.i != RNIL);
+
}//Dblqh::sendAccContOp()
/* ------------------------------------------------------------------------- */
@@ -11897,18 +12085,18 @@ void Dblqh::writeLogfileLab(Signal* signal)
/* WRITE. */
/*---------------------------------------------------------------------------*/
switch (logFilePtr.p->fileChangeState) {
-#if 0
- case LogFileRecord::BOTH_WRITES_ONGOING:
- jam();
- ndbout_c("not crashing!!");
- // Fall-through
-#endif
case LogFileRecord::NOT_ONGOING:
jam();
checkGcpCompleted(signal,
((lfoPtr.p->lfoPageNo + lfoPtr.p->noPagesRw) - 1),
lfoPtr.p->lfoWordWritten);
break;
+#if 0
+ case LogFileRecord::BOTH_WRITES_ONGOING:
+ jam();
+ ndbout_c("not crashing!!");
+ // Fall-through
+#endif
case LogFileRecord::WRITE_PAGE_ZERO_ONGOING:
case LogFileRecord::LAST_WRITE_ONGOING:
jam();
@@ -12996,20 +13184,11 @@ void Dblqh::execSTART_FRAGREQ(Signal* signal)
ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
if (!getFragmentrec(signal, fragId)) {
- jam();
- /* ----------------------------------------------------------------------
- * FRAGMENT WAS NOT DEFINED YET. PUT IT IN. IF NO LOCAL CHECKPOINT EXISTED
- * THEN THE FRAGMENT HAS ALREADY BEEN ADDED.
- * ---------------------------------------------------------------------- */
- if (!insertFragrec(signal, fragId)) {
- jam();
- startFragRefLab(signal);
- return;
- }//if
+ startFragRefLab(signal);
+ return;
}//if
tabptr.p->tableStatus = Tablerec::TABLE_DEFINED;
- initFragrec(signal, tabptr.i, fragId, ZPRIMARY_NODE);
initFragrecSr(signal);
if (startFragReq->lcpNo == ZNIL) {
jam();
@@ -13085,11 +13264,12 @@ void Dblqh::execSR_FRAGIDCONF(Signal* signal)
Uint32 noLocFrag = srFragidConf->noLocFrag;
ndbrequire(noLocFrag == 2);
Uint32 fragid[2];
- for (Uint32 i = 0; i < noLocFrag; i++) {
+ Uint32 i;
+ for (i = 0; i < noLocFrag; i++) {
fragid[i] = srFragidConf->fragId[i];
}//for
- for (Uint32 i = 0; i < noLocFrag; i++) {
+ for (i = 0; i < noLocFrag; i++) {
jam();
Uint32 fragId = fragid[i];
/* ----------------------------------------------------------------------
@@ -13495,14 +13675,22 @@ void Dblqh::execSTART_EXEC_SR(Signal* signal)
* ALSO SEND START_FRAGCONF TO DIH AND SET THE STATE TO ACTIVE ON THE
* FRAGMENT.
* ------------------------------------------------------------------- */
+ Uint32 next = fragptr.p->nextFrag;
if (prevFragptr.i != RNIL) {
jam();
ptrCheckGuard(prevFragptr, cfragrecFileSize, fragrecord);
- prevFragptr.p->nextFrag = fragptr.p->nextFrag;
+ prevFragptr.p->nextFrag = next;
} else {
jam();
- cfirstCompletedFragSr = fragptr.p->nextFrag;
+ cfirstCompletedFragSr = next;
}//if
+
+ /**
+ * Put fragment on list which has completed REDO log
+ */
+ fragptr.p->nextFrag = c_redo_log_complete_frags;
+ c_redo_log_complete_frags = fragptr.i;
+
fragptr.p->fragStatus = Fragrecord::FSACTIVE;
fragptr.p->logFlag = Fragrecord::STATE_TRUE;
signal->theData[0] = fragptr.p->srUserptr;
@@ -13514,7 +13702,7 @@ void Dblqh::execSTART_EXEC_SR(Signal* signal)
* THIS IS PERFORMED BY KEEPING PREV_FRAGPTR AS PREV_FRAGPTR BUT MOVING
* FRAGPTR TO THE NEXT FRAGMENT IN THE LIST.
* ------------------------------------------------------------------- */
- fragptr.i = fragptr.p->nextFrag;
+ fragptr.i = next;
}//if
signal->theData[0] = fragptr.i;
signal->theData[1] = prevFragptr.i;
@@ -14933,6 +15121,11 @@ void Dblqh::openSrFourthPhaseLab(Signal* signal)
void Dblqh::readSrFourthPhaseLab(Signal* signal)
{
+ if(c_diskless){
+ jam();
+ logPagePtr.p->logPageWord[ZPOS_LOG_LAP] = 1;
+ }
+
/* ------------------------------------------------------------------------
* INITIALISE ALL LOG PART INFO AND LOG FILE INFO THAT IS NEEDED TO
* START UP THE SYSTEM.
@@ -14961,6 +15154,7 @@ void Dblqh::readSrFourthPhaseLab(Signal* signal)
logPartPtr.p->logLap = logPagePtr.p->logPageWord[ZPOS_LOG_LAP];
logFilePtr.p->currentFilepage = logPartPtr.p->headPageNo;
logFilePtr.p->currentLogpage = logPagePtr.i;
+
initLogpage(signal);
logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = logPartPtr.p->headPageIndex;
logFilePtr.p->remainingWordsInMbyte =
@@ -15120,6 +15314,17 @@ void Dblqh::srFourthComp(Signal* signal)
conf->startingNodeId = getOwnNodeId();
sendSignal(cmasterDihBlockref, GSN_START_RECCONF, signal,
StartRecConf::SignalLength, JBB);
+
+ if(cstartType == NodeState::ST_SYSTEM_RESTART){
+ fragptr.i = c_redo_log_complete_frags;
+ while(fragptr.i != RNIL){
+ ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
+ signal->theData[0] = fragptr.p->tabRef;
+ signal->theData[1] = fragptr.p->fragId;
+ sendSignal(DBACC_REF, GSN_EXPANDCHECK2, signal, 2, JBB);
+ fragptr.i = fragptr.p->nextFrag;
+ }
+ }
} else {
ndbrequire(false);
}//if
@@ -15657,7 +15862,7 @@ void Dblqh::completedLogPage(Signal* signal, Uint32 clpType)
/* ---------------------------------------------------------------- */
void Dblqh::deleteFragrec(Uint32 fragId)
{
- Uint32 indexFound;
+ Uint32 indexFound= RNIL;
fragptr.i = RNIL;
for (Uint32 i = (NO_OF_FRAG_PER_NODE - 1); (Uint32)~i; i--) {
jam();
@@ -15810,6 +16015,7 @@ void Dblqh::initialiseAttrbuf(Signal* signal)
for (attrinbufptr.i = 0;
attrinbufptr.i < cattrinbufFileSize;
attrinbufptr.i++) {
+ refresh_watch_dog();
ptrAss(attrinbufptr, attrbuf);
attrinbufptr.p->attrbuf[ZINBUF_NEXT] = attrinbufptr.i + 1;
}//for
@@ -15832,6 +16038,7 @@ void Dblqh::initialiseDatabuf(Signal* signal)
{
if (cdatabufFileSize != 0) {
for (databufptr.i = 0; databufptr.i < cdatabufFileSize; databufptr.i++) {
+ refresh_watch_dog();
ptrAss(databufptr, databuf);
databufptr.p->nextDatabuf = databufptr.i + 1;
}//for
@@ -15853,6 +16060,7 @@ void Dblqh::initialiseFragrec(Signal* signal)
{
if (cfragrecFileSize != 0) {
for (fragptr.i = 0; fragptr.i < cfragrecFileSize; fragptr.i++) {
+ refresh_watch_dog();
ptrAss(fragptr, fragrecord);
fragptr.p->fragStatus = Fragrecord::FREE;
fragptr.p->fragActiveStatus = ZFALSE;
@@ -15985,6 +16193,7 @@ void Dblqh::initialiseLogPage(Signal* signal)
{
if (clogPageFileSize != 0) {
for (logPagePtr.i = 0; logPagePtr.i < clogPageFileSize; logPagePtr.i++) {
+ refresh_watch_dog();
ptrAss(logPagePtr, logPageRecord);
logPagePtr.p->logPageWord[ZNEXT_PAGE] = logPagePtr.i + 1;
}//for
@@ -16040,17 +16249,18 @@ void Dblqh::initialisePageRef(Signal* signal)
void Dblqh::initialiseRecordsLab(Signal* signal, Uint32 data,
Uint32 retRef, Uint32 retData)
{
+ Uint32 i;
switch (data) {
case 0:
jam();
- for (Uint32 i = 0; i < MAX_NDB_NODES; i++) {
+ for (i = 0; i < MAX_NDB_NODES; i++) {
cnodeSrState[i] = ZSTART_SR;
cnodeExecSrState[i] = ZSTART_SR;
}//for
- for (Uint32 i = 0; i < 1024; i++) {
+ for (i = 0; i < 1024; i++) {
ctransidHash[i] = RNIL;
}//for
- for (Uint32 i = 0; i < 4; i++) {
+ for (i = 0; i < 4; i++) {
cactiveCopy[i] = RNIL;
}//for
cnoActiveCopy = 0;
@@ -16162,6 +16372,7 @@ void Dblqh::initialiseScanrec(Signal* signal)
DLList<ScanRecord> tmp(c_scanRecordPool);
while (tmp.seize(scanptr)){
//new (scanptr.p) ScanRecord();
+ refresh_watch_dog();
scanptr.p->scanType = ScanRecord::ST_IDLE;
scanptr.p->scanState = ScanRecord::SCAN_FREE;
scanptr.p->scanTcWaiting = ZFALSE;
@@ -16179,6 +16390,7 @@ void Dblqh::initialiseTabrec(Signal* signal)
{
if (ctabrecFileSize != 0) {
for (tabptr.i = 0; tabptr.i < ctabrecFileSize; tabptr.i++) {
+ refresh_watch_dog();
ptrAss(tabptr, tablerec);
tabptr.p->tableStatus = Tablerec::NOT_DEFINED;
tabptr.p->usageCount = 0;
@@ -16200,6 +16412,7 @@ void Dblqh::initialiseTcrec(Signal* signal)
for (tcConnectptr.i = 0;
tcConnectptr.i < ctcConnectrecFileSize;
tcConnectptr.i++) {
+ refresh_watch_dog();
ptrAss(tcConnectptr, tcConnectionrec);
tcConnectptr.p->transactionState = TcConnectionrec::TC_NOT_CONNECTED;
tcConnectptr.p->tcScanRec = RNIL;
@@ -16277,6 +16490,7 @@ void Dblqh::initFragrec(Signal* signal,
fragptr.p->execSrNoReplicas = 0;
fragptr.p->fragDistributionKey = 0;
fragptr.p->activeTcCounter = 0;
+ fragptr.p->tableFragptr = RNIL;
}//Dblqh::initFragrec()
/* ==========================================================================
@@ -18004,7 +18218,7 @@ Dblqh::execDUMP_STATE_ORD(Signal* signal)
infoEvent(" lcpQueued=%d reportEmpty=%d",
TlcpPtr.p->lcpQueued,
TlcpPtr.p->reportEmpty);
- char buf[TlcpPtr.p->m_EMPTY_LCP_REQ.TextLength+1];
+ char buf[8*_NDB_NODE_BITMASK_SIZE+1];
infoEvent(" m_EMPTY_LCP_REQ=%d",
TlcpPtr.p->m_EMPTY_LCP_REQ.getText(buf));
diff --git a/ndb/src/kernel/blocks/dbtc/Dbtc.hpp b/ndb/src/kernel/blocks/dbtc/Dbtc.hpp
index c87712e1887..6e32216557c 100644
--- a/ndb/src/kernel/blocks/dbtc/Dbtc.hpp
+++ b/ndb/src/kernel/blocks/dbtc/Dbtc.hpp
@@ -139,6 +139,7 @@
#define ZNOT_FOUND 626
#define ZALREADYEXIST 630
#define ZINCONSISTENTHASHINDEX 892
+#define ZNOTUNIQUE 893
#endif
class Dbtc: public SimulatedBlock {
@@ -235,7 +236,6 @@ public:
enum ReturnSignal {
RS_NO_RETURN = 0,
RS_TCKEYCONF = 1,
- RS_TCKEYREF = 2,
RS_TC_COMMITCONF = 3,
RS_TCROLLBACKCONF = 4,
RS_TCROLLBACKREP = 5
@@ -699,7 +699,7 @@ public:
UintR lqhkeyreqrec;
AbortState abortState;
Uint32 buddyPtr;
- Uint8 unused;
+ Uint8 m_exec_flag;
Uint8 unused2;
Uint8 takeOverRec;
Uint8 currentReplicaNo;
@@ -993,11 +993,94 @@ public:
typedef Ptr<TableRecord> TableRecordPtr;
/**
+ * There is max 16 ScanFragRec's for
+ * each scan started in TC. Each ScanFragRec is used by
+ * a scan fragment "process" that scans one fragment at a time.
+ * It will receive max 16 tuples in each request
+ */
+ struct ScanFragRec {
+ ScanFragRec(){
+ stopFragTimer();
+ lqhBlockref = 0;
+ scanFragState = IDLE;
+ scanRec = RNIL;
+ }
+ /**
+ * ScanFragState
+ * WAIT_GET_PRIMCONF : Waiting for DIGETPRIMCONF when starting a new
+ * fragment scan
+ * LQH_ACTIVE : The scan process has sent a command to LQH and is
+ * waiting for the response
+ * LQH_ACTIVE_CLOSE : The scan process has sent close to LQH and is
+ * waiting for the response
+ * DELIVERED : The result have been delivered, this scan frag process
+ * are waiting for a SCAN_NEXTREQ to tell us to continue scanning
+ * RETURNING_FROM_DELIVERY : SCAN_NEXTREQ received and continuing scan
+ * soon
+ * QUEUED_FOR_DELIVERY : Result queued in TC and waiting for delivery
+ * to API
+ * COMPLETED : The fragment scan processes has completed and finally
+ * sent a SCAN_PROCCONF
+ */
+ enum ScanFragState {
+ IDLE = 0,
+ WAIT_GET_PRIMCONF = 1,
+ LQH_ACTIVE = 2,
+ DELIVERED = 4,
+ QUEUED_FOR_DELIVERY = 6,
+ COMPLETED = 7
+ };
+ // Timer for checking timeout of this fragment scan
+ Uint32 scanFragTimer;
+
+ // Id of the current scanned fragment
+ Uint32 scanFragId;
+
+ // Blockreference of LQH
+ BlockReference lqhBlockref;
+
+ // getNodeInfo.m_connectCount, set at seize used so that
+ // I don't accidently kill a starting node
+ Uint32 m_connectCount;
+
+ // State of this fragment scan
+ ScanFragState scanFragState;
+
+ // Id of the ScanRecord this fragment scan belongs to
+ Uint32 scanRec;
+
+ // The maximum number of operations that can be scanned before
+ // returning to TC
+ Uint16 scanFragConcurrency;
+
+ inline void startFragTimer(Uint32 timeVal){
+ scanFragTimer = timeVal;
+ }
+ inline void stopFragTimer(void){
+ scanFragTimer = 0;
+ }
+
+ Uint32 m_ops;
+ Uint32 m_chksum;
+ Uint32 m_apiPtr;
+ Uint32 m_totalLen;
+ union {
+ Uint32 nextPool;
+ Uint32 nextList;
+ };
+ Uint32 prevList;
+ };
+
+ typedef Ptr<ScanFragRec> ScanFragRecPtr;
+ typedef LocalDLList<ScanFragRec> ScanFragList;
+
+ /**
* Each scan allocates one ScanRecord to store information
* about the current scan
*
*/
struct ScanRecord {
+ ScanRecord() {}
/** NOTE! This is the old comment for ScanState. - MASV
* STATE TRANSITIONS OF SCAN_STATE. SCAN_STATE IS THE STATE
* VARIABLE OF THE RECEIVE AND DELIVERY PROCESS.
@@ -1057,161 +1140,71 @@ public:
WAIT_SCAN_TAB_INFO = 1,
WAIT_AI = 2,
WAIT_FRAGMENT_COUNT = 3,
- SCAN_NEXT_ORDERED = 4,
- QUEUED_DELIVERED = 5,
- DELIVERED = 6,
- CLOSING_SCAN = 7
+ RUNNING = 4,
+ CLOSING_SCAN = 5
};
+
// State of this scan
ScanState scanState;
- // References to ScanFragRecs
- Uint32 scanFragrec[16];
- // Refrences to ScanOperationRecords
- Uint32 scanOprec[16];
- // Number of ScanOperationRecords allocated
- Uint32 noScanOprec;
+
+ DLList<ScanFragRec>::Head m_running_scan_frags; // Currently in LQH
+ union { Uint32 m_queued_count; Uint32 scanReceivedOperations; };
+ DLList<ScanFragRec>::Head m_queued_scan_frags; // In TC !sent to API
+ DLList<ScanFragRec>::Head m_delivered_scan_frags;// Delivered to API
+ DLList<ScanFragRec>::Head m_completed_scan_frags;// Completed
+
// Id of the next fragment to be scanned. Used by scan fragment
// processes when they are ready for the next fragment
Uint32 scanNextFragId;
+
// Total number of fragments in the table we are scanning
Uint32 scanNoFrag;
+
// Index of next ScanRecords when in free list
Uint32 nextScan;
+
// Length of expected attribute information
Uint32 scanAiLength;
+
// Reference to ApiConnectRecord
Uint32 scanApiRec;
+
// Reference to TcConnectRecord
Uint32 scanTcrec;
+
// Number of scan frag processes that belong to this scan
Uint32 scanParallel;
- // The number of recieved operations so far
- Uint32 scanReceivedOperations;
+
// Schema version used by this scan
Uint32 scanSchemaVersion;
+
// Index of stored procedure belonging to this scan
Uint32 scanStoredProcId;
+
// The index of table that is scanned
Uint32 scanTableref;
+
// Number of operation records per scanned fragment
Uint16 noOprecPerFrag;
- // The number of SCAN_TABINFO to receive
- Uint16 noScanTabInfo;
- // The number of SCAN_TABINFO received so far
- Uint16 scanTabInfoReceived;
- // apiIsClosed indicates if it's ok to release all resources
- // and send a response to the API
- // If it's false resources should not be released wait for API
- // to close the scan
- bool apiIsClosed;
- // The number of scan frag processes that have completed their task
- Uint8 scanProcessesCompleted;
- // This variable is ZFALSE as long as any scan process is still alive
- // It is ZTRUE as soon as all scan processes have been stopped
- Uint8 scanCompletedStatus;
+
// 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;
+
+ // Close is ordered
+ bool m_close_scan_req;
};
typedef Ptr<ScanRecord> ScanRecordPtr;
- /**
- * Each scan has max 16 ScanOperationRecords
- * they are used for storing data to be sent to the api
- */
- struct ScanOperationRecord {
- // Reference to the scan operation in api
- Uint32 apiOpptr[16];
- // Index and length of all recieved operations
- // They will be cached here until SCAN_TABCONF is sent to api
- Uint32 scanOpLength[16];
- // Next ScanOperationRecord when in free list
- Uint32 nextScanOp;
- }; /* p2c: size = 132 bytes */
-
- typedef Ptr<ScanOperationRecord> ScanOperationRecordPtr;
-
- /**
- * There is max 16 ScanFragRec's for
- * each scan started in TC. Each ScanFragRec is used by
- * a scan fragment "process" that scans one fragment at a time.
- * It will receive max 16 tuples in each request
- */
- struct ScanFragRec {
- /**
- * ScanFragState
- * WAIT_GET_PRIMCONF : Waiting for DIGETPRIMCONF when starting a new
- * fragment scan
- * LQH_ACTIVE : The scan process has sent a command to LQH and is
- * waiting for the response
- * LQH_ACTIVE_CLOSE : The scan process has sent close to LQH and is
- * waiting for the response
- * DELIVERED : The result have been delivered, this scan frag process
- * are waiting for a SCAN_NEXTREQ to tell us to continue scanning
- * RETURNING_FROM_DELIVERY : SCAN_NEXTREQ received and continuing scan
- * soon
- * QUEUED_FOR_DELIVERY : Result queued in TC and waiting for delivery
- * to API
- * COMPLETED : The fragment scan processes has completed and finally
- * sent a SCAN_PROCCONF
- */
- enum ScanFragState {
- IDLE = 0,
- WAIT_GET_PRIMCONF = 1,
- LQH_ACTIVE = 2,
- LQH_ACTIVE_CLOSE = 3,
- DELIVERED = 4,
- RETURNING_FROM_DELIVERY = 5,
- QUEUED_FOR_DELIVERY = 6,
- COMPLETED = 7
- };
- // Timer for checking timeout of this fragment scan
- Uint32 scanFragTimer;
- // Id of the current scanned fragment
- Uint32 scanFragId;
- // Blockreference of LQH
- BlockReference lqhBlockref;
- // getNodeInfo.m_connectCount, set at seize used so that
- // I don't accidently kill a starting node
- Uint32 m_connectCount;
- // State of this fragment scan
- ScanFragState scanFragState;
- // Id of the ScanRecord this fragment scan belongs to
- Uint32 scanRec;
- // Index of next ScanFragRec, when in list of
- // free ScanFragRec's
- Uint32 nextScanFrag;
- // Process id of this scan process within the total scan
- Uint32 scanFragProcId;
- // Node where current fragment resides
- NodeId scanFragNodeId;
- // Index of where to store the result in ScanRecord
- Uint16 scanIndividual;
- // The maximum number of operations that can be scanned before
- // returning to TC
- Uint16 scanFragConcurrency;
- // Current status of the fragment scan
- // * 0 = NOT COMPLETED
- // * 1 = COMPLETED
- // * 2 = CLOSED
- Uint8 scanFragCompletedStatus;
-
- inline void startFragTimer(Uint32 timeVal){
- scanFragTimer = timeVal;
- }
- inline void stopFragTimer(void){
- scanFragTimer = 0;
- }
- };
-
- typedef Ptr<ScanFragRec> ScanFragRecPtr;
-
/* **********************************************************************$ */
/* ******$ DATA BUFFER ******$ */
/* */
@@ -1369,6 +1362,7 @@ private:
void execCREATE_TAB_REQ(Signal* signal);
void execPREP_DROP_TAB_REQ(Signal* signal);
void execDROP_TAB_REQ(Signal* signal);
+ void execWAIT_DROP_TAB_REF(Signal* signal);
void execWAIT_DROP_TAB_CONF(Signal* signal);
void checkWaitDropTabFailedLqh(Signal*, Uint32 nodeId, Uint32 tableId);
void execALTER_TAB_REQ(Signal* signal);
@@ -1403,7 +1397,7 @@ private:
void sendCompleteLqh(Signal* signal,
TcConnectRecord * const regTcPtr);
void sendTCKEY_FAILREF(Signal* signal, const ApiConnectRecord *);
- void sendTCKEY_FAILCONF(Signal* signal, const ApiConnectRecord *);
+ void sendTCKEY_FAILCONF(Signal* signal, ApiConnectRecord *);
void checkStartTimeout(Signal* signal);
void checkStartFragTimeout(Signal* signal);
void timeOutFoundFragLab(Signal* signal, Uint32 TscanConPtr);
@@ -1428,23 +1422,17 @@ private:
Uint32 buddyPtr,
UintR transid1,
UintR transid2);
- void initScanOprec(Signal* signal);
- void initScanrec(Signal* signal,
+ void initScanrec(ScanRecordPtr, const class ScanTabReq*,
const UintR scanParallel,
const UintR noOprecPerFrag);
void initScanfragrec(Signal* signal);
- void releaseScanrec(Signal* signal);
- void releaseScanResources(Signal* signal);
- void releaseScanFragrec(Signal* signal);
- void releaseScanOprec(Signal* signal);
- void seizeScanrec(Signal* signal);
- void seizeScanFragrec(Signal* signal);
- void seizeScanOprec(Signal* signal);
- void sendScanFragReq(Signal* signal);
- void sendScanTabConf(Signal* signal);
- void sendScanProcConf(Signal* signal);
- void setScanReceived(Signal* signal, Uint32 noCompletedOps);
-
+ void releaseScanResources(ScanRecordPtr);
+ ScanRecordPtr seizeScanrec(Signal* signal);
+ void sendScanFragReq(Signal* signal, ScanRecord*, ScanFragRec*);
+ void sendScanTabConf(Signal* signal, ScanRecord*);
+ void close_scan_req(Signal*, ScanRecordPtr, bool received_req);
+ void close_scan_req_send_conf(Signal*, ScanRecordPtr);
+
void checkGcp(Signal* signal);
void commitGciHandling(Signal* signal, UintR Tgci);
void copyApi(Signal* signal);
@@ -1473,12 +1461,12 @@ private:
void releaseApiCon(Signal* signal, UintR aApiConnectPtr);
void releaseApiConCopy(Signal* signal);
void releaseApiConnectFail(Signal* signal);
- void releaseAttrinfo(Signal* signal);
+ void releaseAttrinfo();
void releaseGcp(Signal* signal);
- void releaseKeys(Signal* signal);
+ void releaseKeys();
void releaseSimpleRead(Signal* signal);
void releaseDirtyWrite(Signal* signal);
- void releaseTcCon(Signal* signal);
+ void releaseTcCon();
void releaseTcConnectFail(Signal* signal);
void releaseTransResources(Signal* signal);
void saveAttrbuf(Signal* signal);
@@ -1577,11 +1565,11 @@ private:
void systemErrorLab(Signal* signal);
void sendSignalErrorRefuseLab(Signal* signal);
void scanTabRefLab(Signal* signal, Uint32 errCode);
- void diFcountReqLab(Signal* signal);
+ void diFcountReqLab(Signal* signal, ScanRecordPtr);
void signalErrorRefuseLab(Signal* signal);
void abort080Lab(Signal* signal);
void packKeyData000Lab(Signal* signal, BlockReference TBRef);
- void abortScanLab(Signal* signal, Uint32 errCode);
+ void abortScanLab(Signal* signal, ScanRecordPtr, Uint32 errCode);
void sendAbortedAfterTimeout(Signal* signal, int Tcheck);
void abort010Lab(Signal* signal);
void abort015Lab(Signal* signal);
@@ -1609,7 +1597,7 @@ private:
void attrinfo020Lab(Signal* signal);
void scanReleaseResourcesLab(Signal* signal);
void scanCompletedLab(Signal* signal);
- void scanFragError(Signal* signal, Uint32 errorCode);
+ void scanError(Signal* signal, ScanRecordPtr, Uint32 errorCode);
void diverify010Lab(Signal* signal);
void intstartphase2x010Lab(Signal* signal);
void intstartphase3x010Lab(Signal* signal);
@@ -1638,6 +1626,8 @@ private:
void checkScanActiveInFailedLqh(Signal* signal,
Uint32 scanPtrI,
Uint32 failedNodeId);
+ void checkScanFragList(Signal*, Uint32 failedNodeId, ScanRecord * scanP,
+ LocalDLList<ScanFragRec>::Head&);
// Initialisation
void initData();
@@ -1717,20 +1707,12 @@ private:
ApiConnectRecordPtr timeOutptr;
ScanRecord *scanRecord;
- ScanRecordPtr scanptr;
UintR cscanrecFileSize;
- ScanOperationRecord *scanOperationRecord;
- ScanOperationRecordPtr scanOpptr;
- UintR cscanOprecFileSize;
-
- ScanFragRec *scanFragmentRecord;
+ UnsafeArrayPool<ScanFragRec> c_scan_frag_pool;
ScanFragRecPtr scanFragptr;
- UintR cscanFragrecFileSize;
- UintR cfirstfreeScanOprec;
- UintR cnoFreeScanOprec;
- UintR cfirstfreeScanFragrec;
+ UintR cscanFragrecFileSize;
UintR cdatabufFilesize;
BlockReference cdictblockref;
diff --git a/ndb/src/kernel/blocks/dbtc/DbtcInit.cpp b/ndb/src/kernel/blocks/dbtc/DbtcInit.cpp
index 61ecca513f0..6803c3609ed 100644
--- a/ndb/src/kernel/blocks/dbtc/DbtcInit.cpp
+++ b/ndb/src/kernel/blocks/dbtc/DbtcInit.cpp
@@ -35,7 +35,6 @@ void Dbtc::initData()
cgcpFilesize = ZGCP_FILESIZE;
cscanrecFileSize = ZSCANREC_FILE_SIZE;
cscanFragrecFileSize = ZSCAN_FRAGREC_FILE_SIZE;
- cscanOprecFileSize = ZSCAN_OPREC_FILE_SIZE;
ctabrecFilesize = ZTABREC_FILESIZE;
ctcConnectFilesize = ZTC_CONNECT_FILESIZE;
cdihblockref = DBDIH_REF;
@@ -49,8 +48,6 @@ void Dbtc::initData()
hostRecord = 0;
tableRecord = 0;
scanRecord = 0;
- scanOperationRecord = 0;
- scanFragmentRecord = 0;
databufRecord = 0;
attrbufRecord = 0;
gcpRecord = 0;
@@ -143,16 +140,19 @@ void Dbtc::initRecords()
sizeof(ScanRecord),
cscanrecFileSize);
- scanOperationRecord = (ScanOperationRecord*)
- allocRecord("ScanOperationRecord",
- sizeof(ScanOperationRecord),
- cscanOprecFileSize);
- scanFragmentRecord = (ScanFragRec*)
- allocRecord("ScanFragRec",
- sizeof(ScanFragRec),
- cscanFragrecFileSize);
+ c_scan_frag_pool.setSize(cscanFragrecFileSize);
+ {
+ ScanFragRecPtr ptr;
+ SLList<ScanFragRec> tmp(c_scan_frag_pool);
+ while(tmp.seize(ptr)) {
+ new (ptr.p) ScanFragRec();
+ }
+ tmp.release();
+ }
+ indexOps.release();
+
databufRecord = (DatabufRecord*)allocRecord("DatabufRecord",
sizeof(DatabufRecord),
cdatabufFilesize);
@@ -213,10 +213,7 @@ Dbtc::Dbtc(const class Configuration & conf):
addRecSignal(GSN_ATTRINFO, &Dbtc::execATTRINFO);
addRecSignal(GSN_CONTINUEB, &Dbtc::execCONTINUEB);
addRecSignal(GSN_KEYINFO, &Dbtc::execKEYINFO);
- addRecSignal(GSN_SCAN_TABINFO, &Dbtc::execSCAN_TABINFO);
addRecSignal(GSN_SCAN_NEXTREQ, &Dbtc::execSCAN_NEXTREQ);
- addRecSignal(GSN_SCAN_PROCREQ, &Dbtc::execSCAN_PROCREQ);
- addRecSignal(GSN_SCAN_PROCCONF, &Dbtc::execSCAN_PROCCONF);
addRecSignal(GSN_TAKE_OVERTCREQ, &Dbtc::execTAKE_OVERTCREQ);
addRecSignal(GSN_TAKE_OVERTCCONF, &Dbtc::execTAKE_OVERTCCONF);
addRecSignal(GSN_LQHKEYREF, &Dbtc::execLQHKEYREF);
@@ -290,11 +287,29 @@ Dbtc::Dbtc(const class Configuration & conf):
//addRecSignal(GSN_CREATE_TAB_REQ, &Dbtc::execCREATE_TAB_REQ);
addRecSignal(GSN_DROP_TAB_REQ, &Dbtc::execDROP_TAB_REQ);
addRecSignal(GSN_PREP_DROP_TAB_REQ, &Dbtc::execPREP_DROP_TAB_REQ);
+ addRecSignal(GSN_WAIT_DROP_TAB_REF, &Dbtc::execWAIT_DROP_TAB_REF);
addRecSignal(GSN_WAIT_DROP_TAB_CONF, &Dbtc::execWAIT_DROP_TAB_CONF);
addRecSignal(GSN_ALTER_TAB_REQ, &Dbtc::execALTER_TAB_REQ);
initData();
+
+#ifdef VM_TRACE
+ {
+ void* tmp[] = { &apiConnectptr,
+ &tcConnectptr,
+ &cachePtr,
+ &attrbufptr,
+ &hostptr,
+ &gcpPtr,
+ &tmpApiConnectptr,
+ &timeOutptr,
+ &scanFragptr,
+ &databufptr,
+ &tmpDatabufptr };
+ init_globals_list(tmp, sizeof(tmp)/sizeof(tmp[0]));
+ }
+#endif
}//Dbtc::Dbtc()
Dbtc::~Dbtc()
@@ -323,17 +338,7 @@ Dbtc::~Dbtc()
deallocRecord((void **)&scanRecord, "ScanRecord",
sizeof(ScanRecord),
cscanrecFileSize);
-
- deallocRecord((void **)&scanOperationRecord,
- "ScanOperationRecord",
- sizeof(ScanOperationRecord),
- cscanOprecFileSize);
-
- deallocRecord((void **)&scanFragmentRecord,
- "ScanFragRec",
- sizeof(ScanFragRec),
- cscanFragrecFileSize);
-
+
deallocRecord((void **)&databufRecord, "DatabufRecord",
sizeof(DatabufRecord),
cdatabufFilesize);
@@ -360,5 +365,3 @@ Dbtc::~Dbtc()
BLOCK_FUNCTIONS(Dbtc);
-
-
diff --git a/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp b/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp
index 5afd79687a1..7e1db71faee 100644
--- a/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp
+++ b/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp
@@ -65,6 +65,7 @@
#include <signaldata/DictTabInfo.hpp>
#include <NdbOut.hpp>
+#include <DebuggerNames.hpp>
// Use DEBUG to print messages that should be
// seen only when we debug the product
@@ -76,6 +77,68 @@
#define INTERNAL_TRIGGER_TCKEYREQ_JBA 0
+#ifdef VM_TRACE
+NdbOut &
+operator<<(NdbOut& out, Dbtc::ConnectionState state){
+ switch(state){
+ case Dbtc::CS_CONNECTED: out << "CS_CONNECTED"; break;
+ case Dbtc::CS_DISCONNECTED: out << "CS_DISCONNECTED"; break;
+ case Dbtc::CS_STARTED: out << "CS_STARTED"; break;
+ case Dbtc::CS_RECEIVING: out << "CS_RECEIVING"; break;
+ case Dbtc::CS_PREPARED: out << "CS_PREPARED"; break;
+ case Dbtc::CS_START_PREPARING: out << "CS_START_PREPARING"; break;
+ case Dbtc::CS_REC_PREPARING: out << "CS_REC_PREPARING"; break;
+ case Dbtc::CS_RESTART: out << "CS_RESTART"; break;
+ case Dbtc::CS_ABORTING: out << "CS_ABORTING"; break;
+ case Dbtc::CS_COMPLETING: out << "CS_COMPLETING"; break;
+ case Dbtc::CS_COMPLETE_SENT: out << "CS_COMPLETE_SENT"; break;
+ case Dbtc::CS_PREPARE_TO_COMMIT: out << "CS_PREPARE_TO_COMMIT"; break;
+ case Dbtc::CS_COMMIT_SENT: out << "CS_COMMIT_SENT"; break;
+ case Dbtc::CS_START_COMMITTING: out << "CS_START_COMMITTING"; break;
+ case Dbtc::CS_COMMITTING: out << "CS_COMMITTING"; break;
+ case Dbtc::CS_REC_COMMITTING: out << "CS_REC_COMMITTING"; break;
+ case Dbtc::CS_WAIT_ABORT_CONF: out << "CS_WAIT_ABORT_CONF"; break;
+ case Dbtc::CS_WAIT_COMPLETE_CONF: out << "CS_WAIT_COMPLETE_CONF"; break;
+ case Dbtc::CS_WAIT_COMMIT_CONF: out << "CS_WAIT_COMMIT_CONF"; break;
+ case Dbtc::CS_FAIL_ABORTING: out << "CS_FAIL_ABORTING"; break;
+ case Dbtc::CS_FAIL_ABORTED: out << "CS_FAIL_ABORTED"; break;
+ case Dbtc::CS_FAIL_PREPARED: out << "CS_FAIL_PREPARED"; break;
+ case Dbtc::CS_FAIL_COMMITTING: out << "CS_FAIL_COMMITTING"; break;
+ case Dbtc::CS_FAIL_COMMITTED: out << "CS_FAIL_COMMITTED"; break;
+ case Dbtc::CS_FAIL_COMPLETED: out << "CS_FAIL_COMPLETED"; break;
+ case Dbtc::CS_START_SCAN: out << "CS_START_SCAN"; break;
+ default:
+ out << "Unknown: " << (int)state; break;
+ }
+ return out;
+}
+NdbOut &
+operator<<(NdbOut& out, Dbtc::OperationState state){
+ out << (int)state;
+ return out;
+}
+NdbOut &
+operator<<(NdbOut& out, Dbtc::AbortState state){
+ out << (int)state;
+ return out;
+}
+NdbOut &
+operator<<(NdbOut& out, Dbtc::ReturnSignal state){
+ out << (int)state;
+ return out;
+}
+NdbOut &
+operator<<(NdbOut& out, Dbtc::ScanRecord::ScanState state){
+ out << (int)state;
+ return out;
+}
+NdbOut &
+operator<<(NdbOut& out, Dbtc::ScanFragRec::ScanFragState state){
+ out << (int)state;
+ return out;
+}
+#endif
+
void
Dbtc::updateBuddyTimer(ApiConnectRecordPtr apiPtr)
{
@@ -110,13 +173,7 @@ void Dbtc::execCONTINUEB(Signal* signal)
switch (tcase) {
case TcContinueB::ZRETURN_FROM_QUEUED_DELIVERY:
jam();
- scanptr.i = Tdata0;
- ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
- scanFragptr.i = Tdata1;
- ptrCheckGuard(scanFragptr, cscanFragrecFileSize, scanFragmentRecord);
- ndbrequire(scanFragptr.p->scanFragState ==
- ScanFragRec::RETURNING_FROM_DELIVERY);
- returnFromQueuedDeliveryLab(signal);
+ ndbrequire(false);
return;
case TcContinueB::ZCOMPLETE_TRANS_AT_TAKE_OVER:
jam();
@@ -204,6 +261,7 @@ void Dbtc::execCONTINUEB(Signal* signal)
tcConnectptr.i = Tdata0;
apiConnectptr.i = Tdata1;
ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
+ apiConnectptr.p->counter--;
sendAbortedAfterTimeout(signal, 1);
return;
case TcContinueB::ZHANDLE_FAILED_API_NODE_REMOVE_MARKERS:
@@ -375,6 +433,39 @@ Dbtc::execWAIT_DROP_TAB_CONF(Signal* signal)
}
void
+Dbtc::execWAIT_DROP_TAB_REF(Signal* signal)
+{
+ jamEntry();
+ WaitDropTabRef * ref = (WaitDropTabRef*)signal->getDataPtr();
+
+ TableRecordPtr tabPtr;
+ tabPtr.i = ref->tableId;
+ ptrCheckGuard(tabPtr, ctabrecFilesize, tableRecord);
+
+ ndbrequire(tabPtr.p->dropping == true);
+ Uint32 nodeId = refToNode(ref->senderRef);
+ tabPtr.p->dropTable.waitDropTabCount.clearWaitingFor(nodeId);
+
+ ndbrequire(ref->errorCode == WaitDropTabRef::NoSuchTable ||
+ ref->errorCode == WaitDropTabRef::NF_FakeErrorREF);
+
+ if(!tabPtr.p->dropTable.waitDropTabCount.done()){
+ jam();
+ return;
+ }
+
+ {
+ PrepDropTabConf* conf = (PrepDropTabConf*)signal->getDataPtrSend();
+ conf->tableId = tabPtr.i;
+ conf->senderRef = reference();
+ conf->senderData = tabPtr.p->dropTable.senderData;
+ sendSignal(tabPtr.p->dropTable.senderRef, GSN_PREP_DROP_TAB_CONF, signal,
+ PrepDropTabConf::SignalLength, JBB);
+ tabPtr.p->dropTable.senderRef = 0;
+ }
+}
+
+void
Dbtc::checkWaitDropTabFailedLqh(Signal* signal, Uint32 nodeId, Uint32 tableId)
{
@@ -526,7 +617,6 @@ void Dbtc::execREAD_CONFIG_REQ(Signal* signal)
ctcConnectFilesize = tcConnect;
ctabrecFilesize = tables;
cscanrecFileSize = tcScan;
- cscanOprecFileSize = localScan;
cscanFragrecFileSize = localScan;
initRecords();
@@ -882,7 +972,15 @@ Dbtc::handleFailedApiNode(Signal* signal,
// sending several signals we will increase the loop count by 64.
/*********************************************************************/
jam();
- handleScanStop(signal, TapiFailedNode);
+
+ apiConnectptr.p->apiFailState = ZTRUE;
+ capiConnectClosing[TapiFailedNode]++;
+
+ ScanRecordPtr scanPtr;
+ scanPtr.i = apiConnectptr.p->apiScanRec;
+ ptrCheckGuard(scanPtr, cscanrecFileSize, scanRecord);
+ close_scan_req(signal, scanPtr, true);
+
TloopCount += 64;
break;
case CS_CONNECTED:
@@ -952,13 +1050,12 @@ Dbtc::handleFailedApiNode(Signal* signal,
apiConnectptr.i++;
if (apiConnectptr.i > ((capiConnectFilesize / 3) - 1)) {
jam();
- capiConnectClosing[TapiFailedNode]--;
/**
* Finished with scanning connection record
*
* Now scan markers
*/
- removeMarkerForFailedAPI(signal, TapiFailedNode, RNIL); // RNIL = first
+ removeMarkerForFailedAPI(signal, TapiFailedNode, 0);
return;
}//if
} while (TloopCount++ < 256);
@@ -973,15 +1070,26 @@ Dbtc::removeMarkerForFailedAPI(Signal* signal,
Uint32 nodeId,
Uint32 startBucket)
{
- CommitAckMarkerIterator iter;
- if(startBucket == RNIL){
- jam();
- capiConnectClosing[nodeId]++;
- m_commitAckMarkerHash.next(0, iter);
- } else {
+ TcFailRecordPtr node_fail_ptr;
+ node_fail_ptr.i = 0;
+ ptrAss(node_fail_ptr, tcFailRecord);
+ if(node_fail_ptr.p->failStatus != FS_IDLE) {
jam();
- m_commitAckMarkerHash.next(startBucket, iter);
+ DEBUG("Restarting removeMarkerForFailedAPI");
+ /**
+ * TC take-over in progress
+ * needs to restart as this
+ * creates new markers
+ */
+ signal->theData[0] = TcContinueB::ZHANDLE_FAILED_API_NODE_REMOVE_MARKERS;
+ signal->theData[1] = nodeId;
+ signal->theData[2] = 0;
+ sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 500, 3);
+ return;
}
+
+ CommitAckMarkerIterator iter;
+ m_commitAckMarkerHash.next(startBucket, iter);
const Uint32 RT_BREAK = 256;
for(Uint32 i = 0; i<RT_BREAK || iter.bucket == startBucket; i++){
@@ -1012,7 +1120,6 @@ Dbtc::removeMarkerForFailedAPI(Signal* signal,
/**
* Check so that the record is not still in use
*
- * (This can happen when NF and API Fail happens at the same time)
*/
ApiConnectRecordPtr apiConnectPtr;
apiConnectPtr.i = iter.curr.p->apiConnectPtr;
@@ -1024,9 +1131,8 @@ Dbtc::removeMarkerForFailedAPI(Signal* signal,
*
* Don't remove it, but continueb instead
*/
- break;
+ break;
}
-
sendRemoveMarkers(signal, iter.curr.p);
m_commitAckMarkerHash.release(iter.curr);
@@ -1061,136 +1167,6 @@ void Dbtc::handleApiFailState(Signal* signal, UintR TapiConnectptr)
}//if
}//Dbtc::handleApiFailState()
-/**
- * Dbtc::handleScanStop
- * This function is called when an entire scan should be stopped
- * Check state of the scan and take appropriate action.
- * The parameter TapiFailedNode indicates if the scan is stopped
- * because an API node has failed or if it has been stopped because
- * the scan has timed out.
- *
- */
-void Dbtc::handleScanStop(Signal* signal, UintR TapiFailedNode)
-{
- arrGuard(TapiFailedNode, MAX_NODES);
-
- scanptr.i = apiConnectptr.p->apiScanRec;
- ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
-
- // If api has failed we must release all resources
- bool apiNodeHasFailed = (TapiFailedNode != 0);
-
- DEBUG("handleScanStop: scanState = "<< scanptr.p->scanState);
-
- switch (scanptr.p->scanState) {
- case ScanRecord::WAIT_SCAN_TAB_INFO:
- case ScanRecord::WAIT_AI:
- jam();
- /**
- * The scan process is still in the definition phase.
- * We will release the resources and then release the connection
- * to the failed API.
- */
- releaseScanResources(signal);
- if (apiNodeHasFailed) {
- jam();
- releaseApiCon(signal, apiConnectptr.i);
- }//if
- break;
-
- case ScanRecord::WAIT_FRAGMENT_COUNT:
- jam();
- if (!apiNodeHasFailed) {
- jam();
- /**
- * Time-out waiting for a local signal can only happen
- * if we have a serious problem.
- */
- systemErrorLab(signal);
- }//if
- capiConnectClosing[TapiFailedNode]++;
- apiConnectptr.p->apiFailState = ZTRUE;
- scanptr.p->apiIsClosed = true;
- break;
-
- case ScanRecord::CLOSING_SCAN:
- jam();
- /**
- * With CLOSING_SCAN it is enough to set the
- * fail state such that the connection is released at the end of the
- * closing process. The close process is already ongoing.
- * Set apiIsClosed to true to indicate that resources should be released
- * at the end of the close process.
- **/
-
- if (apiNodeHasFailed) {
- jam();
- capiConnectClosing[TapiFailedNode]++;
- apiConnectptr.p->apiFailState = ZTRUE;
- scanptr.p->apiIsClosed = true;
- }//if
- if (apiConnectptr.p->apiFailState == ZTRUE) {
- jam();
- handleApiFailState(signal, apiConnectptr.i);
- return;
- }//if
- break;
-
- case ScanRecord::SCAN_NEXT_ORDERED:
- /**
- * In the SCAN_NEXT_ORDERED state we will wait for the next natural place
- * to receive some action from the API and instead of waiting for the
- * API here we will start the abort process.
-
- * After the abort process is completed we will release the connection.
- */
- if (apiNodeHasFailed) {
- jam();
- capiConnectClosing[TapiFailedNode]++;
- apiConnectptr.p->apiFailState = ZTRUE;
- }//if
- // Release resources and send a response to API
- scanptr.p->apiIsClosed = true;
- scanCompletedLab(signal);
- break;
-
- case ScanRecord::DELIVERED:
- case ScanRecord::QUEUED_DELIVERED:
- /**
- * A response has been sent to the api but it has not responded
- */
-
- if (apiNodeHasFailed) {
- jam();
- capiConnectClosing[TapiFailedNode]++;
- apiConnectptr.p->apiFailState = ZTRUE;
- scanptr.p->apiIsClosed = true;
- } else {
- jam();
- /*
- In this case we have received a time-out caused by the application
- waiting too long to continue the scan. We will check the application
- time-out instead of the deadlock detetection time-out. If the
- application time-out hasn't fired we will simply ignore the condition.
- */
- if ((ctcTimer - getApiConTimer(apiConnectptr.i)) <= c_appl_timeout_value) {
- jam();
- return;
- }//if
- // Dont' release, wait until api responds or fails
- scanptr.p->apiIsClosed = false;
- }
- scanCompletedLab(signal);
- break;
-
- default:
- jam();
- systemErrorLab(signal);
- break;
-
- }//switch
-}//Dbtc::handleScanStop()
-
/****************************************************************************
* T C S E I Z E R E Q
* THE APPLICATION SENDS A REQUEST TO SEIZE A CONNECT RECORD TO CARRY OUT A
@@ -1303,13 +1279,13 @@ void Dbtc::execTCRELEASEREQ(Signal* signal)
jam(); /* JUST REPLY OK */
releaseApiCon(signal, apiConnectptr.i);
signal->theData[0] = tuserpointer;
- sendSignal(apiConnectptr.p->ndbapiBlockref,
+ sendSignal(tapiBlockref,
GSN_TCRELEASECONF, signal, 1, JBB);
} else {
jam();
signal->theData[0] = tuserpointer;
signal->theData[1] = ZINVALID_CONNECTION;
- sendSignal(apiConnectptr.p->ndbapiBlockref,
+ sendSignal(tapiBlockref,
GSN_TCRELEASEREF, signal, 2, JBB);
}
} else {
@@ -1341,6 +1317,7 @@ void Dbtc::sendSignalErrorRefuseLab(Signal* signal)
ptrGuard(apiConnectptr);
if (apiConnectptr.p->apiConnectstate != CS_DISCONNECTED) {
jam();
+ ndbrequire(false);
signal->theData[0] = apiConnectptr.p->ndbapiConnect;
signal->theData[1] = signal->theData[ttransid_ptr];
signal->theData[2] = signal->theData[ttransid_ptr + 1];
@@ -1372,7 +1349,7 @@ void Dbtc::printState(Signal* signal, int place)
<< " counter = " << apiConnectptr.p->counter
<< " lqhkeyconfrec = " << apiConnectptr.p->lqhkeyconfrec
<< " lqhkeyreqrec = " << apiConnectptr.p->lqhkeyreqrec << endl;
- ndbout << "abortState = " << (int)apiConnectptr.p->abortState
+ ndbout << "abortState = " << apiConnectptr.p->abortState
<< " apiScanRec = " << apiConnectptr.p->apiScanRec
<< " returncode = " << apiConnectptr.p->returncode << endl;
ndbout << "tckeyrec = " << apiConnectptr.p->tckeyrec
@@ -1424,6 +1401,7 @@ Dbtc::TCKEY_abort(Signal* signal, int place)
signal->theData[1] = t1;
signal->theData[2] = t2;
signal->theData[3] = ZABORT_ERROR;
+ ndbrequire(false);
sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_TCROLLBACKREP,
signal, 4, JBB);
return;
@@ -1747,6 +1725,13 @@ Dbtc::TCKEY_abort(Signal* signal, int place)
return;
}
+ case 59:{
+ jam();
+ terrorCode = ZABORTINPROGRESS;
+ abortErrorLab(signal);
+ return;
+ }
+
default:
jam();
systemErrorLab(signal);
@@ -1881,7 +1866,7 @@ void Dbtc::packKeyData000Lab(Signal* signal,
/* THERE WERE UNSENT INFORMATION, SEND IT. */
/*---------------------------------------------------------------------*/
sendKeyinfo(signal, TBRef, tdataPos);
- releaseKeys(signal);
+ releaseKeys();
return;
}//if
databufptr.i = databufptr.p->nextDatabuf;
@@ -2264,6 +2249,8 @@ void Dbtc::initApiConnectRec(Signal* signal,
UintR Ttransid0 = tcKeyReq->transId1;
UintR Ttransid1 = tcKeyReq->transId2;
+ regApiPtr->m_exec_flag = 0;
+ regApiPtr->returncode = 0;
regApiPtr->returnsignal = RS_TCKEYCONF;
regApiPtr->firstTcConnect = RNIL;
regApiPtr->lastTcConnect = RNIL;
@@ -2424,9 +2411,12 @@ void Dbtc::execTCKEYREQ(Signal* signal)
apiConnectptr.p = regApiPtr;
Uint32 TstartFlag = tcKeyReq->getStartFlag(Treqinfo);
+ Uint32 TexecFlag = TcKeyReq::getExecuteFlag(Treqinfo);
+
bool isIndexOp = regApiPtr->isIndexOp;
bool isIndexOpReturn = regApiPtr->indexOpReturn;
regApiPtr->isIndexOp = false; // Reset marker
+ regApiPtr->m_exec_flag |= TexecFlag;
switch (regApiPtr->apiConnectstate) {
case CS_CONNECTED:{
if (TstartFlag == 1 && getAllowStartTransaction() == true){
@@ -2435,6 +2425,7 @@ void Dbtc::execTCKEYREQ(Signal* signal)
//---------------------------------------------------------------------
jam();
initApiConnectRec(signal, regApiPtr);
+ regApiPtr->m_exec_flag = TexecFlag;
} else {
if(getAllowStartTransaction() == true){
/*------------------------------------------------------------------
@@ -2477,14 +2468,18 @@ void Dbtc::execTCKEYREQ(Signal* signal)
//--------------------------------------------------------------------
jam();
initApiConnectRec(signal, regApiPtr);
- } else {
+ regApiPtr->m_exec_flag = TexecFlag;
+ } else if(TexecFlag) {
+ TCKEY_abort(signal, 59);
+ return;
+ } else {
//--------------------------------------------------------------------
// The current transaction was aborted successfully.
// We will not do anything before we receive an operation
// with a start indicator. We will ignore this signal.
//--------------------------------------------------------------------
- jam();
- // DEBUG("Drop TCKEYREQ - apiConnectState=CS_ABORTING, ==AS_IDLE");
+ jam();
+ DEBUG("Drop TCKEYREQ - apiConnectState=CS_ABORTING, ==AS_IDLE");
return;
}//if
} else {
@@ -2499,11 +2494,14 @@ void Dbtc::execTCKEYREQ(Signal* signal)
//--------------------------------------------------------------------
TCKEY_abort(signal, 2);
return;
- }//if
+ } else if(TexecFlag) {
+ TCKEY_abort(signal, 59);
+ return;
+ }
//----------------------------------------------------------------------
// Ignore signals without start indicator set when aborting transaction.
//----------------------------------------------------------------------
- // DEBUG("Drop TCKEYREQ - apiConnectState=CS_ABORTING, !=AS_IDLE");
+ DEBUG("Drop TCKEYREQ - apiConnectState=CS_ABORTING, !=AS_IDLE");
return;
}//if
break;
@@ -2593,7 +2591,7 @@ void Dbtc::execTCKEYREQ(Signal* signal)
regTcPtr->triggeringOperation = TsenderData;
}
- if (TcKeyReq::getExecuteFlag(Treqinfo)){
+ if (TexecFlag){
Uint32 currSPId = regApiPtr->currSavePointId;
regApiPtr->currSavePointId = ++currSPId;
}
@@ -2614,7 +2612,7 @@ void Dbtc::execTCKEYREQ(Signal* signal)
Uint8 TDistrGroupFlag = tcKeyReq->getDistributionGroupFlag(Treqinfo);
Uint8 TDistrGroupTypeFlag = tcKeyReq->getDistributionGroupTypeFlag(Treqinfo);
Uint8 TDistrKeyFlag = tcKeyReq->getDistributionKeyFlag(Treqinfo);
- Uint8 TexecuteFlag = tcKeyReq->getExecuteFlag(Treqinfo);
+ Uint8 TexecuteFlag = TexecFlag;
//RONM_TEST Disable simple reads temporarily
regCachePtr->opSimple = 0;
@@ -3238,7 +3236,7 @@ void Dbtc::packLqhkeyreq040Lab(Signal* signal,
/*--------------------------------------------------------------------
* WE HAVE SENT ALL THE SIGNALS OF THIS OPERATION. SET STATE AND EXIT.
*---------------------------------------------------------------------*/
- releaseAttrinfo(signal);
+ releaseAttrinfo();
if (Tboth) {
jam();
releaseSimpleRead(signal);
@@ -3264,7 +3262,7 @@ void Dbtc::packLqhkeyreq040Lab(Signal* signal,
/* ========================================================================= */
/* ------- RELEASE ALL ATTRINFO RECORDS IN AN OPERATION RECORD ------- */
/* ========================================================================= */
-void Dbtc::releaseAttrinfo(Signal* signal)
+void Dbtc::releaseAttrinfo()
{
UintR Tmp;
AttrbufRecordPtr Tattrbufptr;
@@ -3296,7 +3294,7 @@ void Dbtc::releaseAttrinfo(Signal* signal)
regApiPtr->cachePtr = RNIL;
return;
}//if
- systemErrorLab(signal);
+ systemErrorLab(0);
return;
}//Dbtc::releaseAttrinfo()
@@ -3306,7 +3304,7 @@ void Dbtc::releaseAttrinfo(Signal* signal)
void Dbtc::releaseSimpleRead(Signal* signal)
{
unlinkReadyTcCon(signal);
- releaseTcCon(signal);
+ releaseTcCon();
/**
* No LQHKEYCONF in Simple/Dirty read
@@ -3370,7 +3368,7 @@ void Dbtc::unlinkReadyTcCon(Signal* signal)
}//if
}//Dbtc::unlinkReadyTcCon()
-void Dbtc::releaseTcCon(Signal* signal)
+void Dbtc::releaseTcCon()
{
TcConnectRecord * const regTcPtr = tcConnectptr.p;
UintR TfirstfreeTcConnect = cfirstfreeTcConnect;
@@ -3724,7 +3722,7 @@ Dbtc::lqhKeyConf_checkTransactionState(Signal * signal,
case CS_RECEIVING:
if (TnoOfOutStanding == 0) {
jam();
- sendtckeyconf(signal, 0);
+ sendtckeyconf(signal, 2);
return;
} else {
if (apiConnectPtrP->tckeyrec == ZTCOPCONF_SIZE) {
@@ -3783,7 +3781,7 @@ void Dbtc::sendtckeyconf(Signal* signal, UintR TcommitFlag)
ptrAss(localHostptr, hostRecord);
UintR TcurrLen = localHostptr.p->noOfWordsTCKEYCONF;
UintR confInfo = 0;
- TcKeyConf::setCommitFlag(confInfo, TcommitFlag);
+ TcKeyConf::setCommitFlag(confInfo, TcommitFlag == 1);
TcKeyConf::setMarkerFlag(confInfo, Tmarker);
const UintR TpacketLen = 6 + TopWords;
regApiPtr->tckeyrec = 0;
@@ -3808,7 +3806,10 @@ void Dbtc::sendtckeyconf(Signal* signal, UintR TcommitFlag)
return; // No queued TcKeyConf
}//if
}//if
-
+ if(TcommitFlag){
+ jam();
+ regApiPtr->m_exec_flag = 0;
+ }
TcKeyConf::setNoOfOperations(confInfo, (TopWords >> 1));
if ((TpacketLen > 25) || !is_api){
TcKeyConf * const tcKeyConf = (TcKeyConf *)signal->getDataPtrSend();
@@ -4521,6 +4522,8 @@ void Dbtc::copyApi(Signal* signal)
setApiConTimer(tmpApiConnectptr.i, 0, __LINE__);
regTmpApiPtr->apiConnectstate = CS_CONNECTED;
regTmpApiPtr->commitAckMarker = RNIL;
+ regTmpApiPtr->firstTcConnect = RNIL;
+ regTmpApiPtr->lastTcConnect = RNIL;
}//Dbtc::copyApi()
void Dbtc::unlinkApiConnect(Signal* signal)
@@ -4787,7 +4790,7 @@ void Dbtc::releaseTransResources(Signal* signal)
tcConnectptr.i = localTcConnectptr.i;
tcConnectptr.p = localTcConnectptr.p;
localTcConnectptr.i = rtrTcConnectptrIndex;
- releaseTcCon(signal);
+ releaseTcCon();
} while (localTcConnectptr.i != RNIL);
handleGcp(signal);
releaseFiredTriggerData(&apiConnectptr.p->theFiredTriggers);
@@ -4841,7 +4844,7 @@ void Dbtc::releaseApiConCopy(Signal* signal)
void Dbtc::releaseDirtyWrite(Signal* signal)
{
unlinkReadyTcCon(signal);
- releaseTcCon(signal);
+ releaseTcCon();
ApiConnectRecord * const regApiPtr = apiConnectptr.p;
if (regApiPtr->apiConnectstate == CS_START_COMMITTING) {
if (regApiPtr->firstTcConnect == RNIL) {
@@ -4924,7 +4927,9 @@ void Dbtc::execLQHKEYREF(Signal* signal)
// The operation executed an index trigger
const Uint32 opType = regTcPtr->operation;
- if (!(opType == ZDELETE && errCode == ZNOT_FOUND)) {
+ if (errCode == ZALREADYEXIST)
+ errCode = terrorCode = ZNOTUNIQUE;
+ else if (!(opType == ZDELETE && errCode == ZNOT_FOUND)) {
jam();
/**
* "Normal path"
@@ -4942,7 +4947,7 @@ void Dbtc::execLQHKEYREF(Signal* signal)
regApiPtr->lqhkeyconfrec++;
unlinkReadyTcCon(signal);
- releaseTcCon(signal);
+ releaseTcCon();
opPtr.p->triggerExecutionCount--;
if (opPtr.p->triggerExecutionCount == 0) {
@@ -4958,6 +4963,7 @@ void Dbtc::execLQHKEYREF(Signal* signal)
}
}
+ Uint32 marker = regTcPtr->commitAckMarker;
markOperationAborted(regApiPtr, regTcPtr);
if(regApiPtr->apiConnectstate == CS_ABORTING){
@@ -4977,7 +4983,7 @@ void Dbtc::execLQHKEYREF(Signal* signal)
return;
}//if
- if (regTcPtr->commitAckMarker != RNIL){
+ if (marker != RNIL){
/**
* This was an insert/update/delete/write which failed
* that contained the marker
@@ -4998,12 +5004,15 @@ void Dbtc::execLQHKEYREF(Signal* signal)
Uint32 indexOp = tcConnectptr.p->indexOp;
Uint32 clientData = regTcPtr->clientData;
unlinkReadyTcCon(signal); /* LINK TC CONNECT RECORD OUT OF */
- releaseTcCon(signal); /* RELEASE THE TC CONNECT RECORD */
+ releaseTcCon(); /* RELEASE THE TC CONNECT RECORD */
setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
if (isIndexOp) {
jam();
+ regApiPtr->lqhkeyreqrec--; // Compensate for extra during read
tcKeyRef->connectPtr = indexOp;
EXECUTE_DIRECT(DBTC, GSN_TCKEYREF, signal, TcKeyRef::SignalLength);
+ apiConnectptr.i = regTcPtr->apiConnect;
+ apiConnectptr.p = regApiPtr;
} else {
jam();
tcKeyRef->connectPtr = clientData;
@@ -5041,11 +5050,11 @@ void Dbtc::execLQHKEYREF(Signal* signal)
jam();
diverify010Lab(signal);
return;
- } else if (regApiPtr->tckeyrec > 0) {
+ } else if (regApiPtr->tckeyrec > 0 || regApiPtr->m_exec_flag) {
jam();
- sendtckeyconf(signal, 0);
+ sendtckeyconf(signal, 2);
return;
- }//if
+ }
}//if
return;
@@ -5140,8 +5149,8 @@ void Dbtc::execTC_COMMITREQ(Signal* signal)
// We will abort it instead.
/*******************************************************************/
regApiPtr->returnsignal = RS_NO_RETURN;
- abort010Lab(signal);
errorCode = ZTRANS_STATUS_ERROR;
+ abort010Lab(signal);
}//if
} else {
jam();
@@ -5167,8 +5176,8 @@ void Dbtc::execTC_COMMITREQ(Signal* signal)
// transaction. We will abort it instead.
/***********************************************************************/
regApiPtr->returnsignal = RS_NO_RETURN;
- abort010Lab(signal);
errorCode = ZPREPAREINPROGRESS;
+ abort010Lab(signal);
break;
case CS_START_COMMITTING:
@@ -5243,6 +5252,7 @@ void Dbtc::execTCROLLBACKREQ(Signal* signal)
return;
}//if
+ apiConnectptr.p->m_exec_flag = 1;
switch (apiConnectptr.p->apiConnectstate) {
case CS_STARTED:
case CS_RECEIVING:
@@ -5278,8 +5288,9 @@ void Dbtc::execTCROLLBACKREQ(Signal* signal)
signal->theData[1] = apiConnectptr.p->transid[0];
signal->theData[2] = apiConnectptr.p->transid[1];
signal->theData[3] = ZROLLBACKNOTALLOWED;
+ signal->theData[4] = apiConnectptr.p->apiConnectstate;
sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_TCROLLBACKREF,
- signal, 4, JBB);
+ signal, 5, JBB);
break;
/* SEND A REFUSAL SIGNAL*/
case CS_ABORTING:
@@ -5700,7 +5711,10 @@ void Dbtc::abortErrorLab(Signal* signal)
return;
}
transP->returnsignal = RS_TCROLLBACKREP;
- transP->returncode = terrorCode;
+ if(transP->returncode == 0){
+ jam();
+ transP->returncode = terrorCode;
+ }
abort010Lab(signal);
}//Dbtc::abortErrorLab()
@@ -6027,8 +6041,12 @@ void Dbtc::timeOutFoundLab(Signal* signal, Uint32 TapiConPtr)
/* THIS TRANSACTION HAVE EXPERIENCED A TIME-OUT AND WE NEED TO*/
/* FIND OUT WHAT WE NEED TO DO BASED ON THE STATE INFORMATION.*/
/*------------------------------------------------------------------*/
- DEBUG("Time-out in state = " << apiConnectptr.p->apiConnectstate
- << " apiConnectptr.i = " << apiConnectptr.i);
+ DEBUG("[ H'" << hex << apiConnectptr.p->transid[0]
+ << " H'" << apiConnectptr.p->transid[1] << "] " << dec
+ << "Time-out in state = " << apiConnectptr.p->apiConnectstate
+ << " apiConnectptr.i = " << apiConnectptr.i
+ << " - exec: " << apiConnectptr.p->m_exec_flag
+ << " - place: " << c_apiConTimer_line[apiConnectptr.i]);
switch (apiConnectptr.p->apiConnectstate) {
case CS_STARTED:
if(apiConnectptr.p->lqhkeyreqrec == apiConnectptr.p->lqhkeyconfrec){
@@ -6042,11 +6060,8 @@ void Dbtc::timeOutFoundLab(Signal* signal, Uint32 TapiConPtr)
jam();
return;
}//if
- apiConnectptr.p->returnsignal = RS_NO_RETURN;
- } else {
- jam();
- apiConnectptr.p->returnsignal = RS_TCROLLBACKREP;
}
+ apiConnectptr.p->returnsignal = RS_TCROLLBACKREP;
apiConnectptr.p->returncode = ZTIME_OUT_ERROR;
abort010Lab(signal);
return;
@@ -6125,11 +6140,14 @@ void Dbtc::timeOutFoundLab(Signal* signal, Uint32 TapiConPtr)
tcConnectptr.i = apiConnectptr.p->firstTcConnect;
sendAbortedAfterTimeout(signal, 0);
break;
- case CS_START_SCAN:
+ case CS_START_SCAN:{
jam();
- apiConnectptr.p->returncode = ZSCANTIME_OUT_ERROR;
- handleScanStop(signal, 0);
+ ScanRecordPtr scanPtr;
+ scanPtr.i = apiConnectptr.p->apiScanRec;
+ ptrCheckGuard(scanPtr, cscanrecFileSize, scanRecord);
+ scanError(signal, scanPtr, ZSCANTIME_OUT_ERROR);
break;
+ }
case CS_WAIT_ABORT_CONF:
jam();
tcConnectptr.i = apiConnectptr.p->currentTcConnect;
@@ -6289,9 +6307,8 @@ void Dbtc::sendAbortedAfterTimeout(Signal* signal, int Tcheck)
warningEvent(buf);
ndbout_c(buf);
ndbrequire(false);
- releaseAbortResources(signal);
- return;
- }//if
+ }
+ releaseAbortResources(signal);
return;
}//if
TloopCount++;
@@ -6302,6 +6319,7 @@ void Dbtc::sendAbortedAfterTimeout(Signal* signal, int Tcheck)
// away the job buffer.
/*------------------------------------------------------------------*/
setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
+ apiConnectptr.p->counter++;
signal->theData[0] = TcContinueB::ZABORT_TIMEOUT_BREAK;
signal->theData[1] = tcConnectptr.i;
signal->theData[2] = apiConnectptr.i;
@@ -6396,7 +6414,7 @@ void Dbtc::timeOutLoopStartFragLab(Signal* signal, Uint32 TscanConPtr)
UintR texpiredTime[8];
UintR TloopCount = 0;
Uint32 TtcTimer = ctcTimer;
-
+
while ((TscanConPtr + 8) < cscanFragrecFileSize) {
jam();
timeOutPtr[0].i = TscanConPtr + 0;
@@ -6408,14 +6426,14 @@ void Dbtc::timeOutLoopStartFragLab(Signal* signal, Uint32 TscanConPtr)
timeOutPtr[6].i = TscanConPtr + 6;
timeOutPtr[7].i = TscanConPtr + 7;
- ptrAss(timeOutPtr[0], scanFragmentRecord);
- ptrAss(timeOutPtr[1], scanFragmentRecord);
- ptrAss(timeOutPtr[2], scanFragmentRecord);
- ptrAss(timeOutPtr[3], scanFragmentRecord);
- ptrAss(timeOutPtr[4], scanFragmentRecord);
- ptrAss(timeOutPtr[5], scanFragmentRecord);
- ptrAss(timeOutPtr[6], scanFragmentRecord);
- ptrAss(timeOutPtr[7], scanFragmentRecord);
+ c_scan_frag_pool.getPtrForce(timeOutPtr[0]);
+ c_scan_frag_pool.getPtrForce(timeOutPtr[1]);
+ c_scan_frag_pool.getPtrForce(timeOutPtr[2]);
+ c_scan_frag_pool.getPtrForce(timeOutPtr[3]);
+ c_scan_frag_pool.getPtrForce(timeOutPtr[4]);
+ c_scan_frag_pool.getPtrForce(timeOutPtr[5]);
+ c_scan_frag_pool.getPtrForce(timeOutPtr[6]);
+ c_scan_frag_pool.getPtrForce(timeOutPtr[7]);
tfragTimer[0] = timeOutPtr[0].p->scanFragTimer;
tfragTimer[1] = timeOutPtr[1].p->scanFragTimer;
@@ -6467,7 +6485,7 @@ void Dbtc::timeOutLoopStartFragLab(Signal* signal, Uint32 TscanConPtr)
for ( ; TscanConPtr < cscanFragrecFileSize; TscanConPtr++){
jam();
timeOutPtr[0].i = TscanConPtr;
- ptrAss(timeOutPtr[0], scanFragmentRecord);
+ c_scan_frag_pool.getPtrForce(timeOutPtr[0]);
if (timeOutPtr[0].p->scanFragTimer != 0) {
texpiredTime[0] = ctcTimer - timeOutPtr[0].p->scanFragTimer;
if (texpiredTime[0] > ctimeOutValue) {
@@ -6483,6 +6501,7 @@ void Dbtc::timeOutLoopStartFragLab(Signal* signal, Uint32 TscanConPtr)
}//if
}//for
ctimeOutCheckFragActive = TOCS_FALSE;
+
return;
}//timeOutLoopStartFragLab()
@@ -6495,19 +6514,17 @@ void Dbtc::execSCAN_HBREP(Signal* signal)
jamEntry();
scanFragptr.i = signal->theData[0];
- ptrCheckGuard(scanFragptr, cscanFragrecFileSize, scanFragmentRecord);
-
+ c_scan_frag_pool.getPtr(scanFragptr);
switch (scanFragptr.p->scanFragState){
case ScanFragRec::LQH_ACTIVE:
- case ScanFragRec::LQH_ACTIVE_CLOSE:
break;
-
default:
DEBUG("execSCAN_HBREP: scanFragState="<<scanFragptr.p->scanFragState);
systemErrorLab(signal);
break;
}
+ ScanRecordPtr scanptr;
scanptr.i = scanFragptr.p->scanRec;
ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
@@ -6538,6 +6555,7 @@ void Dbtc::execSCAN_HBREP(Signal* signal)
updateBuddyTimer(apiConnectptr);
scanFragptr.p->startFragTimer(ctcTimer);
} else {
+ ndbassert(false);
DEBUG("SCAN_HBREP when scanFragTimer was turned off");
}
}//execSCAN_HBREP()
@@ -6548,62 +6566,50 @@ void Dbtc::execSCAN_HBREP(Signal* signal)
/*--------------------------------------------------------------------------*/
void Dbtc::timeOutFoundFragLab(Signal* signal, UintR TscanConPtr)
{
- scanFragptr.i = TscanConPtr;
- ptrAss(scanFragptr, scanFragmentRecord);
- DEBUG("timeOutFoundFragLab: scanFragState = "<<scanFragptr.p->scanFragState);
+ ScanFragRecPtr ptr;
+ c_scan_frag_pool.getPtr(ptr, TscanConPtr);
+ DEBUG(TscanConPtr << " timeOutFoundFragLab: scanFragState = "<< ptr.p->scanFragState);
/*-------------------------------------------------------------------------*/
// The scan fragment has expired its timeout. Check its state to decide
// what to do.
/*-------------------------------------------------------------------------*/
- switch (scanFragptr.p->scanFragState) {
-
+ switch (ptr.p->scanFragState) {
case ScanFragRec::WAIT_GET_PRIMCONF:
jam();
- // Crash the system if we do not return from DIGETPRIMREQ in time.
- systemErrorLab(signal);
+ ndbrequire(false);
break;
-
- case ScanFragRec::LQH_ACTIVE:
+ case ScanFragRec::LQH_ACTIVE:{
jam();
+
/**
* The LQH expired it's timeout, try to close it
*/
- scanFragError(signal, ZSCAN_FRAG_LQH_ERROR);
- DEBUG(" LQH_ACTIVE - closing the fragment scan in node "
- <<scanFragptr.p->scanFragNodeId);
- break;
-
- case ScanFragRec::LQH_ACTIVE_CLOSE:{
- jam();
- /**
- * The close of LQH expired its time-out. This is not
- * acceptable behaviour from LQH and thus we will shoot
- * it down.
- */
- Uint32 nodeId = scanFragptr.p->scanFragNodeId;
- Uint32 cc = scanFragptr.p->m_connectCount;
- if(getNodeInfo(nodeId).m_connectCount == cc){
- const BlockReference errRef = calcNdbCntrBlockRef(nodeId);
- SystemError * const sysErr = (SystemError*)&signal->theData[0];
- sysErr->errorCode = SystemError::ScanfragTimeout;
- sysErr->errorRef = reference();
- sysErr->data1 = scanFragptr.i;
- sysErr->data2 = scanFragptr.p->scanRec;
- sendSignal(errRef, GSN_SYSTEM_ERROR, signal,
- SystemError::SignalLength, JBA);
- DEBUG(" node " << nodeId << " killed");
- } else {
- DEBUG(" node " << nodeId << " not killed as it has restarted");
+ Uint32 nodeId = refToNode(ptr.p->lqhBlockref);
+ Uint32 connectCount = getNodeInfo(nodeId).m_connectCount;
+ ScanRecordPtr scanptr;
+ scanptr.i = ptr.p->scanRec;
+ ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
+
+ if(connectCount != ptr.p->m_connectCount){
+ jam();
+ /**
+ * The node has died
+ */
+ ptr.p->scanFragState = ScanFragRec::COMPLETED;
+ ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
+ ScanFragList comp(c_scan_frag_pool, scanptr.p->m_completed_scan_frags);
+
+ run.remove(ptr);
+ comp.add(ptr);
+ ptr.p->stopFragTimer();
}
- scanFragptr.p->stopFragTimer();
+
+ scanError(signal, scanptr, ZSCAN_FRAG_LQH_ERROR);
break;
}
-
case ScanFragRec::DELIVERED:
jam();
- case ScanFragRec::RETURNING_FROM_DELIVERY:
- jam();
case ScanFragRec::IDLE:
jam();
case ScanFragRec::QUEUED_FOR_DELIVERY:
@@ -6725,7 +6731,8 @@ void Dbtc::execNODE_FAILREP(Signal* signal)
tcNodeFailptr.i = 0;
ptrAss(tcNodeFailptr, tcFailRecord);
- for (Uint32 tindex = 0; tindex < tnoOfNodes; tindex++) {
+ Uint32 tindex;
+ for (tindex = 0; tindex < tnoOfNodes; tindex++) {
jam();
hostptr.i = cdata[tindex];
ptrCheckGuard(hostptr, chostFilesize, hostRecord);
@@ -6842,8 +6849,7 @@ void Dbtc::execNODE_FAILREP(Signal* signal)
}//if
}//for
}//if
-
- for (Uint32 tindex = 0; tindex < tnoOfNodes; tindex++) {
+ for (tindex = 0; tindex < tnoOfNodes; tindex++) {
jam();
hostptr.i = cdata[tindex];
ptrCheckGuard(hostptr, chostFilesize, hostRecord);
@@ -6859,47 +6865,41 @@ void Dbtc::execNODE_FAILREP(Signal* signal)
}//Dbtc::execNODE_FAILREP()
void Dbtc::checkScanActiveInFailedLqh(Signal* signal,
- Uint32 scanPtrI,
- Uint32 failedNodeId){
+ Uint32 scanPtrI,
+ Uint32 failedNodeId){
+ ScanRecordPtr scanptr;
for (scanptr.i = scanPtrI; scanptr.i < cscanrecFileSize; scanptr.i++) {
jam();
ptrAss(scanptr, scanRecord);
+ bool found = false;
if (scanptr.p->scanState != ScanRecord::IDLE){
- for (Uint32 i=0; i<16; i++) {
- jam();
- scanFragptr.i = scanptr.p->scanFragrec[i];
- if (scanFragptr.i != RNIL) {
+ jam();
+ ScanFragRecPtr ptr;
+ ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
+ ScanFragList comp(c_scan_frag_pool, scanptr.p->m_completed_scan_frags);
+
+ for(run.first(ptr); !ptr.isNull(); ){
+ jam();
+ ScanFragRecPtr curr = ptr;
+ run.next(ptr);
+ if (curr.p->scanFragState == ScanFragRec::LQH_ACTIVE &&
+ refToNode(curr.p->lqhBlockref) == failedNodeId){
jam();
- ptrCheckGuard(scanFragptr, cscanFragrecFileSize, scanFragmentRecord);
- if (scanFragptr.p->scanFragNodeId == failedNodeId){
- switch (scanFragptr.p->scanFragState){
- case ScanFragRec::LQH_ACTIVE:
- case ScanFragRec::LQH_ACTIVE_CLOSE:
- jam();
- apiConnectptr.i = scanptr.p->scanApiRec;
- ptrCheckGuard(apiConnectptr, capiConnectFilesize,
- apiConnectRecord);
-
- // The connection to this LQH is closed
- scanFragptr.p->lqhBlockref = RNIL;
-
- DEBUG("checkScanActiveInFailedLqh: scanFragError");
- scanFragError(signal, ZSCAN_LQH_ERROR);
-
- break;
-
- default:
- /* empty */
- jam();
- break;
- }// switch
+
+ run.remove(curr);
+ comp.add(curr);
+ curr.p->scanFragState = ScanFragRec::COMPLETED;
+ curr.p->stopFragTimer();
+ found = true;
+ }
+ }
+ }
+ if(found){
+ jam();
+ scanError(signal, scanptr, ZSCAN_LQH_ERROR);
+ }
- } //if
- } //if
- } //for
- } //if
-
// Send CONTINUEB to continue later
signal->theData[0] = TcContinueB::ZCHECK_SCAN_ACTIVE_FAILED_LQH;
signal->theData[1] = scanptr.i + 1; // Check next scanptr
@@ -6909,6 +6909,15 @@ void Dbtc::checkScanActiveInFailedLqh(Signal* signal,
}//for
}
+void
+Dbtc::checkScanFragList(Signal* signal,
+ Uint32 failedNodeId,
+ ScanRecord * scanP,
+ ScanFragList::Head & head){
+
+ DEBUG("checkScanActiveInFailedLqh: scanFragError");
+}
+
void Dbtc::execTAKE_OVERTCCONF(Signal* signal)
{
jamEntry();
@@ -7336,25 +7345,23 @@ Dbtc::sendTCKEY_FAILREF(Signal* signal, const ApiConnectRecord * regApiPtr){
}
void
-Dbtc::sendTCKEY_FAILCONF(Signal* signal, const ApiConnectRecord * regApiPtr){
+Dbtc::sendTCKEY_FAILCONF(Signal* signal, ApiConnectRecord * regApiPtr){
jam();
TcKeyFailConf * const failConf = (TcKeyFailConf *)&signal->theData[0];
- if(regApiPtr->commitAckMarker == RNIL){
- jam();
- failConf->apiConnectPtr = regApiPtr->ndbapiConnect;
- } else {
- jam();
- failConf->apiConnectPtr = regApiPtr->ndbapiConnect | 1;
+ const Uint32 ref = regApiPtr->ndbapiBlockref;
+ const Uint32 marker = regApiPtr->commitAckMarker;
+ if(ref != 0){
+ failConf->apiConnectPtr = regApiPtr->ndbapiConnect | (marker != RNIL);
+ failConf->transId1 = regApiPtr->transid[0];
+ failConf->transId2 = regApiPtr->transid[1];
+
+ sendSignal(regApiPtr->ndbapiBlockref,
+ GSN_TCKEY_FAILCONF, signal, TcKeyFailConf::SignalLength, JBB);
}
- failConf->transId1 = regApiPtr->transid[0];
- failConf->transId2 = regApiPtr->transid[1];
-
- sendSignal(regApiPtr->ndbapiBlockref,
- GSN_TCKEY_FAILCONF, signal, TcKeyFailConf::SignalLength, JBB);
+ regApiPtr->commitAckMarker = RNIL;
}
-
/*------------------------------------------------------------*/
/* THIS PART HANDLES THE ABORT PHASE IN THE CASE OF A */
/* NODE FAILURE BEFORE THE COMMIT DECISION. */
@@ -8415,10 +8422,17 @@ void Dbtc::execSCAN_TABREQ(Signal* signal)
const Uint32 buddyPtr = (tmpXX == 0xFFFFFFFF ? RNIL : tmpXX);
Uint32 currSavePointId = 0;
- Uint8 scanConcurrency = scanTabReq->getParallelism(reqinfo);
- Uint32 scanParallel;
- Uint32 noOprecPerFrag;
+ Uint32 scanConcurrency = scanTabReq->getParallelism(reqinfo);
+ Uint32 noOprecPerFrag = ScanTabReq::getScanBatch(reqinfo);
+ Uint32 scanParallel = scanConcurrency;
Uint32 errCode;
+ ScanRecordPtr scanptr;
+
+ if(noOprecPerFrag == 0){
+ jam();
+ scanParallel = (scanConcurrency + 15) / 16;
+ noOprecPerFrag = (scanConcurrency >= 16 ? 16 : scanConcurrency & 15);
+ }
jamEntry();
apiConnectptr.i = scanTabReq->apiConnectPtr;
@@ -8433,12 +8447,13 @@ void Dbtc::execSCAN_TABREQ(Signal* signal)
return;
}//if
ptrAss(apiConnectptr, apiConnectRecord);
+ ApiConnectRecord * transP = apiConnectptr.p;
- if (apiConnectptr.p->apiConnectstate != CS_CONNECTED) {
+ if (transP->apiConnectstate != CS_CONNECTED) {
jam();
// could be left over from TCKEYREQ rollback
- if (apiConnectptr.p->apiConnectstate == CS_ABORTING &&
- apiConnectptr.p->abortState == AS_IDLE) {
+ if (transP->apiConnectstate == CS_ABORTING &&
+ transP->abortState == AS_IDLE) {
jam();
} else {
jam();
@@ -8469,43 +8484,19 @@ void Dbtc::execSCAN_TABREQ(Signal* signal)
errCode = ZNO_CONCURRENCY_ERROR;
goto SCAN_TAB_error;
}//if
- if (scanConcurrency <= 16) {
- jam();
- noOprecPerFrag = scanConcurrency;
- } else {
- if (scanConcurrency <= 240) {
- jam();
- //If scanConcurrency > 16 it must be a multiple of 16
- if (((scanConcurrency >> 4) << 4) < scanConcurrency) {
- scanConcurrency = ((scanConcurrency >> 4) << 4) + 16;
- }//if
- } else {
- jam();
- errCode = ZTOO_HIGH_CONCURRENCY_ERROR;
- goto SCAN_TAB_error;
- }//if
- noOprecPerFrag = 16;
- }//if
-
- scanParallel = ((scanConcurrency - 1) >> 4) + 1;
+
/**********************************************************
* CALCULATE THE NUMBER OF SCAN_TABINFO SIGNALS THAT WILL
* ARRIVE TO DEFINE THIS SCAN. THIS ALSO DEFINES THE NUMBER
* OF PARALLEL SCANS AND IT ALSO DEFINES THE NUMBER OF SCAN
* OPERATION POINTER RECORDS TO ALLOCATE.
**********************************************************/
- if (cnoFreeScanOprec < scanParallel) {
- jam();
- errCode = ZNO_SCANREC_ERROR;
- goto SCAN_TAB_error;
- // WE DID NOT HAVE ENOUGH OF FREE SCAN OPERATION POINTER RECORDS.
- // THUS WE REFUSE THE SCAN OPERATION.
- }//if
if (cfirstfreeTcConnect == RNIL) {
jam();
errCode = ZNO_FREE_TC_CONNECTION;
goto SCAN_TAB_error;
}//if
+
if (cfirstfreeScanrec == RNIL) {
jam();
errCode = ZNO_SCANREC_ERROR;
@@ -8521,22 +8512,39 @@ void Dbtc::execSCAN_TABREQ(Signal* signal)
if ((transid1 == buddyApiPtr.p->transid[0]) &&
(transid2 == buddyApiPtr.p->transid[1])) {
jam();
+
+ if (buddyApiPtr.p->apiConnectstate == CS_ABORTING) {
+ // transaction has been aborted
+ jam();
+ errCode = buddyApiPtr.p->returncode;
+ goto SCAN_TAB_error;
+ }//if
currSavePointId = buddyApiPtr.p->currSavePointId;
buddyApiPtr.p->currSavePointId++;
}
}
seizeTcConnect(signal);
+ tcConnectptr.p->apiConnect = apiConnectptr.i;
+
seizeCacheRecord(signal);
- seizeScanrec(signal);
- initScanrec(signal, scanParallel, noOprecPerFrag);
- initScanTcrec(signal);
- initScanApirec(signal, buddyPtr, transid1, transid2);
- cnoFreeScanOprec = cnoFreeScanOprec - scanParallel;
+ scanptr = seizeScanrec(signal);
+
+ ndbrequire(transP->apiScanRec == RNIL);
+ ndbrequire(scanptr.p->scanApiRec == RNIL);
+
+ initScanrec(scanptr, scanTabReq, scanParallel, noOprecPerFrag);
+
+ //initScanApirec(signal, buddyPtr, transid1, transid2);
+ transP->apiScanRec = scanptr.i;
+ transP->returncode = 0;
+ transP->transid[0] = transid1;
+ transP->transid[1] = transid2;
+ transP->buddyPtr = buddyPtr;
// The scan is started
- apiConnectptr.p->apiConnectstate = CS_START_SCAN;
- apiConnectptr.p->currSavePointId = currSavePointId;
+ transP->apiConnectstate = CS_START_SCAN;
+ transP->currSavePointId = currSavePointId;
/**********************************************************
* We start the timer on scanRec to be able to discover a
@@ -8544,11 +8552,7 @@ void Dbtc::execSCAN_TABREQ(Signal* signal)
***********************************************************/
setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
updateBuddyTimer(apiConnectptr);
- if (scanptr.p->noScanTabInfo > 1) {
- jam();
- scanptr.p->scanState = ScanRecord::WAIT_SCAN_TAB_INFO;
- return;
- }//if
+
/***********************************************************
* WE HAVE NOW RECEIVED ALL REFERENCES TO SCAN OBJECTS IN
* THE API. WE ARE NOW READY TO RECEIVE THE ATTRIBUTE INFO
@@ -8564,48 +8568,28 @@ void Dbtc::execSCAN_TABREQ(Signal* signal)
SCAN_TAB_error:
jam();
ScanTabRef * ref = (ScanTabRef*)&signal->theData[0];
- ref->apiConnectPtr = apiConnectptr.p->ndbapiConnect;
+ ref->apiConnectPtr = transP->ndbapiConnect;
ref->transId1 = transid1;
ref->transId2 = transid2;
ref->errorCode = errCode;
- sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_SCAN_TABREF,
+ ref->closeNeeded = 0;
+ sendSignal(transP->ndbapiBlockref, GSN_SCAN_TABREF,
signal, ScanTabRef::SignalLength, JBB);
return;
}//Dbtc::execSCAN_TABREQ()
-void Dbtc::initScanTcrec(Signal* signal)
-{
- tcConnectptr.p->apiConnect = apiConnectptr.i;
-}//Dbtc::initScanTcrec()
void Dbtc::initScanApirec(Signal* signal,
Uint32 buddyPtr, UintR transid1, UintR transid2)
{
- ApiConnectRecord * apiPtr = apiConnectptr.p;
- apiPtr->apiScanRec = scanptr.i;
- apiPtr->returncode = 0;
- apiPtr->transid[0] = transid1;
- apiPtr->transid[1] = transid2;
- apiPtr->buddyPtr = buddyPtr;
-
}//Dbtc::initScanApirec()
-void Dbtc::initScanOprec(Signal* signal)
-{
- UintR tisoIndex;
-
- for (tisoIndex = 0; tisoIndex < 16; tisoIndex++) {
- scanOpptr.p->apiOpptr[tisoIndex] = cdata[tisoIndex];
- scanOpptr.p->scanOpLength[tisoIndex] = RNIL;
- }//for
-}//Dbtc::initScanOprec()
-
-void Dbtc::initScanrec(Signal* signal,
+void Dbtc::initScanrec(ScanRecordPtr scanptr,
+ const ScanTabReq * scanTabReq,
UintR scanParallel,
UintR noOprecPerFrag)
{
- const ScanTabReq * const scanTabReq = (ScanTabReq *)&signal->theData[0];
const UintR reqinfo = scanTabReq->requestInfo;
ndbrequire(scanParallel < 16);
@@ -8615,34 +8599,26 @@ void Dbtc::initScanrec(Signal* signal,
scanptr.p->scanTableref = tabptr.i;
scanptr.p->scanSchemaVersion = scanTabReq->tableSchemaVersion;
scanptr.p->scanParallel = scanParallel;
- scanptr.p->noScanOprec = scanParallel;
- scanptr.p->noScanTabInfo = scanParallel;
- scanptr.p->scanTabInfoReceived = 1;
- scanptr.p->scanProcessesCompleted = 0;
+ scanptr.p->noOprecPerFrag = noOprecPerFrag;
scanptr.p->scanLockMode = ScanTabReq::getLockMode(reqinfo);
scanptr.p->scanLockHold = ScanTabReq::getHoldLockFlag(reqinfo);
scanptr.p->readCommitted = ScanTabReq::getReadCommittedFlag(reqinfo);
scanptr.p->rangeScan = ScanTabReq::getRangeScanFlag(reqinfo);
scanptr.p->scanStoredProcId = scanTabReq->storedProcId;
- scanptr.p->scanReceivedOperations = 0;
- scanptr.p->noOprecPerFrag = noOprecPerFrag;
- scanptr.p->apiIsClosed = false;
- scanptr.p->scanCompletedStatus = ZFALSE;
- scanptr.p->scanState = ScanRecord::SCAN_NEXT_ORDERED;
- for (Uint32 i = 0; i < 16; i++) {
- if (i < scanParallel){
- jam();
- seizeScanOprec(signal);
- scanptr.p->scanOprec[i] = scanOpptr.i;
- } else {
- jam();
- scanptr.p->scanOprec[i] = RNIL;
- }
- scanptr.p->scanFragrec[i] = RNIL;
+ scanptr.p->scanState = ScanRecord::RUNNING;
+ scanptr.p->m_queued_count = 0;
+
+ ScanFragList list(c_scan_frag_pool,
+ scanptr.p->m_running_scan_frags);
+ for (Uint32 i = 0; i < scanParallel; i++) {
+ jam();
+ ScanFragRecPtr ptr;
+ ndbrequire(list.seize(ptr));
+ ptr.p->scanRec = scanptr.i;
+ ptr.p->scanFragId = 0;
+ ptr.p->scanFragConcurrency = noOprecPerFrag;
+ ptr.p->m_apiPtr = cdata[i];
}//for
- scanOpptr.i = scanptr.p->scanOprec[0];
- ptrCheckGuard(scanOpptr, cscanOprecFileSize, scanOperationRecord);
- initScanOprec(signal);
}//Dbtc::initScanrec()
void Dbtc::scanTabRefLab(Signal* signal, Uint32 errCode)
@@ -8652,68 +8628,18 @@ void Dbtc::scanTabRefLab(Signal* signal, Uint32 errCode)
ref->transId1 = apiConnectptr.p->transid[0];
ref->transId2 = apiConnectptr.p->transid[1];
ref->errorCode = errCode;
+ ref->closeNeeded = 0;
sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_SCAN_TABREF,
signal, ScanTabRef::SignalLength, JBB);
}//Dbtc::scanTabRefLab()
-/******************************************************
- * execSCAN_TABINFO
- ******************************************************/
-void Dbtc::execSCAN_TABINFO(Signal* signal)
-{
- jamEntry();
- apiConnectptr.i = signal->theData[0];
- for(int i=0; i<16; i++)
- cdata[i] = signal->theData[i+1];
-
- if (apiConnectptr.i >= capiConnectFilesize) {
- jam();
- warningHandlerLab(signal);
- return;
- }//if
- ptrAss(apiConnectptr, apiConnectRecord);
-
- if (apiConnectptr.p->apiConnectstate != CS_START_SCAN){
- jam();
- DEBUG("apiPtr(" << apiConnectptr.i << ") Dropping SCAN_TABINFO, wrong state: " << apiConnectptr.p->apiConnectstate);
- return;
- }
-
- scanptr.i = apiConnectptr.p->apiScanRec;
- ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
-
- const Uint32 tscanOprec = scanptr.p->scanTabInfoReceived;
- scanptr.p->scanTabInfoReceived++;
- arrGuard(tscanOprec, 16);
- scanOpptr.i = scanptr.p->scanOprec[tscanOprec];
- ptrCheckGuard(scanOpptr, cscanOprecFileSize, scanOperationRecord);
- // Start timer and wait for response from API node.
- setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
- updateBuddyTimer(apiConnectptr);
-
- initScanOprec(signal);
- // Start timer and wait for response from API node.
- setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
- updateBuddyTimer(apiConnectptr);
-
- if (scanptr.p->scanTabInfoReceived == scanptr.p->noScanTabInfo) {
- jam();
- /******************************************************************
- * WE HAVE NOW RECEIVED ALL REFERENCES TO SCAN OBJECTS IN THE API.
- * WE ARE NOW READY TO RECEIVE THE ATTRIBUTE INFO IF ANY TO RECEIVE.
- ******************************************************************/
- scanptr.p->scanState = ScanRecord::WAIT_AI;
- return;
- }
- ndbrequire(scanptr.p->scanTabInfoReceived <= scanptr.p->noScanTabInfo);
-}//Dbtc::execSCAN_TABINFO()
-
/*---------------------------------------------------------------------------*/
/* */
/* RECEPTION OF ATTRINFO FOR SCAN TABLE REQUEST. */
/*---------------------------------------------------------------------------*/
void Dbtc::scanAttrinfoLab(Signal* signal, UintR Tlen)
{
+ ScanRecordPtr scanptr;
scanptr.i = apiConnectptr.p->apiScanRec;
ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
tcConnectptr.i = scanptr.p->scanTcrec;
@@ -8743,7 +8669,7 @@ void Dbtc::scanAttrinfoLab(Signal* signal, UintR Tlen)
* THIS SCAN. WE ARE READY TO START THE ACTUAL
* EXECUTION OF THE SCAN QUERY
**************************************************/
- diFcountReqLab(signal);
+ diFcountReqLab(signal, scanptr);
return;
}//if
}//if
@@ -8751,21 +8677,21 @@ void Dbtc::scanAttrinfoLab(Signal* signal, UintR Tlen)
scanAttrinfo_attrbuf_error:
jam();
- abortScanLab(signal, ZGET_ATTRBUF_ERROR);
+ abortScanLab(signal, scanptr, ZGET_ATTRBUF_ERROR);
return;
scanAttrinfo_attrbuf2_error:
jam();
- abortScanLab(signal, ZGET_ATTRBUF_ERROR);
+ abortScanLab(signal, scanptr, ZGET_ATTRBUF_ERROR);
return;
scanAttrinfo_len_error:
jam();
- abortScanLab(signal, ZLENGTH_ERROR);
+ abortScanLab(signal, scanptr, ZLENGTH_ERROR);
return;
}//Dbtc::scanAttrinfoLab()
-void Dbtc::diFcountReqLab(Signal* signal)
+void Dbtc::diFcountReqLab(Signal* signal, ScanRecordPtr scanptr)
{
/**
* Check so that the table is not being dropped
@@ -8776,7 +8702,8 @@ void Dbtc::diFcountReqLab(Signal* signal)
if (tabPtr.p->checkTable(scanptr.p->scanSchemaVersion)){
;
} else {
- abortScanLab(signal, tabPtr.p->getErrorCode(scanptr.p->scanSchemaVersion));
+ abortScanLab(signal, scanptr,
+ tabPtr.p->getErrorCode(scanptr.p->scanSchemaVersion));
return;
}
@@ -8808,18 +8735,19 @@ void Dbtc::execDI_FCOUNTCONF(Signal* signal)
ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
apiConnectptr.i = tcConnectptr.p->apiConnect;
ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
+ ScanRecordPtr scanptr;
scanptr.i = apiConnectptr.p->apiScanRec;
ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
ndbrequire(scanptr.p->scanState == ScanRecord::WAIT_FRAGMENT_COUNT);
if (apiConnectptr.p->apiFailState == ZTRUE) {
jam();
- releaseScanResources(signal);
+ releaseScanResources(scanptr);
handleApiFailState(signal, apiConnectptr.i);
return;
}//if
if (tfragCount == 0) {
jam();
- abortScanLab(signal, ZNO_FRAGMENT_ERROR);
+ abortScanLab(signal, scanptr, ZNO_FRAGMENT_ERROR);
return;
}//if
@@ -8832,35 +8760,43 @@ void Dbtc::execDI_FCOUNTCONF(Signal* signal)
if (tabPtr.p->checkTable(scanptr.p->scanSchemaVersion)){
;
} else {
- abortScanLab(signal, tabPtr.p->getErrorCode(scanptr.p->scanSchemaVersion));
+ abortScanLab(signal, scanptr,
+ tabPtr.p->getErrorCode(scanptr.p->scanSchemaVersion));
return;
}
- if (tfragCount < scanptr.p->scanParallel) {
+ if(scanptr.p->scanParallel > tfragCount){
jam();
- for (Uint32 i = tfragCount; i < scanptr.p->scanParallel; i++) {
- jam();
- arrGuard(i, 16);
- scanOpptr.i = scanptr.p->scanOprec[i];
- ptrCheckGuard(scanOpptr, cscanOprecFileSize, scanOperationRecord);
- releaseScanOprec(signal);
- scanptr.p->scanOprec[i] = RNIL;
- }//for
- scanptr.p->scanParallel = tfragCount;
- }//if
+ abortScanLab(signal, scanptr, ZTOO_HIGH_CONCURRENCY_ERROR);
+ return;
+ }
+
+ scanptr.p->scanParallel = tfragCount;
scanptr.p->scanNoFrag = tfragCount;
- for (UintR i = 0; i < scanptr.p->scanParallel; i++) {
- jam();
- // START EACH OF THE PARALLEL SCAN PROCESSES
- signal->theData[0] = scanptr.i;
- signal->theData[1] = i;
- signal->theData[2] = scanptr.p->noOprecPerFrag;
- sendSignal(cownref, GSN_SCAN_PROCREQ, signal, 3, JBB);
- }//for
- // We don't need the timer for checking API anymore, control goes to LQH.
+ scanptr.p->scanNextFragId = 0;
+ scanptr.p->scanState = ScanRecord::RUNNING;
+
setApiConTimer(apiConnectptr.i, 0, __LINE__);
- scanptr.p->scanNextFragId = scanptr.p->scanParallel;
- scanptr.p->scanState = ScanRecord::SCAN_NEXT_ORDERED;
+ updateBuddyTimer(apiConnectptr);
+
+ ScanFragRecPtr ptr;
+ ScanFragList list(c_scan_frag_pool,
+ scanptr.p->m_running_scan_frags);
+ for (list.first(ptr); !ptr.isNull(); list.next(ptr)){
+ jam();
+
+ ptr.p->lqhBlockref = 0;
+ ptr.p->startFragTimer(ctcTimer);
+ ptr.p->scanFragId = scanptr.p->scanNextFragId++;
+ ptr.p->scanFragState = ScanFragRec::WAIT_GET_PRIMCONF;
+ ptr.p->startFragTimer(ctcTimer);
+
+ signal->theData[0] = tcConnectptr.p->dihConnectptr;
+ signal->theData[1] = ptr.i;
+ signal->theData[2] = scanptr.p->scanTableref;
+ signal->theData[3] = ptr.p->scanFragId;
+ sendSignal(cdihblockref, GSN_DIGETPRIMREQ, signal, 4, JBB);
+ }//for
}//Dbtc::execDI_FCOUNTCONF()
/******************************************************
@@ -8874,140 +8810,60 @@ void Dbtc::execDI_FCOUNTREF(Signal* signal)
const Uint32 errCode = signal->theData[1];
apiConnectptr.i = tcConnectptr.p->apiConnect;
ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
+ ScanRecordPtr scanptr;
scanptr.i = apiConnectptr.p->apiScanRec;
ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
ndbrequire(scanptr.p->scanState == ScanRecord::WAIT_FRAGMENT_COUNT);
if (apiConnectptr.p->apiFailState == ZTRUE) {
jam();
- releaseScanResources(signal);
+ releaseScanResources(scanptr);
handleApiFailState(signal, apiConnectptr.i);
return;
}//if
- abortScanLab(signal, errCode);
+ abortScanLab(signal, scanptr, errCode);
}//Dbtc::execDI_FCOUNTREF()
-void Dbtc::abortScanLab(Signal* signal, Uint32 errCode)
+void Dbtc::abortScanLab(Signal* signal, ScanRecordPtr scanptr, Uint32 errCode)
{
- releaseScanResources(signal);
scanTabRefLab(signal, errCode);
+ releaseScanResources(scanptr);
}//Dbtc::abortScanLab()
-void Dbtc::scanReleaseResourcesLab(Signal* signal)
-{
- apiConnectptr.i = scanptr.p->scanApiRec;
- ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
- if (apiConnectptr.p->returncode != 0) {
- jam();
- ScanTabRef * ref = (ScanTabRef*)&signal->theData[0];
- ref->apiConnectPtr = apiConnectptr.p->ndbapiConnect;
- ref->transId1 = apiConnectptr.p->transid[0];
- ref->transId2 = apiConnectptr.p->transid[1];
- ref->errorCode = apiConnectptr.p->returncode;
- sendSignal(apiConnectptr.p->ndbapiBlockref,
- GSN_SCAN_TABREF, signal, ScanTabRef::SignalLength, JBB);
- } else {
- jam();
- sendScanTabConf(signal);
- }//if
- releaseScanResources(signal);
- if (apiConnectptr.p->apiFailState == ZTRUE) {
- jam();
- handleApiFailState(signal, apiConnectptr.i);
- return;
- }//if
-}//Dbtc::scanReleaseResourcesLab()
-
-void Dbtc::releaseScanResources(Signal* signal)
+void Dbtc::releaseScanResources(ScanRecordPtr scanPtr)
{
if (apiConnectptr.p->cachePtr != RNIL) {
cachePtr.i = apiConnectptr.p->cachePtr;
ptrCheckGuard(cachePtr, ccacheFilesize, cacheRecord);
- releaseAttrinfo(signal);
+ releaseAttrinfo();
}//if
- cnoFreeScanOprec = cnoFreeScanOprec + scanptr.p->noScanOprec;
- scanptr.p->scanCompletedStatus = ZCLOSED;
- tcConnectptr.i = scanptr.p->scanTcrec;
+ tcConnectptr.i = scanPtr.p->scanTcrec;
ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
- releaseTcCon(signal);
- for (Uint32 i = 0; i < 16; i++) {
- jam();
- scanFragptr.i = scanptr.p->scanFragrec[i];
- scanptr.p->scanFragrec[i] = RNIL;
- if (scanFragptr.i != RNIL) {
- jam();
- ptrCheckGuard(scanFragptr, cscanFragrecFileSize, scanFragmentRecord);
- releaseScanFragrec(signal);
- }//if
- scanOpptr.i = scanptr.p->scanOprec[i];
- scanptr.p->scanOprec[i] = RNIL;
- if (scanOpptr.i != RNIL) {
- jam();
- ptrCheckGuard(scanOpptr, cscanOprecFileSize, scanOperationRecord);
- releaseScanOprec(signal);
- }//if
- }//for
- releaseScanrec(signal);
+ releaseTcCon();
+
+ ScanFragList x(c_scan_frag_pool,
+ scanPtr.p->m_completed_scan_frags);
+ x.release();
+ ndbrequire(scanPtr.p->m_running_scan_frags.isEmpty());
+ ndbrequire(scanPtr.p->m_queued_scan_frags.isEmpty());
+ ndbrequire(scanPtr.p->m_delivered_scan_frags.isEmpty());
+
+
+ ndbassert(scanPtr.p->scanApiRec == apiConnectptr.i);
+ ndbassert(apiConnectptr.p->apiScanRec == scanPtr.i);
+
+ // link into free list
+ scanPtr.p->nextScan = cfirstfreeScanrec;
+ scanPtr.p->scanState = ScanRecord::IDLE;
+ scanPtr.p->scanTcrec = RNIL;
+ scanPtr.p->scanApiRec = RNIL;
+ cfirstfreeScanrec = scanPtr.i;
+
apiConnectptr.p->apiScanRec = RNIL;
apiConnectptr.p->apiConnectstate = CS_CONNECTED;
setApiConTimer(apiConnectptr.i, 0, __LINE__);
}//Dbtc::releaseScanResources()
-/******************************************************
- * execSCAN_PROCREQ
- ******************************************************/
-void Dbtc::execSCAN_PROCREQ(Signal* signal)
-{
- jamEntry();
- scanptr.i = signal->theData[0];
- ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
-
- const UintR tscanFragId = signal->theData[1];
- ndbrequire(tscanFragId < 16);
- const UintR tscanNoOprec = signal->theData[2];
-
- ndbrequire(cfirstfreeScanFragrec != RNIL);
- seizeScanFragrec(signal);
-
- apiConnectptr.i = scanptr.p->scanApiRec;
- ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
- setApiConTimer(apiConnectptr.i, 0, __LINE__);
-
- scanptr.p->scanFragrec[tscanFragId] = scanFragptr.i;
- scanFragptr.p->scanRec = scanptr.i;
- scanFragptr.p->scanIndividual = tscanFragId * tscanNoOprec;
- scanFragptr.p->scanFragProcId = tscanFragId;
- scanFragptr.p->scanFragId = tscanFragId;
- scanFragptr.p->scanFragConcurrency = tscanNoOprec;
- scanFragptr.p->scanFragCompletedStatus = ZFALSE;
- tcConnectptr.i = scanptr.p->scanTcrec;
- ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
-
- {
- /**
- * Check table
- */
- TableRecordPtr tabPtr;
- tabPtr.i = scanptr.p->scanTableref;
- ptrAss(tabPtr, tableRecord);
- Uint32 schemaVersion = scanptr.p->scanSchemaVersion;
- if(tabPtr.p->checkTable(schemaVersion) == false){
- jam();
- scanFragError(signal, tabPtr.p->getErrorCode(schemaVersion));
- return;
- }
- }
-
- signal->theData[0] = tcConnectptr.p->dihConnectptr;
- signal->theData[1] = scanFragptr.i;
- signal->theData[2] = scanptr.p->scanTableref;
- signal->theData[3] = tscanFragId;
- sendSignal(cdihblockref, GSN_DIGETPRIMREQ, signal, 4, JBB);
- scanFragptr.p->scanFragState = ScanFragRec::WAIT_GET_PRIMCONF;
- updateBuddyTimer(apiConnectptr);
- scanFragptr.p->startFragTimer(ctcTimer);
-}//Dbtc::execSCAN_PROCREQ()
-
/****************************************************************
* execDIGETPRIMCONF
*
@@ -9020,15 +8876,15 @@ void Dbtc::execDIGETPRIMCONF(Signal* signal)
jamEntry();
// tcConnectptr.i in theData[0] is not used
scanFragptr.i = signal->theData[1];
- ptrCheckGuard(scanFragptr, cscanFragrecFileSize, scanFragmentRecord);
+ c_scan_frag_pool.getPtr(scanFragptr);
tnodeid = signal->theData[2];
arrGuard(tnodeid, MAX_NDB_NODES);
ndbrequire(scanFragptr.p->scanFragState == ScanFragRec::WAIT_GET_PRIMCONF);
scanFragptr.p->stopFragTimer();
- scanFragptr.p->lqhBlockref = RNIL;
-
+
+ ScanRecordPtr scanptr;
scanptr.i = scanFragptr.p->scanRec;
ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
@@ -9042,7 +8898,12 @@ void Dbtc::execDIGETPRIMCONF(Signal* signal)
Uint32 schemaVersion = scanptr.p->scanSchemaVersion;
if(tabPtr.p->checkTable(schemaVersion) == false){
jam();
- scanFragError(signal, tabPtr.p->getErrorCode(schemaVersion));
+ ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
+ ScanFragList comp(c_scan_frag_pool, scanptr.p->m_completed_scan_frags);
+
+ run.remove(scanFragptr);
+ comp.add(scanFragptr);
+ scanError(signal, scanptr, tabPtr.p->getErrorCode(schemaVersion));
return;
}
}
@@ -9057,18 +8918,24 @@ void Dbtc::execDIGETPRIMCONF(Signal* signal)
case ScanRecord::CLOSING_SCAN:
jam();
updateBuddyTimer(apiConnectptr);
- scanFragptr.p->startFragTimer(ctcTimer);
- sendScanProcConf(signal);
+ {
+ ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
+ ScanFragList comp(c_scan_frag_pool, scanptr.p->m_completed_scan_frags);
+
+ run.remove(scanFragptr);
+ comp.add(scanFragptr);
+ }
+ close_scan_req_send_conf(signal, scanptr);
return;
default:
jam();
/*empty*/;
break;
}//switch
- scanFragptr.p->scanFragNodeId = tnodeid;
- scanFragptr.p->lqhBlockref = calcLqhBlockRef(tnodeid);
+ Uint32 ref = calcLqhBlockRef(tnodeid);
+ scanFragptr.p->lqhBlockref = ref;
scanFragptr.p->m_connectCount = getNodeInfo(tnodeid).m_connectCount;
- sendScanFragReq(signal);
+ sendScanFragReq(signal, scanptr.p, scanFragptr.p);
attrbufptr.i = cachePtr.p->firstAttrbuf;
while (attrbufptr.i != RNIL) {
jam();
@@ -9076,12 +8943,12 @@ void Dbtc::execDIGETPRIMCONF(Signal* signal)
sendAttrinfo(signal,
scanFragptr.i,
attrbufptr.p,
- scanFragptr.p->lqhBlockref);
+ ref);
attrbufptr.i = attrbufptr.p->attrbuf[ZINBUF_NEXT];
}//while
scanFragptr.p->scanFragState = ScanFragRec::LQH_ACTIVE;
- updateBuddyTimer(apiConnectptr);
scanFragptr.p->startFragTimer(ctcTimer);
+ updateBuddyTimer(apiConnectptr);
/*********************************************
* WE HAVE NOW STARTED A FRAGMENT SCAN. NOW
* WAIT FOR THE FIRST SCANNED RECORDS
@@ -9101,9 +8968,20 @@ void Dbtc::execDIGETPRIMREF(Signal* signal)
// tcConnectptr.i in theData[0] is not used.
scanFragptr.i = signal->theData[1];
const Uint32 errCode = signal->theData[2];
- ptrCheckGuard(scanFragptr, cscanFragrecFileSize, scanFragmentRecord);
+ c_scan_frag_pool.getPtr(scanFragptr);
ndbrequire(scanFragptr.p->scanFragState == ScanFragRec::WAIT_GET_PRIMCONF);
- scanFragError(signal, errCode);
+
+ ScanRecordPtr scanptr;
+ scanptr.i = scanFragptr.p->scanRec;
+ ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
+
+ ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
+ ScanFragList comp(c_scan_frag_pool, scanptr.p->m_completed_scan_frags);
+
+ run.remove(scanFragptr);
+ comp.add(scanFragptr);
+
+ scanError(signal, scanptr, errCode);
}//Dbtc::execDIGETPRIMREF()
/**
@@ -9120,8 +8998,9 @@ void Dbtc::execSCAN_FRAGREF(Signal* signal)
const Uint32 errCode = ref->errorCode;
scanFragptr.i = ref->senderData;
- ptrCheckGuard(scanFragptr, cscanFragrecFileSize, scanFragmentRecord);
+ c_scan_frag_pool.getPtr(scanFragptr);
+ ScanRecordPtr scanptr;
scanptr.i = scanFragptr.p->scanRec;
ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
@@ -9141,56 +9020,64 @@ void Dbtc::execSCAN_FRAGREF(Signal* signal)
* stop fragment timer and call scanFragError to start
* close of the other fragment scans
*/
- scanFragptr.p->lqhBlockref = RNIL;
- scanFragError(signal, errCode);
+ ndbrequire(scanFragptr.p->scanFragState == ScanFragRec::LQH_ACTIVE);
+ {
+ scanFragptr.p->scanFragState = ScanFragRec::COMPLETED;
+ ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
+ ScanFragList comp(c_scan_frag_pool, scanptr.p->m_completed_scan_frags);
+
+ run.remove(scanFragptr);
+ comp.add(scanFragptr);
+ scanFragptr.p->stopFragTimer();
+ }
+ scanError(signal, scanptr, errCode);
}//Dbtc::execSCAN_FRAGREF()
/**
- * Dbtc::scanFragError
+ * Dbtc::scanError
*
* Called when an error occurs during
- * a scan of a fragment.
- * NOTE that one scan may consist of several fragment scans.
- *
*/
-void Dbtc::scanFragError(Signal* signal, Uint32 errorCode)
+void Dbtc::scanError(Signal* signal, ScanRecordPtr scanptr, Uint32 errorCode)
{
jam();
- scanptr.i = scanFragptr.p->scanRec;
- ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
- DEBUG("scanFragError, errorCode = "<< errorCode
- << ", scanState = " << scanptr.p->scanState);
-
- scanFragptr.p->stopFragTimer();
+ ScanRecord* scanP = scanptr.p;
+
+ DEBUG("scanError, errorCode = "<< errorCode <<
+ ", scanState = " << scanptr.p->scanState);
- apiConnectptr.i = scanptr.p->scanApiRec;
+ apiConnectptr.i = scanP->scanApiRec;
ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
- if (scanFragptr.p->lqhBlockref == RNIL){
- // Since the lqh is closed, this scan process should be reported
- // as completed immediately
- jam();
- updateBuddyTimer(apiConnectptr);
- scanFragptr.p->startFragTimer(ctcTimer);
- sendScanProcConf(signal);
- }//if
+ ndbrequire(apiConnectptr.p->apiScanRec == scanptr.i);
- // If close of the scan is not already started
- if (scanptr.p->scanState != ScanRecord::CLOSING_SCAN) {
+ if(scanP->scanState == ScanRecord::CLOSING_SCAN){
jam();
- apiConnectptr.p->returncode = errorCode;
-
- /**
- * Only set apiIsClosed if API is waiting for an answer
- */
- if (scanptr.p->scanState == ScanRecord::SCAN_NEXT_ORDERED){
- jam();
- scanptr.p->apiIsClosed = true;
- }
- scanCompletedLab(signal);
+ close_scan_req_send_conf(signal, scanptr);
return;
- }//if
-}//Dbtc::scanFragError()
-
+ }
+
+ ndbrequire(scanP->scanState == ScanRecord::RUNNING);
+
+ /**
+ * Close scan wo/ having received an order to do so
+ */
+ close_scan_req(signal, scanptr, false);
+
+ const bool apiFail = (apiConnectptr.p->apiFailState == ZTRUE);
+ if(apiFail){
+ jam();
+ return;
+ }
+
+ ScanTabRef * ref = (ScanTabRef*)&signal->theData[0];
+ ref->apiConnectPtr = apiConnectptr.p->ndbapiConnect;
+ ref->transId1 = apiConnectptr.p->transid[0];
+ ref->transId2 = apiConnectptr.p->transid[1];
+ ref->errorCode = errorCode;
+ ref->closeNeeded = 1;
+ sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_SCAN_TABREF,
+ signal, ScanTabRef::SignalLength, JBB);
+}//Dbtc::scanError()
/************************************************************
* execSCAN_FRAGCONF
@@ -9205,14 +9092,13 @@ void Dbtc::execSCAN_FRAGCONF(Signal* signal)
const ScanFragConf * const conf = (ScanFragConf*)&signal->theData[0];
const Uint32 noCompletedOps = conf->completedOps;
- for(Uint32 i = 0; i<noCompletedOps; i++)
- cdata[i] = conf->opReturnDataLen[i];
scanFragptr.i = conf->senderData;
- ptrCheckGuard(scanFragptr, cscanFragrecFileSize, scanFragmentRecord);
-
+ c_scan_frag_pool.getPtr(scanFragptr);
+
+ ScanRecordPtr scanptr;
scanptr.i = scanFragptr.p->scanRec;
ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
-
+
apiConnectptr.i = scanptr.p->scanApiRec;
ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
@@ -9223,270 +9109,79 @@ void Dbtc::execSCAN_FRAGCONF(Signal* signal)
jam();
systemErrorLab(signal);
}//if
-
- scanFragptr.p->scanFragCompletedStatus = conf->fragmentCompleted;
- scanFragptr.p->stopFragTimer();
-
- switch (scanFragptr.p->scanFragCompletedStatus) {
- case ZFALSE:
- case ZTRUE:
- jam();
- /* empty */
- break;
-
- case ZCLOSED:
- /* The scan has finished this fragment. */
- jam();
- returnFromQueuedDeliveryLab(signal);
- return;
- break;
-
- default:
- jam();
- systemErrorLab(signal);
- break;
- }//switch
-
- // CHECK THE STATE OF THE DELIVERY PROCESS TO THE APPLICATION.
- switch (scanptr.p->scanState) {
- case ScanRecord::SCAN_NEXT_ORDERED:
+
+ ndbrequire(scanFragptr.p->scanFragState == ScanFragRec::LQH_ACTIVE);
+
+ const Uint32 status = conf->fragmentCompleted;
+
+ if(scanptr.p->scanState == ScanRecord::CLOSING_SCAN){
jam();
- /**
- * THE APPLICATION HAVE ISSUED A SCAN_NEXTREQ AND IS WAITING
- * FOR MORE OPERATIONS. SEND OPERATIONS DIRECTLY
- */
- if (noCompletedOps > 0) {
- jam();
- setScanReceived(signal, noCompletedOps);
- sendScanTabConf(signal);
- scanptr.p->scanState = ScanRecord::DELIVERED;
- scanFragptr.p->scanFragState = ScanFragRec::DELIVERED;
+ if(status == ZFALSE){
+ /**
+ * We have started closing = we sent a close -> ignore this
+ */
return;
- }//if
- break;
-
- case ScanRecord::DELIVERED:
- case ScanRecord::QUEUED_DELIVERED:
- jam();
- /**
- * THE APPLICATION HAVE ALREADY RECEIVED A DELIVERY.
- * QUEUE THE RECEIVED SCAN OPERATIONS AND ISSUE THEM
- * WHEN THE APPLICATION ASKS FOR MORE.
- */
- if (noCompletedOps > 0) {
+ } else {
jam();
- setScanReceived(signal, noCompletedOps);
- scanptr.p->scanState = ScanRecord::QUEUED_DELIVERED;
- scanFragptr.p->scanFragState = ScanFragRec::QUEUED_FOR_DELIVERY;
- return;
- }//if
- break;
-
- case ScanRecord::CLOSING_SCAN:
- jam();
- /*************************************************
- * WE ARE CURRENTLY CLOSING THE SCAN.
- *
- * WE HAVE ALREADY ORDERED THE FRAGMENT TO CLOSE ITS
- * SCAN. THIS SIGNAL MUST HAVE BEEN SENT BEFORE THIS
- * CLOSE SIGNAL ARRIVED. SIMPLY IGNORE THIS SIGNAL.
- **************************************************/
+ ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
+ ScanFragList comp(c_scan_frag_pool, scanptr.p->m_completed_scan_frags);
+
+ run.remove(scanFragptr);
+ comp.add(scanFragptr);
+ scanFragptr.p->stopFragTimer();
+ scanFragptr.p->scanFragState = ScanFragRec::COMPLETED;
+ }
+ close_scan_req_send_conf(signal, scanptr);
return;
- break;
-
- default:
- jam();
- systemErrorLab(signal);
- break;
-
- }//switch
+ }
- /**
- * THERE WAS NO TUPLES LEFT TO REPORT IN THIS FRAGMENT. CLOSE SCAN
- * HAVE NOT BEEN ORDERED. WE CAN CONTINUE THE SCAN PROCESS IMMEDIATELY.
- * THE COMPLETED STATUS MUST BE TRUE SINCE IT IS NOT CLOSED. IF IT WAS
- * FALSE IT MUST HAVE BEEN MORE TUPLES TO SCAN AND AT LEAST ONE OF
- * THOSE SHOULD HAVE BEEN REPORTED.
- */
- if (scanFragptr.p->scanFragCompletedStatus == ZFALSE) {
- jam();
+ if(status == ZCLOSED && scanptr.p->scanNextFragId < scanptr.p->scanNoFrag){
/**
- * THE SENDING NODE IS OUT OF ORDER WE WILL KILL IT BY SENDING SYSTEM
- * ERROR TO IT
+ * Start on next fragment
*/
- const BlockReference errRef =
- calcNdbCntrBlockRef(scanFragptr.p->scanFragNodeId);
- SystemError * const sysErr = (SystemError*)&signal->theData[0];
- sysErr->errorCode = SystemError::ScanfragStateError;
- sysErr->errorRef = reference();
- sendSignal(errRef, GSN_SYSTEM_ERROR, signal,
- SystemError::SignalLength, JBA);
- return;
- }//if
- returnFromQueuedDeliveryLab(signal);
-}//Dbtc::execSCAN_FRAGCONF()
-
-void Dbtc::returnFromQueuedDeliveryLab(Signal* signal)
-{
- apiConnectptr.i = scanptr.p->scanApiRec;
- ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
-
- switch(scanFragptr.p->scanFragCompletedStatus) {
- case ZFALSE:
- {
- /*********************************************************************
- * WE HAVE SENT THE SCANNED OPERATION TO THE APPLICATION AND WE HAVE
- * RECEIVED THE ORDER TO CONTINUE SCANNING. THE CURRENT FRAGMENT STILL
- * CONTAINS MORE TUPLES TO SCAN.
- *********************************************************************/
- jam();
- scanFragptr.p->scanFragState = ScanFragRec::LQH_ACTIVE;
- ScanFragNextReq * nextReq = (ScanFragNextReq*)&signal->theData[0];
- nextReq->senderData = scanFragptr.i;
- nextReq->closeFlag = ZFALSE;
- nextReq->transId1 = apiConnectptr.p->transid[0];
- nextReq->transId2 = apiConnectptr.p->transid[1];
- sendSignal(scanFragptr.p->lqhBlockref, GSN_SCAN_NEXTREQ, signal,
- ScanFragNextReq::SignalLength, JBB);
- }
- break;
-
- case ZTRUE:
- {
- /*********************************************************************
- * WE HAVE SENT THE SCANNED OPERATION TO THE APPLICATION AND WE HAVE
- * RECEIVED THE ORDER TO CONTINUE SCANNING. THE CURRENT FRAGMENT HAVE
- * BEEN COMPLETELY SCANNED AND WE ARE READY TO CLOSE IT.
- *********************************************************************/
- jam();
- scanFragptr.p->scanFragState = ScanFragRec::LQH_ACTIVE_CLOSE;
- ScanFragNextReq * nextReq = (ScanFragNextReq*)&signal->theData[0];
- nextReq->senderData = scanFragptr.i;
- nextReq->closeFlag = ZTRUE;
- nextReq->transId1 = apiConnectptr.p->transid[0];
- nextReq->transId2 = apiConnectptr.p->transid[1];
- sendSignal(scanFragptr.p->lqhBlockref, GSN_SCAN_NEXTREQ, signal,
- ScanFragNextReq::SignalLength, JBB);
- }
- break;
-
- case ZCLOSED:
- {
- /********************************************************************
- * THE SCANNED FRAGMENT HAVE BEEN CLOSED. IF CLOSE SCAN HAVE BEEN
- * ORDERED THEN WE CAN REPORT THAT THIS SCAN PROCESS IS COMPLETED.
- * ALSO IF THERE ARE NO MORE FRAGMENTS TO SCAN WE CAN REPORT THAT
- * THE SCAN PROCESS IS COMPLETED.
- ********************************************************************/
- jam();
- scanFragptr.p->lqhBlockref = RNIL;
- if ((scanptr.p->scanState != ScanRecord::CLOSING_SCAN) &&
- (scanptr.p->scanNextFragId < scanptr.p->scanNoFrag)){
- jam();
- scanFragptr.p->scanFragState = ScanFragRec::WAIT_GET_PRIMCONF;
- tcConnectptr.i = scanptr.p->scanTcrec;
- ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
- scanFragptr.p->scanFragId = scanptr.p->scanNextFragId;
- scanptr.p->scanNextFragId++;
- signal->theData[0] = tcConnectptr.p->dihConnectptr;
- signal->theData[1] = scanFragptr.i;
- signal->theData[2] = scanptr.p->scanTableref;
- signal->theData[3] = scanFragptr.p->scanFragId;
- sendSignal(cdihblockref, GSN_DIGETPRIMREQ, signal, 4, JBB);
- } else {
- jam();
- sendScanProcConf(signal);
- }//if
- }
- break;
-
- default:
- jam();
- systemErrorLab(signal);
- break;
- }//switch
-
- updateBuddyTimer(apiConnectptr);
- scanFragptr.p->startFragTimer(ctcTimer);
-}//Dbtc::returnFromQueuedDeliveryLab()
-
-/**********************************************************
- * execSCAN_PROCCONF
- **********************************************************/
-void Dbtc::execSCAN_PROCCONF(Signal* signal)
-{
- jamEntry();
+ ndbrequire(noCompletedOps == 0);
+ scanFragptr.p->scanFragState = ScanFragRec::WAIT_GET_PRIMCONF;
+ scanFragptr.p->startFragTimer(ctcTimer);
- scanptr.i = signal->theData[0];
- ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
- scanptr.p->scanProcessesCompleted++;
- ndbassert(scanptr.p->scanProcessesCompleted <= scanptr.p->scanParallel);
+ tcConnectptr.i = scanptr.p->scanTcrec;
+ ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
+ scanFragptr.p->scanFragId = scanptr.p->scanNextFragId++;
+ signal->theData[0] = tcConnectptr.p->dihConnectptr;
+ signal->theData[1] = scanFragptr.i;
+ signal->theData[2] = scanptr.p->scanTableref;
+ signal->theData[3] = scanFragptr.p->scanFragId;
+ sendSignal(cdihblockref, GSN_DIGETPRIMREQ, signal, 4, JBB);
+ return;
+ }
+
+ Uint32 chksum = 0;
+ Uint32 totalLen = 0;
+ for(Uint32 i = 0; i<noCompletedOps; i++){
+ Uint32 tmp = conf->opReturnDataLen[i];
+ chksum += (tmp << i);
+ totalLen += tmp;
+ }
+
+ {
+ ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
+ ScanFragList queued(c_scan_frag_pool, scanptr.p->m_queued_scan_frags);
+
+ run.remove(scanFragptr);
+ queued.add(scanFragptr);
+ scanptr.p->m_queued_count++;
+ }
- scanFragptr.i = signal->theData[1];
- ptrCheckGuard(scanFragptr, cscanFragrecFileSize, scanFragmentRecord);
+ scanFragptr.p->m_ops = noCompletedOps;
+ scanFragptr.p->m_chksum = chksum;
+ scanFragptr.p->m_totalLen = totalLen;
+ scanFragptr.p->scanFragState = ScanFragRec::QUEUED_FOR_DELIVERY;
scanFragptr.p->stopFragTimer();
- scanFragptr.p->scanFragState = ScanFragRec::COMPLETED;
-
- if (scanptr.p->scanProcessesCompleted == scanptr.p->scanParallel) {
+
+ if(scanptr.p->m_queued_count > /** Min */ 0){
jam();
-
- // Check that all scan processes are in state COMPLETED
- for (Uint32 i = 0; i < 16; i++) {
- scanFragptr.i = scanptr.p->scanFragrec[i];
- if (scanFragptr.i != RNIL) {
- ptrCheckGuard(scanFragptr, cscanFragrecFileSize, scanFragmentRecord);
- ndbrequire(scanFragptr.p->scanFragState == ScanFragRec::COMPLETED);
- }
- }
-
- // ALL SCAN PROCESSES HAS COMPLETED
- scanptr.p->scanCompletedStatus = ZTRUE;
- switch (scanptr.p->scanState) {
-
- case ScanRecord::CLOSING_SCAN:
- jam();
- if (scanptr.p->apiIsClosed == true) {
- jam();
- /*
- * The API has either failed or ordered a close of this scan
- * it's resources should be released and a response sent
- */
- scanReleaseResourcesLab(signal);
- return;
- }//if
-
- /**
- * The close have been performed but the API is still alive and not
- * expecting a response, keep resources until API fails or it orders
- * a close
- */
- return;
- case ScanRecord::SCAN_NEXT_ORDERED:
- jam();
- /**
- * The scan is completed and api is waiting for a response.
- * Reslease resources and send a response.
- */
- scanReleaseResourcesLab(signal);
- return;
- case ScanRecord::DELIVERED:
- case ScanRecord::QUEUED_DELIVERED:
- jam();
- /**
- * All processes have reported completion, wait for a new request from
- * API and start close of the scan then.
- */
- scanptr.p->scanReceivedOperations = 0;
- scanptr.p->scanState = ScanRecord::CLOSING_SCAN;
- return;
- default:
- jam();
- systemErrorLab(signal);
- break;
- }//switch
+ sendScanTabConf(signal, scanptr.p);
}
-}//Dbtc::execSCAN_PROCCONF()
-
+}//Dbtc::execSCAN_FRAGCONF()
/****************************************************************************
* execSCAN_NEXTREQ
@@ -9522,6 +9217,7 @@ void Dbtc::execSCAN_NEXTREQ(Signal* signal)
ref->transId1 = transid1;
ref->transId2 = transid2;
ref->errorCode = ZSTATE_ERROR;
+ ref->closeNeeded = 0;
sendSignal(signal->senderBlockRef(), GSN_SCAN_TABREF,
signal, ScanTabRef::SignalLength, JBB);
DEBUG("Wrong transid");
@@ -9546,358 +9242,340 @@ void Dbtc::execSCAN_NEXTREQ(Signal* signal)
}
DEBUG("scanTabRefLab: ZSTATE_ERROR");
DEBUG(" apiConnectstate="<<apiConnectptr.p->apiConnectstate);
+ ndbrequire(false); //B2 indication of strange things going on
scanTabRefLab(signal, ZSTATE_ERROR);
return;
}//if
-
+
/*******************************************************
* START THE ACTUAL LOGIC OF SCAN_NEXTREQ.
********************************************************/
// Stop the timer that is used to check for timeout in the API
setApiConTimer(apiConnectptr.i, 0, __LINE__);
+ ScanRecordPtr scanptr;
scanptr.i = apiConnectptr.p->apiScanRec;
ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
+ ScanRecord* scanP = scanptr.p;
- if (scanptr.p->apiIsClosed == true) {
- jam();
- /**
- * The close is already started. Api has failed or
- * has not responded in time so this signal is not allowed
- */
- DEBUG("execSCAN_NEXTREQ: apiIsClosed == true");
- DEBUG(" apiConnectstate="<<apiConnectptr.p->apiConnectstate);
- DEBUG(" scanState="<<scanptr.p->scanState);
- return;
- }//if
-
-
- if (scanptr.p->scanState == ScanRecord::CLOSING_SCAN) {
- jam();
- /*********************************************************************
- * WE HAVE STARTED A CLOSE OF THIS SCAN OPERATION. NOW WE CAN REPORT
- * THIS TO THE APPLICATION. BEFORE WE REPORT IT TO THE APPLICATION WE
- * MUST COMPLETE THE CLOSE FIRST.
- *********************************************************************/
- if (scanptr.p->scanCompletedStatus == ZTRUE) {
- jam();
- /*********************************************************************
- * THE SCAN IS ALREADY COMPLETED. WE ARE NOW READY TO COMPLETE THE SCAN
- * BY RELEASING ALL RESOURCES AND SENDING THE CONFIRMATION TO THE
- * APPLICATION.
- *********************************************************************/
- scanReleaseResourcesLab(signal);
- return;
- } else {
- jam();
- /*********************************************************************
- * THE CLOSE IS ONGOING BUT NOT YET COMPLETED. WE WILL SET THE STATE
- * TO INDICATE THAT THE APPLICATION IS WAITING FOR THE RESPONSE.
- *********************************************************************/
- scanptr.p->apiIsClosed = true;
- return;
- }//if
- }//if
+ const Uint32 len = signal->getLength() - 4;
if (stopScan == ZTRUE) {
jam();
/*********************************************************************
* APPLICATION IS CLOSING THE SCAN.
**********************************************************************/
- scanptr.p->apiIsClosed = true;
- scanCompletedLab(signal);
+ ndbrequire(len == 0);
+ close_scan_req(signal, scanptr, true);
return;
}//if
- /*********************************************************************
- * THOSE SCAN PROCESSES THAT WAS SENT IN PREVIOUS MESSAGE ARE
- * ACKNOWLEDGED BY THIS REQUEST FOR MORE SCANNED OPERATIONS. WE CAN
- * THUS RESTART THOSE SCAN PROCESSES.
- *********************************************************************/
- for (Uint32 i = 0; i < 16; i++) {
+ if (scanptr.p->scanState == ScanRecord::CLOSING_SCAN){
jam();
- scanFragptr.i = scanptr.p->scanFragrec[i];
- if (scanFragptr.i != RNIL) {
- jam();
- ptrCheckGuard(scanFragptr, cscanFragrecFileSize, scanFragmentRecord);
- if (scanFragptr.p->scanFragState == ScanFragRec::DELIVERED) {
- jam();
- scanFragptr.p->scanFragState = ScanFragRec::RETURNING_FROM_DELIVERY;
- signal->theData[0] = TcContinueB::ZRETURN_FROM_QUEUED_DELIVERY;
- signal->theData[1] = scanptr.i;
- signal->theData[2] = scanFragptr.i;
- sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
- }
- }//if
- }//for
-
- switch (scanptr.p->scanState) {
- case ScanRecord::QUEUED_DELIVERED:
- /*********************************************************************
- * A NUMBER OF SCAN PROCESSES ARE READY TO DELIVER. DELIVER AND SET
- * STATE TO DELIVERED. ALSO CONTINUE PROCESS QUEUED SCAN PROCESSES.
- *********************************************************************/
- jam();
- sendScanTabConf(signal);
- scanptr.p->scanState = ScanRecord::DELIVERED;
- /*********************************************************************
- * UPDATE STATUS OF THE SCAN PROCESSES THAT WAS NOW SENT TO THE
- * APPLICATION TO DELIVERED. PREVIOUSLY THEY WERE QUEUED FOR DELIVERY.
- *********************************************************************/
- for (Uint32 i = 0; i < 16; i++) {
- jam();
- scanFragptr.i = scanptr.p->scanFragrec[i];
- if (scanFragptr.i != RNIL) {
- ptrCheckGuard(scanFragptr, cscanFragrecFileSize, scanFragmentRecord);
- if (scanFragptr.p->scanFragState == ScanFragRec::QUEUED_FOR_DELIVERY) {
- jam();
- scanFragptr.p->scanFragState = ScanFragRec::DELIVERED;
- }//if
- }//if
- }//for
- return;
- case ScanRecord::DELIVERED:
- jam();
- /*********************************************************************
- * WE HAVE NOT ANY QUEUED DELIVERIES. SET STATE TO INDICATE IT IS OK
- * TO SEND SCAN_TABCONF AS SOON AS ANY FRAGMENT IS READY TO DELIVER.
- *********************************************************************/
- scanptr.p->scanState = ScanRecord::SCAN_NEXT_ORDERED;
- return;
- case ScanRecord::SCAN_NEXT_ORDERED:
- jam();
- /* empty */
+ /**
+ * The scan is closing (typically due to error)
+ * but the API hasn't understood it yet
+ *
+ * Wait for API close request
+ */
return;
- default:
+ }
+
+ // Copy op ptrs so I dont overwrite them when sending...
+ memcpy(signal->getDataPtrSend()+25, signal->getDataPtr()+4, 4 * len);
+
+ ScanFragNextReq * nextReq = (ScanFragNextReq*)&signal->theData[0];
+ nextReq->closeFlag = ZFALSE;
+ nextReq->transId1 = apiConnectptr.p->transid[0];
+ nextReq->transId2 = apiConnectptr.p->transid[1];
+
+ ScanFragList running(c_scan_frag_pool, scanP->m_running_scan_frags);
+ ScanFragList delivered(c_scan_frag_pool, scanP->m_delivered_scan_frags);
+ for(Uint32 i = 0 ; i<len; i++){
jam();
- systemErrorLab(signal);
- return;
- }//switch
+ scanFragptr.i = signal->theData[i+25];
+ c_scan_frag_pool.getPtr(scanFragptr);
+ ndbrequire(scanFragptr.p->scanFragState == ScanFragRec::DELIVERED);
+
+ scanFragptr.p->scanFragState = ScanFragRec::LQH_ACTIVE;
+ scanFragptr.p->startFragTimer(ctcTimer);
+
+ scanFragptr.p->m_ops = 0;
+ nextReq->senderData = scanFragptr.i;
+ sendSignal(scanFragptr.p->lqhBlockref, GSN_SCAN_NEXTREQ, signal,
+ ScanFragNextReq::SignalLength, JBB);
+ delivered.remove(scanFragptr);
+ running.add(scanFragptr);
+ }//for
+
}//Dbtc::execSCAN_NEXTREQ()
-void Dbtc::scanCompletedLab(Signal* signal) {
- scanptr.p->scanReceivedOperations = 0;
- scanptr.p->scanState = ScanRecord::CLOSING_SCAN;
+void
+Dbtc::close_scan_req(Signal* signal, ScanRecordPtr scanPtr, bool req_received){
- // Iterate over all fragment scans and check if
- // they need to be closed in LQH
- for (Uint32 i = 0; i < 16; i++) {
- if (scanptr.p->scanFragrec[i] == RNIL) {
- jam();
- continue;
- }
- scanFragptr.i = scanptr.p->scanFragrec[i];
- ptrCheckGuard(scanFragptr, cscanFragrecFileSize, scanFragmentRecord);
+ ScanRecord* scanP = scanPtr.p;
+ ndbrequire(scanPtr.p->scanState != ScanRecord::IDLE);
+ scanPtr.p->scanState = ScanRecord::CLOSING_SCAN;
+ scanPtr.p->m_close_scan_req = req_received;
+
+ /**
+ * Queue : Action
+ * ============= : =================
+ * completed : -
+ * running : close -> LQH
+ * delivered w/ : close -> LQH
+ * delivered wo/ : move to completed
+ * queued w/ : close -> LQH
+ * queued wo/ : move to completed
+ */
+
+ ScanFragNextReq * nextReq = (ScanFragNextReq*)&signal->theData[0];
+ nextReq->closeFlag = ZTRUE;
+ nextReq->transId1 = apiConnectptr.p->transid[0];
+ nextReq->transId2 = apiConnectptr.p->transid[1];
+
+ {
+ ScanFragRecPtr ptr;
+ ScanFragList running(c_scan_frag_pool, scanP->m_running_scan_frags);
+ ScanFragList completed(c_scan_frag_pool, scanP->m_completed_scan_frags);
+ ScanFragList delivered(c_scan_frag_pool, scanP->m_delivered_scan_frags);
+ ScanFragList queued(c_scan_frag_pool, scanP->m_queued_scan_frags);
- if (scanFragptr.p->lqhBlockref == RNIL){
- // The connection to this LQH has been closed
- jam();
- continue;
+ // Close running
+ for(running.first(ptr); !ptr.isNull(); ){
+ ScanFragRecPtr curr = ptr; // Remove while iterating...
+ running.next(ptr);
+
+ if(curr.p->scanFragState == ScanFragRec::WAIT_GET_PRIMCONF){
+ jam();
+ continue;
+ }
+ ndbrequire(curr.p->scanFragState == ScanFragRec::LQH_ACTIVE);
+
+ curr.p->startFragTimer(ctcTimer);
+ curr.p->scanFragState = ScanFragRec::LQH_ACTIVE;
+ nextReq->senderData = curr.i;
+ sendSignal(curr.p->lqhBlockref, GSN_SCAN_NEXTREQ, signal,
+ ScanFragNextReq::SignalLength, JBB);
}
-
- if (scanFragptr.p->scanFragCompletedStatus == ZCLOSED){
- // The fragment scan is already completed
+
+ // Close delivered
+ for(delivered.first(ptr); !ptr.isNull(); ){
jam();
- continue;
- }
-
- if (scanFragptr.p->scanFragState == ScanFragRec::RETURNING_FROM_DELIVERY){
- // The scan process is soon to continue executing
- // Set scanFragCompletedStatus to ZTRUE so that LQH is properly closed
- // when this scan process "returns from delivery"
- jam();
- DEBUG("scanCompletedLab: setting scanFragCompletedStatus to ZTRUE");
- scanFragptr.p->scanFragCompletedStatus = ZTRUE;
- continue;
+ ScanFragRecPtr curr = ptr; // Remove while iterating...
+ delivered.next(ptr);
+
+ ndbrequire(curr.p->scanFragState == ScanFragRec::DELIVERED);
+ delivered.remove(curr);
+
+ if(curr.p->m_ops > 0){
+ jam();
+ running.add(curr);
+ curr.p->scanFragState = ScanFragRec::LQH_ACTIVE;
+ curr.p->startFragTimer(ctcTimer);
+ nextReq->senderData = curr.i;
+ sendSignal(curr.p->lqhBlockref, GSN_SCAN_NEXTREQ, signal,
+ ScanFragNextReq::SignalLength, JBB);
+
+ } else {
+ jam();
+ completed.add(curr);
+ curr.p->scanFragState = ScanFragRec::COMPLETED;
+ curr.p->stopFragTimer();
+ }
+ }//for
+
+ /**
+ * All queued with data should be closed
+ */
+ for(queued.first(ptr); !ptr.isNull(); ){
+ jam();
+ ndbrequire(ptr.p->scanFragState == ScanFragRec::QUEUED_FOR_DELIVERY);
+ ScanFragRecPtr curr = ptr; // Remove while iterating...
+ queued.next(ptr);
+
+ queued.remove(curr);
+ scanP->m_queued_count--;
+
+ if(curr.p->m_ops > 0){
+ jam();
+ running.add(curr);
+ curr.p->scanFragState = ScanFragRec::LQH_ACTIVE;
+ curr.p->startFragTimer(ctcTimer);
+ nextReq->senderData = curr.i;
+ sendSignal(curr.p->lqhBlockref, GSN_SCAN_NEXTREQ, signal,
+ ScanFragNextReq::SignalLength, JBB);
+ } else {
+ jam();
+ completed.add(curr);
+ curr.p->scanFragState = ScanFragRec::COMPLETED;
+ curr.p->stopFragTimer();
+ }
}
-
- apiConnectptr.i = scanptr.p->scanApiRec;
- ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
+ }
+ close_scan_req_send_conf(signal, scanPtr);
+}
- ScanFragNextReq * nextReq = (ScanFragNextReq*)&signal->theData[0];
- nextReq->senderData = scanFragptr.i;
- nextReq->closeFlag = ZTRUE;
- nextReq->transId1 = apiConnectptr.p->transid[0];
- nextReq->transId2 = apiConnectptr.p->transid[1];
- sendSignal(scanFragptr.p->lqhBlockref, GSN_SCAN_NEXTREQ, signal,
- ScanFragNextReq::SignalLength, JBB);
- updateBuddyTimer(apiConnectptr);
+void
+Dbtc::close_scan_req_send_conf(Signal* signal, ScanRecordPtr scanPtr){
- updateBuddyTimer(apiConnectptr);
- scanFragptr.p->startFragTimer(ctcTimer);
- scanFragptr.p->scanFragState = ScanFragRec::LQH_ACTIVE_CLOSE;
+ jam();
- }//for
-}//Dbtc::scanCompletedLab()
+ ndbrequire(scanPtr.p->m_queued_scan_frags.isEmpty());
+ ndbrequire(scanPtr.p->m_delivered_scan_frags.isEmpty());
+ //ndbrequire(scanPtr.p->m_running_scan_frags.isEmpty());
-void Dbtc::sendScanProcConf(Signal* signal){
- signal->theData[0] = scanptr.i;
- signal->theData[1] = scanFragptr.i;
- sendSignal(cownref, GSN_SCAN_PROCCONF, signal, 2, JBB);
-}
+#if 0
+ {
+ ScanFragList comp(c_scan_frag_pool, scanPtr.p->m_completed_scan_frags);
+ ScanFragRecPtr ptr;
+ for(comp.first(ptr); !ptr.isNull(); comp.next(ptr)){
+ ndbrequire(ptr.p->scanFragTimer == 0);
+ ndbrequire(ptr.p->scanFragState == ScanFragRec::COMPLETED);
+ }
+ }
+#endif
+
+ if(!scanPtr.p->m_running_scan_frags.isEmpty()){
+ jam();
+ return;
+ }
-void Dbtc::releaseScanrec(Signal* signal) {
- scanptr.p->nextScan = cfirstfreeScanrec;
- scanptr.p->scanState = ScanRecord::IDLE;
- scanptr.p->scanTcrec = RNIL;
- cfirstfreeScanrec = scanptr.i;
-}//Dbtc::releaseScanrec()
-
-void Dbtc::releaseScanFragrec(Signal* signal) {
- scanFragptr.p->nextScanFrag = cfirstfreeScanFragrec;
- scanFragptr.p->scanFragState = ScanFragRec::IDLE;
- cfirstfreeScanFragrec = scanFragptr.i;
- scanFragptr.p->stopFragTimer();
-}//Dbtc::releaseScanFragrec()
+ const bool apiFail = (apiConnectptr.p->apiFailState == ZTRUE);
+
+ if(!scanPtr.p->m_close_scan_req){
+ jam();
+ /**
+ * The API hasn't order closing yet
+ */
+ return;
+ }
-void Dbtc::releaseScanOprec(Signal* signal) {
- scanOpptr.p->nextScanOp = cfirstfreeScanOprec;
- cfirstfreeScanOprec = scanOpptr.i;
-}//Dbtc::releaseScanOprec()
+ Uint32 ref = apiConnectptr.p->ndbapiBlockref;
+ if(!apiFail && ref){
+ jam();
+ ScanTabConf * conf = (ScanTabConf*)&signal->theData[0];
+ conf->apiConnectPtr = apiConnectptr.p->ndbapiConnect;
+ conf->requestInfo = ScanTabConf::EndOfData;
+ conf->transId1 = apiConnectptr.p->transid[0];
+ conf->transId2 = apiConnectptr.p->transid[1];
+ sendSignal(ref, GSN_SCAN_TABCONF, signal, ScanTabConf::SignalLength, JBB);
+ }
+
+ releaseScanResources(scanPtr);
+
+ if(apiFail){
+ jam();
+ /**
+ * API has failed
+ */
+ handleApiFailState(signal, apiConnectptr.i);
+ }
+}
-void Dbtc::seizeScanrec(Signal* signal) {
+Dbtc::ScanRecordPtr
+Dbtc::seizeScanrec(Signal* signal) {
+ ScanRecordPtr scanptr;
scanptr.i = cfirstfreeScanrec;
ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
cfirstfreeScanrec = scanptr.p->nextScan;
scanptr.p->nextScan = RNIL;
ndbrequire(scanptr.p->scanState == ScanRecord::IDLE);
+ return scanptr;
}//Dbtc::seizeScanrec()
-void Dbtc::seizeScanFragrec(Signal* signal) {
- scanFragptr.i = cfirstfreeScanFragrec;
- ptrCheckGuard(scanFragptr, cscanFragrecFileSize, scanFragmentRecord);
- cfirstfreeScanFragrec = scanFragptr.p->nextScanFrag;
- scanFragptr.p->nextScanFrag = RNIL;
- ndbrequire(scanFragptr.p->scanFragState == ScanFragRec::IDLE);
-}//Dbtc::seizeScanFragrec()
-
-void Dbtc::seizeScanOprec(Signal* signal) {
- scanOpptr.i = cfirstfreeScanOprec;
- ptrCheckGuard(scanOpptr, cscanOprecFileSize, scanOperationRecord);
- cfirstfreeScanOprec = scanOpptr.p->nextScanOp;
- scanOpptr.p->nextScanOp = RNIL;
-}//Dbtc::seizeScanOprec()
-
-
-void Dbtc::sendScanFragReq(Signal* signal) {
- arrGuard(scanFragptr.p->scanFragProcId, 16);
- scanOpptr.i = scanptr.p->scanOprec[scanFragptr.p->scanFragProcId];
- ptrCheckGuard(scanOpptr, cscanOprecFileSize, scanOperationRecord);
-
+void Dbtc::sendScanFragReq(Signal* signal,
+ ScanRecord* scanP,
+ ScanFragRec* scanFragP){
Uint32 requestInfo = 0;
- ScanFragReq::setConcurrency(requestInfo, scanFragptr.p->scanFragConcurrency);
- ScanFragReq::setLockMode(requestInfo, scanptr.p->scanLockMode);
- ScanFragReq::setHoldLockFlag(requestInfo, scanptr.p->scanLockHold);
- if(scanptr.p->scanLockMode == 1){ // Not read -> keyinfo
+ ScanFragReq::setConcurrency(requestInfo, scanFragP->scanFragConcurrency);
+ 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, scanptr.p->readCommitted);
- ScanFragReq::setRangeScanFlag(requestInfo, scanptr.p->rangeScan);
- ScanFragReq::setAttrLen(requestInfo, scanptr.p->scanAiLength);
+ ScanFragReq::setReadCommittedFlag(requestInfo, scanP->readCommitted);
+ ScanFragReq::setRangeScanFlag(requestInfo, scanP->rangeScan);
+ ScanFragReq::setAttrLen(requestInfo, scanP->scanAiLength);
ScanFragReq::setScanPrio(requestInfo, 1);
- apiConnectptr.i = scanptr.p->scanApiRec;
+ apiConnectptr.i = scanP->scanApiRec;
ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
ScanFragReq * const req = (ScanFragReq *)&signal->theData[0];
req->senderData = scanFragptr.i;
req->resultRef = apiConnectptr.p->ndbapiBlockref;
req->requestInfo = requestInfo;
req->savePointId = apiConnectptr.p->currSavePointId;
- req->tableId = scanptr.p->scanTableref;
- req->fragmentNo = scanFragptr.p->scanFragId;
- req->schemaVersion = scanptr.p->scanSchemaVersion;
+ req->tableId = scanP->scanTableref;
+ req->fragmentNo = scanFragP->scanFragId;
+ req->schemaVersion = scanP->scanSchemaVersion;
req->transId1 = apiConnectptr.p->transid[0];
req->transId2 = apiConnectptr.p->transid[1];
for(int i = 0; i<16; i++){
- req->clientOpPtr[i] = scanOpptr.p->apiOpptr[i];
+ req->clientOpPtr[i] = scanFragP->m_apiPtr;
}
- sendSignal(scanFragptr.p->lqhBlockref, GSN_SCAN_FRAGREQ, signal, 25, JBB);
+ sendSignal(scanFragP->lqhBlockref, GSN_SCAN_FRAGREQ, signal, 25, JBB);
updateBuddyTimer(apiConnectptr);
- scanFragptr.p->startFragTimer(ctcTimer);
- scanFragptr.p->scanFragCompletedStatus = ZFALSE;
+ scanFragP->startFragTimer(ctcTimer);
}//Dbtc::sendScanFragReq()
-void Dbtc::sendScanTabConf(Signal* signal) {
+void Dbtc::sendScanTabConf(Signal* signal, ScanRecord * scanP) {
jam();
- /*******************************************************
- * Send SCAN_TABINFO with information about all
- * received operations
- *******************************************************/
- Int32 operationsToSend = scanptr.p->scanReceivedOperations;
- Uint32 sstOpIndex = 0;
-
- while (operationsToSend > 0){
+ Uint32* ops = signal->getDataPtrSend()+4;
+ Uint32 op_count = scanP->m_queued_count;
+ if(4 + 3 * op_count > 25){
jam();
-
- ScanTabInfo * info = (ScanTabInfo*)&signal->theData[0];
- info->apiConnectPtr = apiConnectptr.p->ndbapiConnect;
-
- for (int i = 0; i < 16; i++){
- jam();
- arrGuard(sstOpIndex, 16);
- scanOpptr.i = scanptr.p->scanOprec[sstOpIndex];
- ptrCheckGuard(scanOpptr, cscanOprecFileSize, scanOperationRecord);
- info->operLenAndIdx[i] = scanOpptr.p->scanOpLength[i];
- operationsToSend--;
- scanOpptr.p->scanOpLength[i] = RNIL;
- }
- sstOpIndex++;
- sendSignal(apiConnectptr.p->ndbapiBlockref,
- GSN_SCAN_TABINFO, signal, ScanTabInfo::SignalLength, JBB);
+ ops += 21;
}
-
- /********************************************************
- * Send SCAN_TABCONF signaling that a result set have
- * been sent to the API
- *********************************************************/
- Uint32 requestInfo = 0;
- ScanTabConf::setOperations(requestInfo, scanptr.p->scanReceivedOperations);
- ScanTabConf::setScanStatus(requestInfo, scanptr.p->scanCompletedStatus);
-
+
ScanTabConf * conf = (ScanTabConf*)&signal->theData[0];
conf->apiConnectPtr = apiConnectptr.p->ndbapiConnect;
- conf->requestInfo = requestInfo;
+ conf->requestInfo = op_count;
conf->transId1 = apiConnectptr.p->transid[0];
conf->transId2 = apiConnectptr.p->transid[1];
- sendSignal(apiConnectptr.p->ndbapiBlockref,
- GSN_SCAN_TABCONF, signal, ScanTabConf::SignalLength, JBB);
-
- scanptr.p->scanReceivedOperations = 0;
- // Start the scanRec-timer again and wait for response from the API.
- setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
- updateBuddyTimer(apiConnectptr);
+ ScanFragRecPtr ptr;
+ ScanFragList queued(c_scan_frag_pool, scanP->m_queued_scan_frags);
+ ScanFragList completed(c_scan_frag_pool, scanP->m_completed_scan_frags);
+ ScanFragList delivered(c_scan_frag_pool, scanP->m_delivered_scan_frags);
+ for(queued.first(ptr); !ptr.isNull(); ){
+ ndbrequire(ptr.p->scanFragState == ScanFragRec::QUEUED_FOR_DELIVERY);
+ ScanFragRecPtr curr = ptr; // Remove while iterating...
+ queued.next(ptr);
+
+ * ops++ = curr.p->m_apiPtr;
+ * ops++ = curr.i;
+ * ops++ = (curr.p->m_totalLen << 5) + curr.p->m_ops;
+
+ queued.remove(curr);
+ if(curr.p->m_ops > 0){
+ delivered.add(curr);
+ curr.p->scanFragState = ScanFragRec::DELIVERED;
+ curr.p->stopFragTimer();
+ } else {
+ (* --ops) = ScanTabConf::EndOfData; ops++;
+ completed.add(curr);
+ curr.p->scanFragState = ScanFragRec::COMPLETED;
+ curr.p->stopFragTimer();
+ }
+ }
+
+ if(4 + 3 * op_count > 25){
+ jam();
+ LinearSectionPtr ptr[3];
+ ptr[0].p = signal->getDataPtrSend()+25;
+ ptr[0].sz = 3 * op_count;
+ sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_SCAN_TABCONF, signal,
+ ScanTabConf::SignalLength, JBB, ptr, 1);
+ } else {
+ jam();
+ sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_SCAN_TABCONF, signal,
+ ScanTabConf::SignalLength + 3 * op_count, JBB);
+ }
+ scanP->m_queued_count = 0;
}//Dbtc::sendScanTabConf()
-/*
- * Write index and length of all operations received into
- * scanOprec->scanOpLength buffer
- */
-void Dbtc::setScanReceived(Signal* signal, Uint32 noCompletedOps)
-{
- UintR tssrIndividual;
- UintR tssrOprecIndex;
- UintR tssrLengthPlusIndex;
- UintR tssrOpIndex;
-
- ndbrequire(noCompletedOps <= 16);
- tssrIndividual = scanFragptr.p->scanIndividual;
- for (Uint32 i = 0; i < noCompletedOps; i++) {
- jam();
- tssrOprecIndex = scanptr.p->scanReceivedOperations >> 4;
- arrGuard(tssrOprecIndex, 16);
- scanOpptr.i = scanptr.p->scanOprec[tssrOprecIndex];
- ptrCheckGuard(scanOpptr, cscanOprecFileSize, scanOperationRecord);
- tssrLengthPlusIndex = tssrIndividual << 24;
- tssrLengthPlusIndex += cdata[i];
- tssrOpIndex = scanptr.p->scanReceivedOperations & 15;
- scanOpptr.p->scanOpLength[tssrOpIndex] = tssrLengthPlusIndex;
- scanptr.p->scanReceivedOperations++;
- tssrIndividual++;
- }//for
-}//Dbtc::setScanReceived()
-
void Dbtc::gcpTcfinished(Signal* signal)
{
signal->theData[1] = tcheckGcpId;
@@ -9913,6 +9591,7 @@ void Dbtc::initApiConnect(Signal* signal)
ndbrequire(tiacTmp > 0);
guard4 = tiacTmp + 1;
for (cachePtr.i = 0; cachePtr.i < guard4; cachePtr.i++) {
+ refresh_watch_dog();
ptrAss(cachePtr, cacheRecord);
cachePtr.p->firstAttrbuf = RNIL;
cachePtr.p->lastAttrbuf = RNIL;
@@ -9927,6 +9606,7 @@ void Dbtc::initApiConnect(Signal* signal)
guard4 = tiacTmp - 1;
for (apiConnectptr.i = 0; apiConnectptr.i <= guard4; apiConnectptr.i++) {
+ refresh_watch_dog();
jam();
ptrAss(apiConnectptr, apiConnectRecord);
apiConnectptr.p->apiConnectstate = CS_DISCONNECTED;
@@ -9952,6 +9632,7 @@ void Dbtc::initApiConnect(Signal* signal)
guard4 = (2 * tiacTmp) - 1;
for (apiConnectptr.i = tiacTmp; apiConnectptr.i <= guard4; apiConnectptr.i++)
{
+ refresh_watch_dog();
jam();
ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
apiConnectptr.p->apiConnectstate = CS_RESTART;
@@ -9977,6 +9658,7 @@ void Dbtc::initApiConnect(Signal* signal)
guard4 = (3 * tiacTmp) - 1;
for (apiConnectptr.i = 2 * tiacTmp; apiConnectptr.i <= guard4;
apiConnectptr.i++) {
+ refresh_watch_dog();
jam();
ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
setApiConTimer(apiConnectptr.i, 0, __LINE__);
@@ -10005,6 +9687,7 @@ void Dbtc::initattrbuf(Signal* signal)
{
ndbrequire(cattrbufFilesize > 0);
for (attrbufptr.i = 0; attrbufptr.i < cattrbufFilesize; attrbufptr.i++) {
+ refresh_watch_dog();
jam();
ptrAss(attrbufptr, attrbufRecord);
attrbufptr.p->attrbuf[ZINBUF_NEXT] = attrbufptr.i + 1; /* NEXT ATTRBUF */
@@ -10019,6 +9702,7 @@ void Dbtc::initdatabuf(Signal* signal)
{
ndbrequire(cdatabufFilesize > 0);
for (databufptr.i = 0; databufptr.i < cdatabufFilesize; databufptr.i++) {
+ refresh_watch_dog();
ptrAss(databufptr, databufRecord);
databufptr.p->nextDatabuf = databufptr.i + 1;
}//for
@@ -10143,11 +9827,15 @@ void Dbtc::initialiseRecordsLab(Signal* signal, UintR Tdata0,
/* ========================================================================= */
void Dbtc::initialiseScanrec(Signal* signal)
{
+ ScanRecordPtr scanptr;
ndbrequire(cscanrecFileSize > 0);
for (scanptr.i = 0; scanptr.i < cscanrecFileSize; scanptr.i++) {
+ refresh_watch_dog();
jam();
ptrAss(scanptr, scanRecord);
+ new (scanptr.p) ScanRecord();
scanptr.p->scanState = ScanRecord::IDLE;
+ scanptr.p->scanApiRec = RNIL;
scanptr.p->nextScan = scanptr.i + 1;
}//for
scanptr.i = cscanrecFileSize - 1;
@@ -10158,34 +9846,10 @@ void Dbtc::initialiseScanrec(Signal* signal)
void Dbtc::initialiseScanFragrec(Signal* signal)
{
- ndbrequire(cscanFragrecFileSize > 0);
- for (scanFragptr.i = 0; scanFragptr.i < cscanFragrecFileSize;
- scanFragptr.i++) {
- jam();
- ptrAss(scanFragptr, scanFragmentRecord);
- scanFragptr.p->scanFragState = ScanFragRec::IDLE;
- scanFragptr.p->stopFragTimer();
- scanFragptr.p->nextScanFrag = scanFragptr.i + 1;
- }//for
- scanFragptr.i = cscanFragrecFileSize - 1;
- ptrAss(scanFragptr, scanFragmentRecord);
- scanFragptr.p->nextScanFrag = RNIL;
- cfirstfreeScanFragrec = 0;
}//Dbtc::initialiseScanFragrec()
void Dbtc::initialiseScanOprec(Signal* signal)
{
- ndbrequire(cscanOprecFileSize > 0);
- for (scanOpptr.i = 0; scanOpptr.i < cscanOprecFileSize; scanOpptr.i++) {
- jam();
- ptrAss(scanOpptr, scanOperationRecord);
- scanOpptr.p->nextScanOp = scanOpptr.i + 1;
- }//for
- scanOpptr.i = cscanOprecFileSize - 1;
- ptrAss(scanOpptr, scanOperationRecord);
- scanOpptr.p->nextScanOp = RNIL;
- cfirstfreeScanOprec = 0;
- cnoFreeScanOprec = cscanOprecFileSize;
}//Dbtc::initialiseScanOprec()
void Dbtc::initTable(Signal* signal)
@@ -10193,6 +9857,7 @@ void Dbtc::initTable(Signal* signal)
ndbrequire(ctabrecFilesize > 0);
for (tabptr.i = 0; tabptr.i < ctabrecFilesize; tabptr.i++) {
+ refresh_watch_dog();
ptrAss(tabptr, tableRecord);
tabptr.p->currentSchemaVersion = 0;
tabptr.p->storedTable = true;
@@ -10209,6 +9874,7 @@ void Dbtc::initialiseTcConnect(Signal* signal)
// Place half of tcConnectptr's in cfirstfreeTcConnectFail list
Uint32 titcTmp = ctcConnectFilesize / 2;
for (tcConnectptr.i = 0; tcConnectptr.i < titcTmp; tcConnectptr.i++) {
+ refresh_watch_dog();
jam();
ptrAss(tcConnectptr, tcConnectRecord);
tcConnectptr.p->tcConnectstate = OS_RESTART;
@@ -10224,6 +9890,7 @@ void Dbtc::initialiseTcConnect(Signal* signal)
// Place other half in cfirstfreeTcConnect list
for (tcConnectptr.i = titcTmp; tcConnectptr.i < ctcConnectFilesize;
tcConnectptr.i++) {
+ refresh_watch_dog();
jam();
ptrAss(tcConnectptr, tcConnectRecord);
tcConnectptr.p->tcConnectstate = OS_RESTART;
@@ -10310,8 +9977,8 @@ void Dbtc::releaseAbortResources(Signal* signal)
if (apiConnectptr.p->cachePtr != RNIL) {
cachePtr.i = apiConnectptr.p->cachePtr;
ptrCheckGuard(cachePtr, ccacheFilesize, cacheRecord);
- releaseAttrinfo(signal);
- releaseKeys(signal);
+ releaseAttrinfo();
+ releaseKeys();
}//if
tcConnectptr.i = apiConnectptr.p->firstTcConnect;
while (tcConnectptr.i != RNIL) {
@@ -10320,7 +9987,7 @@ void Dbtc::releaseAbortResources(Signal* signal)
// Clear any markers that were set in CS_RECEIVING state
clearCommitAckMarker(apiConnectptr.p, tcConnectptr.p);
rarTcConnectptr.i = tcConnectptr.p->nextTcConnect;
- releaseTcCon(signal);
+ releaseTcCon();
tcConnectptr.i = rarTcConnectptr.i;
}//while
apiConnectptr.p->firstTcConnect = RNIL;
@@ -10334,48 +10001,53 @@ void Dbtc::releaseAbortResources(Signal* signal)
apiConnectptr.p->apiConnectstate = CS_ABORTING;
apiConnectptr.p->abortState = AS_IDLE;
- bool ok = false;
- Uint32 blockRef = apiConnectptr.p->ndbapiBlockref;
- switch(apiConnectptr.p->returnsignal){
- case RS_TCROLLBACKCONF:
+ if(apiConnectptr.p->m_exec_flag || apiConnectptr.p->apiFailState == ZTRUE){
jam();
- ok = true;
- signal->theData[0] = apiConnectptr.p->ndbapiConnect;
- signal->theData[1] = apiConnectptr.p->transid[0];
- signal->theData[2] = apiConnectptr.p->transid[1];
- sendSignal(blockRef, GSN_TCROLLBACKCONF, signal, 3, JBB);
- break;
- case RS_TCROLLBACKREP:{
- jam();
- ok = true;
- TcRollbackRep * const tcRollbackRep =
- (TcRollbackRep *) signal->getDataPtr();
-
- tcRollbackRep->connectPtr = apiConnectptr.p->ndbapiConnect;
- tcRollbackRep->transId[0] = apiConnectptr.p->transid[0];
- tcRollbackRep->transId[1] = apiConnectptr.p->transid[1];
- tcRollbackRep->returnCode = apiConnectptr.p->returncode;
- sendSignal(blockRef, GSN_TCROLLBACKREP, signal,
- TcRollbackRep::SignalLength, JBB);
- }
- break;
- case RS_NO_RETURN:
- jam();
- ok = true;
- break;
- case RS_TCKEYCONF:
- case RS_TCKEYREF:
- case RS_TC_COMMITCONF:
- break;
- }
- if(!ok){
- jam();
- ndbout_c("returnsignal = %d", apiConnectptr.p->returnsignal);
- sendSystemError(signal);
- }//if
+ bool ok = false;
+ Uint32 blockRef = apiConnectptr.p->ndbapiBlockref;
+ ReturnSignal ret = apiConnectptr.p->returnsignal;
+ apiConnectptr.p->returnsignal = RS_NO_RETURN;
+ apiConnectptr.p->m_exec_flag = 0;
+ switch(ret){
+ case RS_TCROLLBACKCONF:
+ jam();
+ ok = true;
+ signal->theData[0] = apiConnectptr.p->ndbapiConnect;
+ signal->theData[1] = apiConnectptr.p->transid[0];
+ signal->theData[2] = apiConnectptr.p->transid[1];
+ sendSignal(blockRef, GSN_TCROLLBACKCONF, signal, 3, JBB);
+ break;
+ case RS_TCROLLBACKREP:{
+ jam();
+ ok = true;
+ TcRollbackRep * const tcRollbackRep =
+ (TcRollbackRep *) signal->getDataPtr();
+
+ tcRollbackRep->connectPtr = apiConnectptr.p->ndbapiConnect;
+ tcRollbackRep->transId[0] = apiConnectptr.p->transid[0];
+ tcRollbackRep->transId[1] = apiConnectptr.p->transid[1];
+ tcRollbackRep->returnCode = apiConnectptr.p->returncode;
+ sendSignal(blockRef, GSN_TCROLLBACKREP, signal,
+ TcRollbackRep::SignalLength, JBB);
+ }
+ break;
+ case RS_NO_RETURN:
+ jam();
+ ok = true;
+ break;
+ case RS_TCKEYCONF:
+ case RS_TC_COMMITCONF:
+ break;
+ }
+ if(!ok){
+ jam();
+ ndbout_c("returnsignal = %d", apiConnectptr.p->returnsignal);
+ sendSystemError(signal);
+ }//if
- setApiConTimer(apiConnectptr.i, 0, __LINE__);
- apiConnectptr.p->abortState = AS_IDLE;
+ }
+ setApiConTimer(apiConnectptr.i, 0,
+ 100000+c_apiConTimer_line[apiConnectptr.i]);
if (apiConnectptr.p->apiFailState == ZTRUE) {
jam();
handleApiFailState(signal, apiConnectptr.i);
@@ -10393,6 +10065,8 @@ void Dbtc::releaseApiCon(Signal* signal, UintR TapiConnectPtr)
cfirstfreeApiConnect = TlocalApiConnectptr.i;
setApiConTimer(TlocalApiConnectptr.i, 0, __LINE__);
TlocalApiConnectptr.p->apiConnectstate = CS_DISCONNECTED;
+ ndbassert(TlocalApiConnectptr.p->apiScanRec == RNIL);
+ TlocalApiConnectptr.p->ndbapiBlockref = 0;
}//Dbtc::releaseApiCon()
void Dbtc::releaseApiConnectFail(Signal* signal)
@@ -10411,7 +10085,7 @@ void Dbtc::releaseGcp(Signal* signal)
cfirstfreeGcp = gcpPtr.i;
}//Dbtc::releaseGcp()
-void Dbtc::releaseKeys(Signal* signal)
+void Dbtc::releaseKeys()
{
UintR Tmp;
databufptr.i = cachePtr.p->firstKeybuf;
@@ -10445,12 +10119,12 @@ void Dbtc::seizeApiConnect(Signal* signal)
apiConnectptr.p->nextApiConnect = RNIL;
setApiConTimer(apiConnectptr.i, 0, __LINE__);
apiConnectptr.p->apiConnectstate = CS_CONNECTED; /* STATE OF CONNECTION */
+ apiConnectptr.p->triggerPending = false;
+ apiConnectptr.p->isIndexOp = false;
} else {
jam();
terrorCode = ZNO_FREE_API_CONNECTION;
}//if
- apiConnectptr.p->triggerPending = false;
- apiConnectptr.p->isIndexOp = false;
}//Dbtc::seizeApiConnect()
void Dbtc::seizeApiConnectFail(Signal* signal)
@@ -10690,20 +10364,15 @@ Dbtc::execDUMP_STATE_ORD(Signal* signal)
ScanFragRecPtr sfp;
sfp.i = recordNo;
- ptrAss(sfp, scanFragmentRecord);
- infoEvent("Dbtc::ScanFragRec[%d]: state=%d, status=%d, "
- "fragid=%d, procid=%d, ",
+ c_scan_frag_pool.getPtr(sfp);
+ infoEvent("Dbtc::ScanFragRec[%d]: state=%d fragid=%d",
sfp.i,
sfp.p->scanFragState,
- sfp.p->scanFragCompletedStatus,
- sfp.p->scanFragId,
- sfp.p->scanFragProcId);
- infoEvent(" nodeid=%d, ind=%d, concurr=%d, timer=%d, next=%d",
- sfp.p->scanFragNodeId,
- sfp.p->scanIndividual,
+ sfp.p->scanFragId);
+ infoEvent(" nodeid=%d, concurr=%d, timer=%d",
+ refToNode(sfp.p->lqhBlockref),
sfp.p->scanFragConcurrency,
- sfp.p->scanFragTimer,
- sfp.p->nextScanFrag);
+ sfp.p->scanFragTimer);
}
// Dump all ScanRecords
@@ -10770,11 +10439,10 @@ Dbtc::execDUMP_STATE_ORD(Signal* signal)
ScanRecordPtr sp;
sp.i = recordNo;
ptrAss(sp, scanRecord);
- infoEvent("Dbtc::ScanRecord[%d]: state=%d, scanOprec=%d, "
+ infoEvent("Dbtc::ScanRecord[%d]: state=%d"
"nextfrag=%d, nofrag=%d",
sp.i,
sp.p->scanState,
- sp.p->noScanOprec,
sp.p->scanNextFragId,
sp.p->scanNoFrag);
infoEvent(" ailen=%d, para=%d, receivedop=%d, noOprePperFrag=%d",
@@ -10782,17 +10450,11 @@ Dbtc::execDUMP_STATE_ORD(Signal* signal)
sp.p->scanParallel,
sp.p->scanReceivedOperations,
sp.p->noOprecPerFrag);
- infoEvent(" schv=%d, tab=%d, sproc=%d, noTI=%d, norecTI=%d",
+ infoEvent(" schv=%d, tab=%d, sproc=%d",
sp.p->scanSchemaVersion,
sp.p->scanTableref,
- sp.p->scanStoredProcId,
- sp.p->noScanTabInfo,
- sp.p->scanTabInfoReceived);
- infoEvent(" apiclosed=%d, noProcCompl=%d, "
- "complStat=%d, lhold=%d, lmode=%d",
- sp.p->apiIsClosed,
- sp.p->scanProcessesCompleted,
- sp.p->scanCompletedStatus,
+ sp.p->scanStoredProcId);
+ infoEvent(" lhold=%d, lmode=%d",
sp.p->scanLockHold,
sp.p->scanLockMode);
infoEvent(" apiRec=%d, next=%d",
@@ -10800,13 +10462,20 @@ Dbtc::execDUMP_STATE_ORD(Signal* signal)
if (sp.p->scanState != ScanRecord::IDLE){
// Request dump of ScanFragRec
- for (Uint32 i = 0; i < 16; i++){
- if (sp.p->scanFragrec[i] != RNIL){
- dumpState->args[0] = DumpStateOrd::TcDumpOneScanFragRec;
- dumpState->args[1] = sp.p->scanFragrec[i];
- execDUMP_STATE_ORD(signal);
- }
- }
+ ScanFragRecPtr sfptr;
+#define DUMP_SFR(x){\
+ ScanFragList list(c_scan_frag_pool, x);\
+ for(list.first(sfptr); !sfptr.isNull(); list.next(sfptr)){\
+ dumpState->args[0] = DumpStateOrd::TcDumpOneScanFragRec; \
+ dumpState->args[1] = sfptr.i;\
+ execDUMP_STATE_ORD(signal);\
+ }}
+
+ DUMP_SFR(sp.p->m_running_scan_frags);
+ DUMP_SFR(sp.p->m_queued_scan_frags);
+ DUMP_SFR(sp.p->m_delivered_scan_frags);
+ DUMP_SFR(sp.p->m_completed_scan_frags);
+
// Request dump of ApiConnectRecord
dumpState->args[0] = DumpStateOrd::TcDumpOneApiConnectRec;
dumpState->args[1] = sp.p->scanApiRec;
@@ -10883,6 +10552,13 @@ Dbtc::execDUMP_STATE_ORD(Signal* signal)
set_timeout_value(signal->theData[1]);
}
}
+
+ if (dumpState->args[0] == DumpStateOrd::TcSetApplTransactionTimeout){
+ jam();
+ if(signal->getLength() > 1){
+ set_appl_timeout_value(signal->theData[1]);
+ }
+ }
}//Dbtc::execDUMP_STATE_ORD()
void Dbtc::execSET_VAR_REQ(Signal* signal)
@@ -11405,11 +11081,16 @@ void Dbtc::sendTcIndxConf(Signal* signal, UintR TcommitFlag)
UintR TcurrLen = localHostptr.p->noOfWordsTCINDXCONF;
UintR confInfo = 0;
TcIndxConf::setNoOfOperations(confInfo, (TopWords >> 1));
- TcIndxConf::setCommitFlag(confInfo, TcommitFlag);
+ TcIndxConf::setCommitFlag(confInfo, TcommitFlag == 1);
TcIndxConf::setMarkerFlag(confInfo, Tmarker);
const UintR TpacketLen = 6 + TopWords;
regApiPtr->tcindxrec = 0;
+ if(TcommitFlag || (regApiPtr->lqhkeyreqrec == regApiPtr->lqhkeyconfrec)){
+ jam();
+ regApiPtr->m_exec_flag = 0;
+ }
+
if ((TpacketLen > 25) || !is_api){
TcIndxConf * const tcIndxConf = (TcIndxConf *)signal->getDataPtrSend();
@@ -11653,6 +11334,8 @@ void Dbtc::execTCKEYCONF(Signal* signal)
}
const UintR TconnectIndex = indexOp->connectionIndex;
ApiConnectRecord * const regApiPtr = &apiConnectRecord[TconnectIndex];
+ apiConnectptr.p = regApiPtr;
+ apiConnectptr.i = TconnectIndex;
switch(indexOp->indexOpState) {
case(IOS_NOOP): {
jam();
@@ -11952,7 +11635,8 @@ void Dbtc::readIndexTable(Signal* signal,
Uint32 transId1 = indexOp->tcIndxReq->transId1;
Uint32 transId2 = indexOp->tcIndxReq->transId2;
- const Uint8 opType = TcKeyReq::getOperationType(tcKeyRequestInfo);
+ const Operation_t opType =
+ (Operation_t)TcKeyReq::getOperationType(tcKeyRequestInfo);
// Find index table
if ((indexData = c_theIndexes.getPtr(indexOp->tcIndxReq->indexId)) == NULL) {
@@ -12494,34 +12178,33 @@ void Dbtc::insertIntoIndexTable(Signal* signal,
// Calculate key length and renumber attribute id:s
AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
LocalDataBuffer<11> afterValues(pool, firedTriggerData->afterValues);
+ bool skipNull = false;
for(bool moreKeyAttrs = afterValues.first(iter); moreKeyAttrs; attrId++) {
jam();
AttributeHeader* attrHeader = (AttributeHeader *) iter.data;
+ // Filter out NULL valued attributes
+ if (attrHeader->isNULL()) {
+ skipNull = true;
+ break;
+ }
attrHeader->setAttributeId(attrId);
keyLength += attrHeader->getDataSize();
hops = attrHeader->getHeaderSize() + attrHeader->getDataSize();
moreKeyAttrs = afterValues.next(iter, hops);
}
-
- // Filter out single NULL attributes
- if (attrId == 1) {
+ if (skipNull) {
jam();
- afterValues.first(iter);
- AttributeHeader* attrHeader = (AttributeHeader *) iter.data;
- if (attrHeader->isNULL() && !afterValues.next(iter)) {
- jam();
- opRecord->triggerExecutionCount--;
- if (opRecord->triggerExecutionCount == 0) {
- /*
- We have completed current trigger execution
- Continue triggering operation
- */
- jam();
- continueTriggeringOp(signal, opRecord);
- }//if
- return;
+ opRecord->triggerExecutionCount--;
+ if (opRecord->triggerExecutionCount == 0) {
+ /*
+ We have completed current trigger execution
+ Continue triggering operation
+ */
+ jam();
+ continueTriggeringOp(signal, opRecord);
}//if
+ return;
}//if
// Calculate total length of primary key to be stored in index table
@@ -12849,36 +12532,36 @@ void Dbtc::deleteFromIndexTable(Signal* signal,
// Calculate key length and renumber attribute id:s
AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
LocalDataBuffer<11> beforeValues(pool, firedTriggerData->beforeValues);
+ bool skipNull = false;
for(bool moreKeyAttrs = beforeValues.first(iter);
(moreKeyAttrs);
attrId++) {
jam();
AttributeHeader* attrHeader = (AttributeHeader *) iter.data;
+ // Filter out NULL valued attributes
+ if (attrHeader->isNULL()) {
+ skipNull = true;
+ break;
+ }
attrHeader->setAttributeId(attrId);
keyLength += attrHeader->getDataSize();
hops = attrHeader->getHeaderSize() + attrHeader->getDataSize();
moreKeyAttrs = beforeValues.next(iter, hops);
}
- // Filter out single NULL attributes
- if (attrId == 1) {
+ if (skipNull) {
jam();
- beforeValues.first(iter);
- AttributeHeader* attrHeader = (AttributeHeader *) iter.data;
- if (attrHeader->isNULL() && !beforeValues.next(iter)) {
- jam();
- opRecord->triggerExecutionCount--;
- if (opRecord->triggerExecutionCount == 0) {
- /*
+ opRecord->triggerExecutionCount--;
+ if (opRecord->triggerExecutionCount == 0) {
+ /*
We have completed current trigger execution
Continue triggering operation
- */
- jam();
- continueTriggeringOp(signal, opRecord);
- }//if
- return;
+ */
+ jam();
+ continueTriggeringOp(signal, opRecord);
}//if
+ return;
}//if
TcKeyReq::setKeyLength(tcKeyRequestInfo, keyLength);
diff --git a/ndb/src/kernel/blocks/dbtup/Dbtup.hpp b/ndb/src/kernel/blocks/dbtup/Dbtup.hpp
index 4781230a311..b792edf9333 100644
--- a/ndb/src/kernel/blocks/dbtup/Dbtup.hpp
+++ b/ndb/src/kernel/blocks/dbtup/Dbtup.hpp
@@ -950,9 +950,6 @@ typedef Ptr<TableDescriptor> TableDescriptorPtr;
struct HostBuffer {
bool inPackedList;
- Uint32 packetLenRC;
- Uint32 noOfPacketsRC;
- Uint32 packetBufferRC[29];
Uint32 packetLenTA;
Uint32 noOfPacketsTA;
Uint32 packetBufferTA[30];
@@ -1017,9 +1014,15 @@ public:
void tuxReadAttrs(Uint32 fragPtrI, Uint32 pageId, Uint32 pageOffset, Uint32 tupVersion, Uint32 numAttrs, const Uint32* attrIds, const Uint32** attrData);
/*
- * TUX reads primary key for md5 summing and when returning keyinfo.
+ * TUX reads primary key without headers into an array of words. Used
+ * for md5 summing and when returning keyinfo.
*/
- void tuxReadKeys(); // under construction
+ void tuxReadKeys(Uint32 fragPtrI, Uint32 pageId, Uint32 pageOffset, Uint32* pkSize, Uint32* pkData);
+
+ /*
+ * TUX checks if tuple is visible to scan.
+ */
+ bool tuxQueryTh(Uint32 fragPtrI, Uint32 tupAddr, Uint32 tupVersion, Uint32 transId1, Uint32 transId2, Uint32 savePointId);
private:
BLOCK_DEFINES(Dbtup);
@@ -1065,9 +1068,6 @@ private:
void execTUP_WRITELOG_REQ(Signal* signal);
// Ordered index related
- void execTUP_READ_ATTRS(Signal* signal);
- void execTUP_QUERY_TH(Signal* signal);
- void execTUP_STORE_TH(Signal* signal);
void execBUILDINDXREQ(Signal* signal);
void buildIndex(Signal* signal, Uint32 buildPtrI);
void buildIndexReply(Signal* signal, const BuildIndexRec* buildRec);
@@ -1662,11 +1662,7 @@ private:
//------------------------------------------------------------------
//------------------------------------------------------------------
- void bufferREADCONF(Signal* signal, BlockReference aRef, Uint32* buffer, Uint32 Tlen);
-
-//------------------------------------------------------------------
-//------------------------------------------------------------------
- void bufferTRANSID_AI(Signal* signal, BlockReference aRef, Uint32* buffer, Uint32 Tlen);
+ void bufferTRANSID_AI(Signal* signal, BlockReference aRef, Uint32 Tlen);
//------------------------------------------------------------------
// Trigger handling routines
@@ -2326,10 +2322,15 @@ private:
// Counters for num UNDO log records executed
Uint32 cSrUndoRecords[9];
+ STATIC_CONST(MAX_PARALLELL_TUP_SRREQ = 2);
+ Uint32 c_sr_free_page_0;
+
Uint32 c_errorInsert4000TableId;
void initGlobalTemporaryVars();
void reportMemoryUsage(Signal* signal, int incDec);
+
+
#ifdef VM_TRACE
struct Th {
Uint32 data[1];
diff --git a/ndb/src/kernel/blocks/dbtup/DbtupBuffer.cpp b/ndb/src/kernel/blocks/dbtup/DbtupBuffer.cpp
index 90c6dbc6802..ea46ee94fdc 100644
--- a/ndb/src/kernel/blocks/dbtup/DbtupBuffer.cpp
+++ b/ndb/src/kernel/blocks/dbtup/DbtupBuffer.cpp
@@ -35,7 +35,6 @@ void Dbtup::execSEND_PACKED(Signal* signal)
hostId = cpackedList[i];
ndbrequire((hostId - 1) < (MAX_NODES - 1)); // Also check not zero
Uint32 TpacketTA = hostBuffer[hostId].noOfPacketsTA;
- Uint32 TpacketRC = hostBuffer[hostId].noOfPacketsRC;
if (TpacketTA != 0) {
ljam();
BlockReference TBref = numberToRef(API_PACKED, hostId);
@@ -47,91 +46,20 @@ void Dbtup::execSEND_PACKED(Signal* signal)
hostBuffer[hostId].noOfPacketsTA = 0;
hostBuffer[hostId].packetLenTA = 0;
}//if
- if (TpacketRC != 0) {
- ljam();
- BlockReference TBref = numberToRef(API_PACKED, hostId);
- Uint32 TpacketLen = hostBuffer[hostId].packetLenRC;
- MEMCOPY_NO_WORDS(&signal->theData[0],
- &hostBuffer[hostId].packetBufferRC[0],
- TpacketLen);
- sendSignal(TBref, GSN_READCONF, signal, TpacketLen, JBB);
- hostBuffer[hostId].noOfPacketsRC = 0;
- hostBuffer[hostId].packetLenRC = 0;
- }//if
hostBuffer[hostId].inPackedList = false;
}//for
cpackedListIndex = 0;
}//Dbtup::execSEND_PACKED()
-void Dbtup::bufferREADCONF(Signal* signal, BlockReference aRef,
- Uint32* buffer, Uint32 Tlen)
-{
- Uint32 hostId = refToNode(aRef);
- Uint32 Theader = ((refToBlock(aRef) << 16) + (Tlen-3));
-
- ndbrequire(hostId < MAX_NODES);
- Uint32 TpacketLen = hostBuffer[hostId].packetLenRC;
- Uint32 TnoOfPackets = hostBuffer[hostId].noOfPacketsRC;
- Uint32 sig0 = signal->theData[0];
- Uint32 sig1 = signal->theData[1];
- Uint32 sig2 = signal->theData[2];
- Uint32 sig3 = signal->theData[3];
-
- BlockReference TBref = numberToRef(API_PACKED, hostId);
-
- if ((Tlen + TpacketLen + 1) <= 25) {
-// ----------------------------------------------------------------
-// There is still space in the buffer. We will copy it into the
-// buffer.
-// ----------------------------------------------------------------
- ljam();
- updatePackedList(signal, hostId);
- } else if (TnoOfPackets == 1) {
-// ----------------------------------------------------------------
-// The buffer is full and there was only one packet buffered. We
-// will send this as a normal signal.
-// ----------------------------------------------------------------
- Uint32 TnewRef = numberToRef((hostBuffer[hostId].packetBufferRC[0] >> 16),
- hostId);
- MEMCOPY_NO_WORDS(&signal->theData[0],
- &hostBuffer[hostId].packetBufferRC[1],
- TpacketLen - 1);
- sendSignal(TnewRef, GSN_READCONF, signal, (TpacketLen - 1), JBB);
- TpacketLen = 0;
- TnoOfPackets = 0;
- } else {
-// ----------------------------------------------------------------
-// The buffer is full but at least two packets. Send those in
-// packed form.
-// ----------------------------------------------------------------
- MEMCOPY_NO_WORDS(&signal->theData[0],
- &hostBuffer[hostId].packetBufferRC[0],
- TpacketLen);
- sendSignal(TBref, GSN_READCONF, signal, TpacketLen, JBB);
- TpacketLen = 0;
- TnoOfPackets = 0;
- }//if
-// ----------------------------------------------------------------
-// Copy the signal into the buffer
-// ----------------------------------------------------------------
- hostBuffer[hostId].packetBufferRC[TpacketLen + 0] = Theader;
- hostBuffer[hostId].packetBufferRC[TpacketLen + 1] = sig0;
- hostBuffer[hostId].packetBufferRC[TpacketLen + 2] = sig1;
- hostBuffer[hostId].packetBufferRC[TpacketLen + 3] = sig2;
- hostBuffer[hostId].packetBufferRC[TpacketLen + 4] = sig3;
- hostBuffer[hostId].noOfPacketsRC = TnoOfPackets + 1;
- hostBuffer[hostId].packetLenRC = Tlen + TpacketLen + 1;
- MEMCOPY_NO_WORDS(&hostBuffer[hostId].packetBufferRC[TpacketLen + 5],
- buffer,
- Tlen - 4);
-}//Dbtup::bufferREADCONF()
-
void Dbtup::bufferTRANSID_AI(Signal* signal, BlockReference aRef,
- Uint32* buffer, Uint32 Tlen)
+ Uint32 Tlen)
{
+ if(Tlen == 3)
+ return;
+
Uint32 hostId = refToNode(aRef);
Uint32 Theader = ((refToBlock(aRef) << 16)+(Tlen-3));
-
+
ndbrequire(hostId < MAX_NODES);
Uint32 TpacketLen = hostBuffer[hostId].packetLenTA;
Uint32 TnoOfPackets = hostBuffer[hostId].noOfPacketsTA;
@@ -148,7 +76,7 @@ void Dbtup::bufferTRANSID_AI(Signal* signal, BlockReference aRef,
// ----------------------------------------------------------------
ljam();
updatePackedList(signal, hostId);
- } else if (TnoOfPackets == 1) {
+ } else if (false && TnoOfPackets == 1) {
// ----------------------------------------------------------------
// The buffer is full and there was only one packet buffered. We
// will send this as a normal signal.
@@ -183,7 +111,7 @@ void Dbtup::bufferTRANSID_AI(Signal* signal, BlockReference aRef,
hostBuffer[hostId].noOfPacketsTA = TnoOfPackets + 1;
hostBuffer[hostId].packetLenTA = Tlen + TpacketLen + 1;
MEMCOPY_NO_WORDS(&hostBuffer[hostId].packetBufferTA[TpacketLen + 4],
- buffer,
+ &signal->theData[25],
Tlen - 3);
}//Dbtup::bufferTRANSID_AI()
@@ -206,124 +134,122 @@ void Dbtup::sendReadAttrinfo(Signal* signal,
const Operationrec * const regOperPtr)
{
const BlockReference recBlockref = regOperPtr->recBlockref;
- bool toOwnNode = refToNode(recBlockref) == getOwnNodeId();
- bool connectedToNode = getNodeInfo(refToNode(recBlockref)).m_connected;
- const Uint32 type = getNodeInfo(refToNode(recBlockref)).m_type;
+ const Uint32 block = refToBlock(recBlockref);
+ const Uint32 nodeId = refToNode(recBlockref);
+
+ bool connectedToNode = getNodeInfo(nodeId).m_connected;
+ const Uint32 type = getNodeInfo(nodeId).m_type;
bool is_api = (type >= NodeInfo::API && type <= NodeInfo::REP);
+ bool old_dest = (getNodeInfo(nodeId).m_version < MAKE_VERSION(3,5,0));
- if (ERROR_INSERTED(4006)){
+ if (ERROR_INSERTED(4006) && (nodeId != getOwnNodeId())){
// Use error insert to turn routing on
ljam();
connectedToNode = false;
}
- if (!toOwnNode && !connectedToNode){
- /**
- * If this node does not have a direct connection
- * to the receiving node we want to send the signals
- * routed via the node that controls this read
- */
- Uint32 routeBlockref = regOperPtr->coordinatorTC;
-
+ Uint32 sig0 = regOperPtr->tcOperationPtr;
+ Uint32 sig1 = regOperPtr->transid1;
+ Uint32 sig2 = regOperPtr->transid2;
+
+ TransIdAI * transIdAI = (TransIdAI *)signal->getDataPtrSend();
+ transIdAI->connectPtr = sig0;
+ transIdAI->transId[0] = sig1;
+ transIdAI->transId[1] = sig2;
+
+ if (connectedToNode){
/**
- * Fill in a TRANSID_AI signal, use last word to store
- * final destination and send it to route node
- * as signal TRANSID_AI_R (R as in Routed)
- */
- TransIdAI * const transIdAI = (TransIdAI *)signal->getDataPtr();
- transIdAI->connectPtr = regOperPtr->tcOperationPtr;
- transIdAI->transId[0] = regOperPtr->transid1;
- transIdAI->transId[1] = regOperPtr->transid2;
+ * Own node -> execute direct
+ */
+ if(nodeId != getOwnNodeId()){
+ ljam();
+
+ /**
+ * Send long sig
+ */
+ if(ToutBufIndex >= 22 && is_api && !old_dest) {
+ ljam();
+ LinearSectionPtr ptr[3];
+ ptr[0].p = &signal->theData[25];
+ ptr[0].sz = ToutBufIndex;
+ sendSignal(recBlockref, GSN_TRANSID_AI, signal, 3, JBB, ptr, 1);
+ return;
+ }
- Uint32 tot = ToutBufIndex;
- Uint32 sent = 0;
- Uint32 maxLen = TransIdAI::DataLength - 1;
- while (sent < tot) {
- ljam();
- Uint32 dataLen = (tot - sent > maxLen) ? maxLen : tot - sent;
- Uint32 sigLen = dataLen + TransIdAI::HeaderLength + 1;
- MEMCOPY_NO_WORDS(&transIdAI->attrData,
- &coutBuffer[sent],
- dataLen);
- // Set final destination in last word
- transIdAI->attrData[dataLen] = recBlockref;
-
- sendSignal(routeBlockref, GSN_TRANSID_AI_R,
- signal, sigLen, JBB);
- sent += dataLen;
+ /**
+ * short sig + api -> buffer
+ */
+#ifndef NDB_NO_DROPPED_SIGNAL
+ if (ToutBufIndex < 22 && is_api){
+ ljam();
+ bufferTRANSID_AI(signal, recBlockref, 3+ToutBufIndex);
+ return;
+ }//if
+#endif
+
+ /**
+ * rest -> old send sig
+ */
+ Uint32 * src = signal->theData+25;
+ if(ToutBufIndex >= 22){
+ do {
+ ljam();
+ MEMCOPY_NO_WORDS(&signal->theData[3], src, 22);
+ sendSignal(recBlockref, GSN_TRANSID_AI, signal, 25, JBB);
+ ToutBufIndex -= 22;
+ src += 22;
+ } while(ToutBufIndex >= 22);
+ }
+ if(ToutBufIndex > 0){
+ ljam();
+ MEMCOPY_NO_WORDS(&signal->theData[3], src, ToutBufIndex);
+ sendSignal(recBlockref, GSN_TRANSID_AI, signal, 3+ToutBufIndex, JBB);
+ }
+ return;
}
+ EXECUTE_DIRECT(block, GSN_TRANSID_AI, signal, 3 + ToutBufIndex);
+ ljamEntry();
return;
}
- Uint32 TbufIndex = 0;
- Uint32 sig0 = regOperPtr->tcOperationPtr;
- Uint32 sig1 = regOperPtr->transid1;
- Uint32 sig2 = regOperPtr->transid2;
- signal->theData[0] = sig0;
- signal->theData[1] = sig1;
- signal->theData[2] = sig2;
-
- while (ToutBufIndex > 21) {
- ljam();
- MEMCOPY_NO_WORDS(&signal->theData[3],
- &coutBuffer[TbufIndex],
- 22);
- TbufIndex += 22;
- ToutBufIndex -= 22;
- const BlockReference sendBref = regOperPtr->recBlockref;
- if (refToNode(sendBref) != getOwnNodeId()) {
- ljam();
- sendSignal(sendBref, GSN_TRANSID_AI, signal, 25, JBB);
- ljam();
- } else {
- ljam();
- EXECUTE_DIRECT(refToBlock(sendBref), GSN_TRANSID_AI, signal, 25);
- ljamEntry();
- }//if
- }//while
-
- Uint32 TsigNumber;
- Uint32 TsigLen;
- Uint32 TdataIndex;
- if ((regOperPtr->opSimple == ZTRUE) &&
- (regOperPtr->optype == ZREAD)) {
- /* DIRTY OPERATIONS ARE ALSO SIMPLE */
- ljam();
- Uint32 sig3 = regOperPtr->attroutbufLen;
- TdataIndex = 4;
- TsigLen = 4 + ToutBufIndex;
- TsigNumber = GSN_READCONF;
- signal->theData[3] = sig3;
- if ((TsigLen < 18) && is_api){
- bufferREADCONF(signal, regOperPtr->recBlockref,
- &coutBuffer[TbufIndex], TsigLen);
- return;
- }//if
- } else if (ToutBufIndex > 0) {
- ljam();
- TdataIndex = 3;
- TsigLen = 3 + ToutBufIndex;
- TsigNumber = GSN_TRANSID_AI;
- if ((TsigLen < 18) && is_api){
- ljam();
- bufferTRANSID_AI(signal, regOperPtr->recBlockref,
- &coutBuffer[TbufIndex], TsigLen);
- return;
- }//if
- } else {
+ /**
+ * If this node does not have a direct connection
+ * to the receiving node we want to send the signals
+ * routed via the node that controls this read
+ */
+ Uint32 routeBlockref = regOperPtr->coordinatorTC;
+
+ if(true){ // TODO is_api && !old_dest){
ljam();
+ transIdAI->attrData[0] = recBlockref;
+ LinearSectionPtr ptr[3];
+ ptr[0].p = &signal->theData[25];
+ ptr[0].sz = ToutBufIndex;
+ sendSignal(routeBlockref, GSN_TRANSID_AI_R, signal, 4, JBB, ptr, 1);
return;
- }//if
- MEMCOPY_NO_WORDS(&signal->theData[TdataIndex],
- &coutBuffer[TbufIndex],
- ToutBufIndex);
- const BlockReference sendBref = regOperPtr->recBlockref;
- if (refToNode(sendBref) != getOwnNodeId()) {
- ljam();
- sendSignal(sendBref, TsigNumber, signal, TsigLen, JBB);
- } else {
- EXECUTE_DIRECT(refToBlock(sendBref), GSN_TRANSID_AI, signal, TsigLen);
- ljamEntry();
- }//if
+ }
+
+ /**
+ * Fill in a TRANSID_AI signal, use last word to store
+ * final destination and send it to route node
+ * as signal TRANSID_AI_R (R as in Routed)
+ */
+ Uint32 tot = ToutBufIndex;
+ Uint32 sent = 0;
+ Uint32 maxLen = TransIdAI::DataLength - 1;
+ while (sent < tot) {
+ ljam();
+ Uint32 dataLen = (tot - sent > maxLen) ? maxLen : tot - sent;
+ Uint32 sigLen = dataLen + TransIdAI::HeaderLength + 1;
+ MEMCOPY_NO_WORDS(&transIdAI->attrData,
+ &signal->theData[25+sent],
+ dataLen);
+ // Set final destination in last word
+ transIdAI->attrData[dataLen] = recBlockref;
+
+ sendSignal(routeBlockref, GSN_TRANSID_AI_R,
+ signal, sigLen, JBB);
+ sent += dataLen;
+ }
}//Dbtup::sendReadAttrinfo()
diff --git a/ndb/src/kernel/blocks/dbtup/DbtupDebug.cpp b/ndb/src/kernel/blocks/dbtup/DbtupDebug.cpp
index c38fde23404..768a61655b5 100644
--- a/ndb/src/kernel/blocks/dbtup/DbtupDebug.cpp
+++ b/ndb/src/kernel/blocks/dbtup/DbtupDebug.cpp
@@ -201,6 +201,10 @@ Dbtup::execDUMP_STATE_ORD(Signal* signal)
ndbrequire(chunk.pageCount <= alloc);
if(chunk.pageCount != 0){
chunks.push_back(chunk);
+ if(chunk.pageCount != alloc) {
+ ndbout_c(" Tried to allocate %d - only allocated %d - free: %d",
+ alloc, chunk.pageCount, free);
+ }
} else {
ndbout_c(" Failed to alloc %d pages with %d pages free",
alloc, free);
@@ -212,6 +216,9 @@ Dbtup::execDUMP_STATE_ORD(Signal* signal)
ptrCheckGuard(pagePtr, cnoOfPage, page);
pagePtr.p->pageWord[ZPAGE_STATE_POS] = ~ZFREE_COMMON;
}
+
+ if(alloc == 1 && free > 0)
+ ndbrequire(chunk.pageCount == alloc);
}
break;
}
@@ -238,11 +245,12 @@ void Dbtup::execMEMCHECKREQ(Signal* signal)
ljamEntry();
BlockReference blockref = signal->theData[0];
- for (Uint32 i = 0; i < 25; i++) {
+ Uint32 i;
+ for (i = 0; i < 25; i++) {
ljam();
data[i] = 0;
}//for
- for (Uint32 i = 0; i < 16; i++) {
+ for (i = 0; i < 16; i++) {
regPagePtr.i = cfreepageList[i];
ljam();
while (regPagePtr.i != RNIL) {
diff --git a/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp b/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp
index 07bad00acf1..0dc196d5f56 100644
--- a/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp
+++ b/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp
@@ -873,6 +873,7 @@ int Dbtup::handleReadReq(Signal* signal,
Page* pagePtr)
{
Uint32 Ttupheadoffset = regOperPtr->pageOffset;
+ const BlockReference sendBref = regOperPtr->recBlockref;
if (regTabPtr->checksumIndicator &&
(calculateChecksum(pagePtr, Ttupheadoffset,
regTabPtr->tupheadsize) != 0)) {
@@ -882,14 +883,29 @@ int Dbtup::handleReadReq(Signal* signal,
return -1;
}//if
+ Uint32 * dst = &signal->theData[25];
+ Uint32 dstLen = (sizeof(signal->theData) / 4) - 25;
+ const Uint32 node = refToNode(sendBref);
+ if(node != 0 && node != getOwnNodeId()) {
+ ;
+ } else {
+ jam();
+ /**
+ * execute direct
+ */
+ dst = &signal->theData[3];
+ dstLen = (sizeof(signal->theData) / 4) - 3;
+ }
+
if (regOperPtr->interpretedExec != 1) {
jam();
+
Uint32 TnoOfDataRead = readAttributes(pagePtr,
Ttupheadoffset,
&cinBuffer[0],
regOperPtr->attrinbufLen,
- &coutBuffer[0],
- (Uint32)ZATTR_BUFFER_SIZE);
+ dst,
+ dstLen);
if (TnoOfDataRead != (Uint32)-1) {
/* ------------------------------------------------------------------------- */
// We have read all data into coutBuffer. Now send it to the API.
@@ -1214,11 +1230,8 @@ int Dbtup::interpreterStartLab(Signal* signal,
Uint32 RattrinbufLen = regOperPtr->attrinbufLen;
const BlockReference sendBref = regOperPtr->recBlockref;
- Uint32 * dst = &coutBuffer[0];
- Uint32 dstLen = sizeof(coutBuffer) / 4;
- Uint32 * tmp = &signal->theData[3];
- Uint32 tmpLen = (sizeof(signal->theData) / 4) - 3;
- bool executeDirect = false;
+ Uint32 * dst = &signal->theData[25];
+ Uint32 dstLen = (sizeof(signal->theData) / 4) - 25;
const Uint32 node = refToNode(sendBref);
if(node != 0 && node != getOwnNodeId()) {
;
@@ -1227,12 +1240,8 @@ int Dbtup::interpreterStartLab(Signal* signal,
/**
* execute direct
*/
- executeDirect = true;
dst = &signal->theData[3];
dstLen = (sizeof(signal->theData) / 4) - 3;
-
- tmp = &coutBuffer[0];
- tmpLen = sizeof(coutBuffer) / 4;
}
RtotalLen = RinitReadLen;
@@ -1292,8 +1301,8 @@ int Dbtup::interpreterStartLab(Signal* signal,
RexecRegionLen,
&cinBuffer[RsubPC],
RsubLen,
- tmp,
- tmpLen);
+ &coutBuffer[0],
+ sizeof(coutBuffer) / 4);
if (TnoDataRW != (Uint32)-1) {
RinstructionCounter += RexecRegionLen;
RlogSize = TnoDataRW;
@@ -1350,20 +1359,7 @@ int Dbtup::interpreterStartLab(Signal* signal,
}//if
regOperPtr->logSize = RlogSize;
regOperPtr->attroutbufLen = RattroutCounter;
- if(!executeDirect) {
- jam();
- sendReadAttrinfo(signal, RattroutCounter, regOperPtr);
- } else {
- jam();
- Uint32 sig0 = regOperPtr->tcOperationPtr;
- Uint32 sig1 = regOperPtr->transid1;
- Uint32 sig2 = regOperPtr->transid2;
- signal->theData[0] = sig0;
- signal->theData[1] = sig1;
- signal->theData[2] = sig2;
- EXECUTE_DIRECT(refToBlock(sendBref), GSN_TRANSID_AI, signal,
- 3 + RattroutCounter);
- }//if
+ sendReadAttrinfo(signal, RattroutCounter, regOperPtr);
if (RlogSize > 0) {
sendLogAttrinfo(signal, RlogSize, regOperPtr);
}//if
@@ -1445,7 +1441,10 @@ int Dbtup::interpreterNextLab(Signal* signal,
register Uint32 theRegister;
Uint32 TdataWritten = 0;
Uint32 RstackPtr = 0;
- Uint32 TregMemBuffer[32];
+ union {
+ Uint32 TregMemBuffer[32];
+ Uint64 Tdummy[16];
+ };
Uint32 TstackMemBuffer[32];
/* ---------------------------------------------------------------- */
@@ -1496,19 +1495,23 @@ int Dbtup::interpreterNextLab(Signal* signal,
// word read. Thus we set the register to be a 32 bit register.
/* ------------------------------------------------------------- */
TregMemBuffer[theRegister] = 0x50;
- TregMemBuffer[theRegister + 2] = 0;
+ * (Int64*)(TregMemBuffer+theRegister+2) = TregMemBuffer[theRegister+1];
} else if (TnoDataRW == 3) {
/* ------------------------------------------------------------- */
// Three words read means that we get the instruction plus two
// 32 words read. Thus we set the register to be a 64 bit register.
/* ------------------------------------------------------------- */
TregMemBuffer[theRegister] = 0x60;
+ TregMemBuffer[theRegister+3] = TregMemBuffer[theRegister+2];
+ TregMemBuffer[theRegister+2] = TregMemBuffer[theRegister+1];
} else if (TnoDataRW == 1) {
/* ------------------------------------------------------------- */
// One word read means that we must have read a NULL value. We set
// the register to indicate a NULL value.
/* ------------------------------------------------------------- */
TregMemBuffer[theRegister] = 0;
+ TregMemBuffer[theRegister + 2] = 0;
+ TregMemBuffer[theRegister + 3] = 0;
} else if (TnoDataRW == (Uint32)-1) {
jam();
tupkeyErrorLab(signal);
@@ -1550,8 +1553,8 @@ int Dbtup::interpreterNextLab(Signal* signal,
AttributeHeader& ah = AttributeHeader::init(&TdataForUpdate[0],
TattrId, TattrNoOfWords);
- TdataForUpdate[1] = TregMemBuffer[theRegister + 1];
- TdataForUpdate[2] = TregMemBuffer[theRegister + 2];
+ TdataForUpdate[1] = TregMemBuffer[theRegister + 2];
+ TdataForUpdate[2] = TregMemBuffer[theRegister + 3];
Tlen = TattrNoOfWords + 1;
if (Toptype == ZUPDATE) {
if (TattrNoOfWords <= 2) {
@@ -1597,24 +1600,22 @@ int Dbtup::interpreterNextLab(Signal* signal,
case Interpreter::LOAD_CONST16:
jam();
TregMemBuffer[theRegister] = 0x50; /* 32 BIT UNSIGNED CONSTANT */
- TregMemBuffer[theRegister + 1] = theInstruction >> 16;
- TregMemBuffer[theRegister + 2] = 0;
+ * (Int64*)(TregMemBuffer+theRegister+2) = theInstruction >> 16;
break;
case Interpreter::LOAD_CONST32:
jam();
TregMemBuffer[theRegister] = 0x50; /* 32 BIT UNSIGNED CONSTANT */
- TregMemBuffer[theRegister + 1] = TcurrentProgram[TprogramCounter];
- TregMemBuffer[theRegister + 2] = 0;
+ * (Int64*)(TregMemBuffer+theRegister+2) = *
+ (TcurrentProgram+TprogramCounter);
TprogramCounter++;
break;
case Interpreter::LOAD_CONST64:
jam();
TregMemBuffer[theRegister] = 0x60; /* 64 BIT UNSIGNED CONSTANT */
- TregMemBuffer[theRegister + 1] = TcurrentProgram[TprogramCounter + 0];
- TregMemBuffer[theRegister + 2] = TcurrentProgram[TprogramCounter + 1];
- TprogramCounter += 2;
+ TregMemBuffer[theRegister + 2 ] = * (TcurrentProgram + TprogramCounter++);
+ TregMemBuffer[theRegister + 3 ] = * (TcurrentProgram + TprogramCounter++);
break;
case Interpreter::ADD_REG_REG:
@@ -1624,27 +1625,16 @@ int Dbtup::interpreterNextLab(Signal* signal,
Uint32 TdestRegister = Interpreter::getReg3(theInstruction) << 2;
Uint32 TrightType = TregMemBuffer[TrightRegister];
- Uint32 Tright0 = TregMemBuffer[TrightRegister + 1];
- Uint32 Tright1 = TregMemBuffer[TrightRegister + 2];
+ Int64 Tright0 = * (Int64*)(TregMemBuffer + TrightRegister + 2);
+
Uint32 TleftType = TregMemBuffer[theRegister];
- Uint32 Tleft0 = TregMemBuffer[theRegister + 1];
- Uint32 Tleft1 = TregMemBuffer[theRegister + 2];
- Uint32 Tany64bit = (((TleftType | TrightType) & 0x60) == 0x60);
+ Int64 Tleft0 = * (Int64*)(TregMemBuffer + theRegister + 2);
if ((TleftType | TrightType) != 0) {
- Uint32 Tdest0 = Tleft0 + Tright0;
- Uint32 Tdest1 = 0;
- TregMemBuffer[TdestRegister + 1] = Tdest0;
- TregMemBuffer[TdestRegister] = 0x50;
- if (Tany64bit) {
- TregMemBuffer[TdestRegister] = 0x60;
- Tdest1 = Tleft1 + Tright1;
- if (Tdest0 < Tleft0) {
- Tdest1++;
- }
- }//if
- TregMemBuffer[TdestRegister + 2] = Tdest1;
+ Uint64 Tdest0 = Tleft0 + Tright0;
+ * (Int64*)(TregMemBuffer+TdestRegister+2) = Tdest0;
+ TregMemBuffer[TdestRegister] = 0x60;
} else {
return TUPKEY_abort(signal, 20);
}
@@ -1658,30 +1648,18 @@ int Dbtup::interpreterNextLab(Signal* signal,
Uint32 TdestRegister = Interpreter::getReg3(theInstruction) << 2;
Uint32 TrightType = TregMemBuffer[TrightRegister];
- Uint32 Tright0 = TregMemBuffer[TrightRegister + 1];
- Uint32 Tright1 = TregMemBuffer[TrightRegister + 2];
-
+ Int64 Tright0 = * (Int64*)(TregMemBuffer + TrightRegister + 2);
+
Uint32 TleftType = TregMemBuffer[theRegister];
- Uint32 Tleft0 = TregMemBuffer[theRegister + 1];
- Uint32 Tleft1 = TregMemBuffer[theRegister + 2];
- Uint32 Tany64bit = (((TleftType | TrightType) & 0x60) == 0x60);
+ Int64 Tleft0 = * (Int64*)(TregMemBuffer + theRegister + 2);
if ((TleftType | TrightType) != 0) {
- Uint32 Tdest0 = Tleft0 - Tright0;
- Uint32 Tdest1 = 0;
- TregMemBuffer[TdestRegister + 1] = Tdest0;
- TregMemBuffer[TdestRegister] = 0x50;
- if (Tany64bit) {
- TregMemBuffer[TdestRegister] = 0x60;
- Tdest1 = Tleft1 - Tright1;
- if (Tdest0 > Tleft0) {
- Tdest1--;
- }//if
- }//if
- TregMemBuffer[TdestRegister + 2] = Tdest1;
+ Int64 Tdest0 = Tleft0 - Tright0;
+ * (Int64*)(TregMemBuffer+TdestRegister+2) = Tdest0;
+ TregMemBuffer[TdestRegister] = 0x60;
} else {
- return TUPKEY_abort(signal, 21);
- }//if
+ return TUPKEY_abort(signal, 20);
+ }
break;
}
@@ -1715,12 +1693,12 @@ int Dbtup::interpreterNextLab(Signal* signal,
Uint32 TrightRegister = Interpreter::getReg2(theInstruction) << 2;
Uint32 TleftType = TregMemBuffer[theRegister];
- Uint32 Tleft0 = TregMemBuffer[theRegister + 1];
- Uint32 Tleft1 = TregMemBuffer[theRegister + 2];
+ Uint32 Tleft0 = TregMemBuffer[theRegister + 2];
+ Uint32 Tleft1 = TregMemBuffer[theRegister + 3];
Uint32 TrightType = TregMemBuffer[TrightRegister];
- Uint32 Tright0 = TregMemBuffer[TrightRegister + 1];
- Uint32 Tright1 = TregMemBuffer[TrightRegister + 2];
+ Uint32 Tright0 = TregMemBuffer[TrightRegister + 2];
+ Uint32 Tright1 = TregMemBuffer[TrightRegister + 3];
if ((TrightType | TleftType) != 0) {
jam();
if ((Tleft0 == Tright0) && (Tleft1 == Tright1)) {
@@ -1737,12 +1715,12 @@ int Dbtup::interpreterNextLab(Signal* signal,
Uint32 TrightRegister = Interpreter::getReg2(theInstruction) << 2;
Uint32 TleftType = TregMemBuffer[theRegister];
- Uint32 Tleft0 = TregMemBuffer[theRegister + 1];
- Uint32 Tleft1 = TregMemBuffer[theRegister + 2];
+ Uint32 Tleft0 = TregMemBuffer[theRegister + 2];
+ Uint32 Tleft1 = TregMemBuffer[theRegister + 3];
Uint32 TrightType = TregMemBuffer[TrightRegister];
- Uint32 Tright0 = TregMemBuffer[TrightRegister + 1];
- Uint32 Tright1 = TregMemBuffer[TrightRegister + 2];
+ Uint32 Tright0 = TregMemBuffer[TrightRegister + 2];
+ Uint32 Tright1 = TregMemBuffer[TrightRegister + 3];
if ((TrightType | TleftType) != 0) {
jam();
if ((Tleft0 != Tright0) || (Tleft1 != Tright1)) {
@@ -1758,17 +1736,16 @@ int Dbtup::interpreterNextLab(Signal* signal,
{
Uint32 TrightRegister = Interpreter::getReg2(theInstruction) << 2;
+ Uint32 TrightType = TregMemBuffer[TrightRegister];
+ Int64 Tright0 = * (Int64*)(TregMemBuffer + TrightRegister + 2);
+
Uint32 TleftType = TregMemBuffer[theRegister];
- Uint32 Tleft0 = TregMemBuffer[theRegister + 1];
- Uint32 Tleft1 = TregMemBuffer[theRegister + 2];
+ Int64 Tleft0 = * (Int64*)(TregMemBuffer + theRegister + 2);
+
- Uint32 TrightType = TregMemBuffer[TrightRegister];
- Uint32 Tright0 = TregMemBuffer[TrightRegister + 1];
- Uint32 Tright1 = TregMemBuffer[TrightRegister + 2];
if ((TrightType | TleftType) != 0) {
jam();
- if ((Tleft0 < Tright0) || ((Tleft0 == Tright0) &&
- (Tleft1 < Tright1))) {
+ if (Tleft0 < Tright0) {
TprogramCounter = brancher(theInstruction, TprogramCounter);
}//if
} else {
@@ -1781,17 +1758,16 @@ int Dbtup::interpreterNextLab(Signal* signal,
{
Uint32 TrightRegister = Interpreter::getReg2(theInstruction) << 2;
+ Uint32 TrightType = TregMemBuffer[TrightRegister];
+ Int64 Tright0 = * (Int64*)(TregMemBuffer + TrightRegister + 2);
+
Uint32 TleftType = TregMemBuffer[theRegister];
- Uint32 Tleft0 = TregMemBuffer[theRegister + 1];
- Uint32 Tleft1 = TregMemBuffer[theRegister + 2];
+ Int64 Tleft0 = * (Int64*)(TregMemBuffer + theRegister + 2);
+
- Uint32 TrightType = TregMemBuffer[TrightRegister];
- Uint32 Tright0 = TregMemBuffer[TrightRegister + 1];
- Uint32 Tright1 = TregMemBuffer[TrightRegister + 2];
if ((TrightType | TleftType) != 0) {
jam();
- if ((Tleft0 < Tright0) || ((Tleft0 == Tright0) &&
- (Tleft1 <= Tright1))) {
+ if (Tleft0 <= Tright0) {
TprogramCounter = brancher(theInstruction, TprogramCounter);
}//if
} else {
@@ -1804,17 +1780,16 @@ int Dbtup::interpreterNextLab(Signal* signal,
{
Uint32 TrightRegister = Interpreter::getReg2(theInstruction) << 2;
+ Uint32 TrightType = TregMemBuffer[TrightRegister];
+ Int64 Tright0 = * (Int64*)(TregMemBuffer + TrightRegister + 2);
+
Uint32 TleftType = TregMemBuffer[theRegister];
- Uint32 Tleft0 = TregMemBuffer[theRegister + 1];
- Uint32 Tleft1 = TregMemBuffer[theRegister + 2];
+ Int64 Tleft0 = * (Int64*)(TregMemBuffer + theRegister + 2);
+
- Uint32 TrightType = TregMemBuffer[TrightRegister];
- Uint32 Tright0 = TregMemBuffer[TrightRegister + 1];
- Uint32 Tright1 = TregMemBuffer[TrightRegister + 2];
if ((TrightType | TleftType) != 0) {
jam();
- if ((Tleft0 > Tright0) || ((Tleft0 == Tright0) &&
- (Tleft1 > Tright1))) {
+ if (Tleft0 > Tright0){
TprogramCounter = brancher(theInstruction, TprogramCounter);
}//if
} else {
@@ -1827,17 +1802,16 @@ int Dbtup::interpreterNextLab(Signal* signal,
{
Uint32 TrightRegister = Interpreter::getReg2(theInstruction) << 2;
+ Uint32 TrightType = TregMemBuffer[TrightRegister];
+ Int64 Tright0 = * (Int64*)(TregMemBuffer + TrightRegister + 2);
+
Uint32 TleftType = TregMemBuffer[theRegister];
- Uint32 Tleft0 = TregMemBuffer[theRegister + 1];
- Uint32 Tleft1 = TregMemBuffer[theRegister + 2];
+ Int64 Tleft0 = * (Int64*)(TregMemBuffer + theRegister + 2);
+
- Uint32 TrightType = TregMemBuffer[TrightRegister];
- Uint32 Tright0 = TregMemBuffer[TrightRegister + 1];
- Uint32 Tright1 = TregMemBuffer[TrightRegister + 2];
if ((TrightType | TleftType) != 0) {
jam();
- if ((Tleft0 > Tright0) || ((Tleft0 == Tright0) &&
- (Tleft1 >= Tright1))) {
+ if (Tleft0 >= Tright0){
TprogramCounter = brancher(theInstruction, TprogramCounter);
}//if
} else {
diff --git a/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp b/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp
index 095ea412701..f5c3e2b4128 100644
--- a/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp
+++ b/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp
@@ -132,9 +132,6 @@ Dbtup::Dbtup(const class Configuration & conf)
addRecSignal(GSN_TUP_WRITELOG_REQ, &Dbtup::execTUP_WRITELOG_REQ);
// Ordered index related
- addRecSignal(GSN_TUP_READ_ATTRS, &Dbtup::execTUP_READ_ATTRS);
- addRecSignal(GSN_TUP_QUERY_TH, &Dbtup::execTUP_QUERY_TH);
- addRecSignal(GSN_TUP_STORE_TH, &Dbtup::execTUP_STORE_TH);
addRecSignal(GSN_BUILDINDXREQ, &Dbtup::execBUILDINDXREQ);
initData();
@@ -701,7 +698,8 @@ void Dbtup::initRecords()
page = (Page*)allocRecord("Page",
sizeof(Page),
- cnoOfPage);
+ cnoOfPage,
+ false);
pageRange = (PageRange*)allocRecord("PageRange",
sizeof(PageRange),
@@ -891,6 +889,7 @@ void Dbtup::initializeAttrbufrec()
AttrbufrecPtr attrBufPtr;
for (attrBufPtr.i = 0;
attrBufPtr.i < cnoOfAttrbufrec; attrBufPtr.i++) {
+ refresh_watch_dog();
ptrAss(attrBufPtr, attrbufrec);
attrBufPtr.p->attrbuf[ZBUF_NEXT] = attrBufPtr.i + 1;
}//for
@@ -947,6 +946,7 @@ void Dbtup::initializeFragrecord()
{
FragrecordPtr regFragPtr;
for (regFragPtr.i = 0; regFragPtr.i < cnoOfFragrec; regFragPtr.i++) {
+ refresh_watch_dog();
ptrAss(regFragPtr, fragrecord);
regFragPtr.p->nextfreefrag = regFragPtr.i + 1;
regFragPtr.p->checkpointVersion = RNIL;
@@ -966,9 +966,7 @@ void Dbtup::initializeHostBuffer()
for (hostId = 0; hostId < MAX_NODES; hostId++) {
hostBuffer[hostId].inPackedList = false;
hostBuffer[hostId].noOfPacketsTA = 0;
- hostBuffer[hostId].noOfPacketsRC = 0;
hostBuffer[hostId].packetLenTA = 0;
- hostBuffer[hostId].packetLenRC = 0;
}//for
}//Dbtup::initializeHostBuffer()
@@ -987,6 +985,7 @@ void Dbtup::initializeOperationrec()
{
OperationrecPtr regOpPtr;
for (regOpPtr.i = 0; regOpPtr.i < cnoOfOprec; regOpPtr.i++) {
+ refresh_watch_dog();
ptrAss(regOpPtr, operationrec);
regOpPtr.p->firstAttrinbufrec = RNIL;
regOpPtr.p->lastAttrinbufrec = RNIL;
@@ -1041,6 +1040,7 @@ void Dbtup::initializeTablerec()
TablerecPtr regTabPtr;
for (regTabPtr.i = 0; regTabPtr.i < cnoOfTablerec; regTabPtr.i++) {
ljam();
+ refresh_watch_dog();
ptrAss(regTabPtr, tablerec);
initTab(regTabPtr.p);
}//for
@@ -1104,6 +1104,7 @@ void Dbtup::initializeTabDescr()
cfreeTdList[i] = RNIL;
}//for
for (regTabDesPtr.i = 0; regTabDesPtr.i < cnoOfTabDescrRec; regTabDesPtr.i++) {
+ refresh_watch_dog();
ptrAss(regTabDesPtr, tableDescriptor);
regTabDesPtr.p->tabDescr = RNIL;
}//for
@@ -1116,6 +1117,7 @@ void Dbtup::initializeUndoPage()
for (undoPagep.i = 0;
undoPagep.i < cnoOfUndoPage;
undoPagep.i = undoPagep.i + ZUB_SEGMENT_SIZE) {
+ refresh_watch_dog();
ptrAss(undoPagep, undoPage);
undoPagep.p->undoPageWord[ZPAGE_NEXT_POS] = undoPagep.i +
ZUB_SEGMENT_SIZE;
diff --git a/ndb/src/kernel/blocks/dbtup/DbtupIndex.cpp b/ndb/src/kernel/blocks/dbtup/DbtupIndex.cpp
index f11de5238e2..e7a431f17de 100644
--- a/ndb/src/kernel/blocks/dbtup/DbtupIndex.cpp
+++ b/ndb/src/kernel/blocks/dbtup/DbtupIndex.cpp
@@ -22,7 +22,6 @@
#include <AttributeDescriptor.hpp>
#include "AttributeOffset.hpp"
#include <AttributeHeader.hpp>
-#include <signaldata/TupAccess.hpp>
#include <signaldata/TuxMaint.hpp>
#define ljam() { jamLine(28000 + __LINE__); }
@@ -152,10 +151,10 @@ Dbtup::tuxReadAttrs(Uint32 fragPtrI, Uint32 pageId, Uint32 pageOffset, Uint32 tu
const Uint32* tupleHeader = &pagePtr.p->pageWord[pageOffset];
for (Uint32 i = 0; i < numAttrs; i++) {
AttributeHeader ah(attrIds[i]);
- Uint32 attrId = ah.getAttributeId();
- Uint32 index = tabDescriptor + (attrId << ZAD_LOG_SIZE);
- Uint32 desc1 = tableDescriptor[index].tabDescr;
- Uint32 desc2 = tableDescriptor[index + 1].tabDescr;
+ const Uint32 attrId = ah.getAttributeId();
+ const Uint32 index = tabDescriptor + (attrId << ZAD_LOG_SIZE);
+ const Uint32 desc1 = tableDescriptor[index].tabDescr;
+ const Uint32 desc2 = tableDescriptor[index + 1].tabDescr;
if (AttributeDescriptor::getNullable(desc1)) {
Uint32 offset = AttributeOffset::getNullFlagOffset(desc2);
ndbrequire(offset < tablePtr.p->tupNullWords);
@@ -171,275 +170,78 @@ Dbtup::tuxReadAttrs(Uint32 fragPtrI, Uint32 pageId, Uint32 pageOffset, Uint32 tu
}
}
-void // under construction
-Dbtup::tuxReadKeys()
-{
-}
-
-// deprecated signal interfaces
-
void
-Dbtup::execTUP_READ_ATTRS(Signal* signal)
+Dbtup::tuxReadKeys(Uint32 fragPtrI, Uint32 pageId, Uint32 pageOffset, Uint32* pkSize, Uint32* pkData)
{
ljamEntry();
- TupReadAttrs* const sig = (TupReadAttrs*)signal->getDataPtrSend();
- TupReadAttrs reqCopy = *sig;
- TupReadAttrs* const req = &reqCopy;
- req->errorCode = 0;
- // get table
+ FragrecordPtr fragPtr;
+ fragPtr.i = fragPtrI;
+ ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
TablerecPtr tablePtr;
- tablePtr.i = req->tableId;
+ tablePtr.i = fragPtr.p->fragTableId;
ptrCheckGuard(tablePtr, cnoOfTablerec, tablerec);
- // get fragment
- FragrecordPtr fragPtr;
- if (req->fragPtrI == RNIL) {
- ljam();
- getFragmentrec(fragPtr, req->fragId, tablePtr.p);
- ndbrequire(fragPtr.i != RNIL);
- req->fragPtrI = fragPtr.i;
- } else {
- fragPtr.i = req->fragPtrI;
- ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
- ndbrequire(req->fragId == fragPtr.p->fragmentId);
- }
- // get page
PagePtr pagePtr;
- if (req->pageId == RNIL) {
- ljam();
- Uint32 fragPageId = req->tupAddr >> MAX_TUPLES_BITS;
- Uint32 pageIndex = req->tupAddr & ((1 << MAX_TUPLES_BITS ) - 1);
- ndbrequire((pageIndex & 0x1) == 0);
- // data returned for original tuple
- req->pageId = getRealpid(fragPtr.p, fragPageId);
- req->pageOffset = ZPAGE_HEADER_SIZE + (pageIndex >> 1) * tablePtr.p->tupheadsize;
- }
- pagePtr.i = req->pageId;
+ pagePtr.i = pageId;
ptrCheckGuard(pagePtr, cnoOfPage, page);
- Uint32 pageOffset = req->pageOffset;
- // search for tuple version if not original
- if (! (req->requestInfo & TupReadAttrs::ReadKeys) &&
- pagePtr.p->pageWord[pageOffset + 1] != req->tupVersion) {
- ljam();
- OperationrecPtr opPtr;
- opPtr.i = pagePtr.p->pageWord[pageOffset];
- Uint32 loopGuard = 0;
- while (true) {
- ptrCheckGuard(opPtr, cnoOfOprec, operationrec);
- if (opPtr.p->realPageIdC != RNIL) {
- pagePtr.i = opPtr.p->realPageIdC;
- pageOffset = opPtr.p->pageOffsetC;
- ptrCheckGuard(pagePtr, cnoOfPage, page);
- if (pagePtr.p->pageWord[pageOffset + 1] == req->tupVersion) {
- ljam();
- break;
- }
- }
- ljam();
- // next means before in event order
- opPtr.i = opPtr.p->nextActiveOp;
- ndbrequire(++loopGuard < (1 << ZTUP_VERSION_BITS));
+ const Uint32 tabDescriptor = tablePtr.p->tabDescriptor;
+ const Uint32 numAttrs = tablePtr.p->noOfKeyAttr;
+ const Uint32* attrIds = &tableDescriptor[tablePtr.p->readKeyArray].tabDescr;
+ const Uint32* tupleHeader = &pagePtr.p->pageWord[pageOffset];
+ Uint32 size = 0;
+ for (Uint32 i = 0; i < numAttrs; i++) {
+ AttributeHeader ah(attrIds[i]);
+ const Uint32 attrId = ah.getAttributeId();
+ const Uint32 index = tabDescriptor + (attrId << ZAD_LOG_SIZE);
+ const Uint32 desc1 = tableDescriptor[index].tabDescr;
+ const Uint32 desc2 = tableDescriptor[index + 1].tabDescr;
+ ndbrequire(! AttributeDescriptor::getNullable(desc1));
+ const Uint32 attrSize = AttributeDescriptor::getSizeInWords(desc1);
+ const Uint32* attrData = tupleHeader + AttributeOffset::getOffset(desc2);
+ for (Uint32 j = 0; j < attrSize; j++) {
+ pkData[size + j] = attrData[j];
}
+ size += attrSize;
}
- // shared buffer
- Uint32* buffer = (Uint32*)sig + TupReadAttrs::SignalLength;
- // if request is for keys then we create input section
- if (req->requestInfo & TupReadAttrs::ReadKeys) {
- ljam();
- buffer[0] = tablePtr.p->noOfKeyAttr;
- const Uint32* keyArray = &tableDescriptor[tablePtr.p->readKeyArray].tabDescr;
- MEMCOPY_NO_WORDS(&buffer[1], keyArray, tablePtr.p->noOfKeyAttr);
- }
- Uint32 inBufLen = buffer[0];
- Uint32* inBuffer = &buffer[1];
- Uint32* outBuffer = &buffer[1 + inBufLen];
- Uint32 maxRead = ZATTR_BUFFER_SIZE;
- // save globals
- TablerecPtr tabptr_old = tabptr;
- FragrecordPtr fragptr_old = fragptr;
- OperationrecPtr operPtr_old = operPtr;
- // new globals
- tabptr = tablePtr;
- fragptr = fragPtr;
- operPtr.i = RNIL; // XXX check later
- operPtr.p = NULL;
- int ret = readAttributes(pagePtr.p, pageOffset, inBuffer, inBufLen, outBuffer, maxRead);
- // restore globals
- tabptr = tabptr_old;
- fragptr = fragptr_old;
- operPtr = operPtr_old;
- // check error
- if ((Uint32)ret == (Uint32)-1) {
- ljam();
- req->errorCode = terrorCode;
- }
- // copy back
- *sig = *req;
+ *pkSize = size;
}
-void
-Dbtup::execTUP_QUERY_TH(Signal* signal)
+bool
+Dbtup::tuxQueryTh(Uint32 fragPtrI, Uint32 tupAddr, Uint32 tupVersion, Uint32 transId1, Uint32 transId2, Uint32 savePointId)
{
ljamEntry();
- Operationrec tempOp;
- TupQueryTh* const req = (TupQueryTh*)signal->getDataPtrSend();
- Uint32 tableId = req->tableId;
- Uint32 fragId = req->fragId;
- Uint32 tupAddr = req->tupAddr;
- Uint32 req_tupVersion = req->tupVersion;
- Uint32 transid1 = req->transId1;
- Uint32 transid2 = req->transId2;
- Uint32 savePointId = req->savePointId;
- Uint32 ret_result = 0;
- // get table
+ FragrecordPtr fragPtr;
+ fragPtr.i = fragPtrI;
+ ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
TablerecPtr tablePtr;
- tablePtr.i = tableId;
+ tablePtr.i = fragPtr.p->fragTableId;
ptrCheckGuard(tablePtr, cnoOfTablerec, tablerec);
- // get fragment
- FragrecordPtr fragPtr;
- getFragmentrec(fragPtr, fragId, tablePtr.p);
- ndbrequire(fragPtr.i != RNIL);
// get page
PagePtr pagePtr;
Uint32 fragPageId = tupAddr >> MAX_TUPLES_BITS;
Uint32 pageIndex = tupAddr & ((1 << MAX_TUPLES_BITS ) - 1);
-
+ // use temp op rec
+ Operationrec tempOp;
tempOp.fragPageId = fragPageId;
tempOp.pageIndex = pageIndex;
- tempOp.transid1 = transid1;
- tempOp.transid2 = transid2;
+ tempOp.transid1 = transId1;
+ tempOp.transid2 = transId2;
tempOp.savePointId = savePointId;
tempOp.optype = ZREAD;
tempOp.dirtyOp = 1;
if (getPage(pagePtr, &tempOp, fragPtr.p, tablePtr.p)) {
/*
- We use the normal getPage which will return the tuple to be used
- for this transaction and savepoint id. If its tuple version equals
- the requested then we have a visible tuple otherwise not.
+ * We use the normal getPage which will return the tuple to be used
+ * for this transaction and savepoint id. If its tuple version
+ * equals the requested then we have a visible tuple otherwise not.
*/
ljam();
Uint32 read_tupVersion = pagePtr.p->pageWord[tempOp.pageOffset + 1];
- if (read_tupVersion == req_tupVersion) {
+ if (read_tupVersion == tupVersion) {
ljam();
- ret_result = 1;
- }
- }
- req->returnCode = ret_result;
- return;
-}
-
-void
-Dbtup::execTUP_STORE_TH(Signal* signal)
-{
- ljamEntry();
- TupStoreTh* const sig = (TupStoreTh*)signal->getDataPtrSend();
- TupStoreTh reqCopy = *sig;
- TupStoreTh* const req = &reqCopy;
- req->errorCode = 0;
- ndbrequire(req->tupVersion == 0);
- // get table
- TablerecPtr tablePtr;
- tablePtr.i = req->tableId;
- ptrCheckGuard(tablePtr, cnoOfTablerec, tablerec);
- // offset to attribute 0
- Uint32 attrDescIndex = tablePtr.p->tabDescriptor + (0 << ZAD_LOG_SIZE);
- Uint32 attrDataOffset = AttributeOffset::getOffset(tableDescriptor[attrDescIndex + 1].tabDescr);
- // get fragment
- FragrecordPtr fragPtr;
- if (req->fragPtrI == RNIL) {
- ljam();
- getFragmentrec(fragPtr, req->fragId, tablePtr.p);
- ndbrequire(fragPtr.i != RNIL);
- req->fragPtrI = fragPtr.i;
- } else {
- fragPtr.i = req->fragPtrI;
- ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
- ndbrequire(req->fragId == fragPtr.p->fragmentId);
- }
- // handle each case
- switch (req->opCode) {
- case TupStoreTh::OpRead:
- ljam();
- {
- PagePtr pagePtr;
- if (req->pageId == RNIL) {
- ljam();
- Uint32 fragPageId = req->tupAddr >> MAX_TUPLES_BITS;
- Uint32 pageIndex = req->tupAddr & ((1 << MAX_TUPLES_BITS ) - 1);
- ndbrequire((pageIndex & 0x1) == 0);
- req->pageId = getRealpid(fragPtr.p, fragPageId);
- req->pageOffset = ZPAGE_HEADER_SIZE + (pageIndex >> 1) * tablePtr.p->tupheadsize;
- }
- pagePtr.i = req->pageId;
- ptrCheckGuard(pagePtr, cnoOfPage, page);
- Uint32* data = &pagePtr.p->pageWord[req->pageOffset] + attrDataOffset;
- Uint32* buffer = (Uint32*)sig + TupStoreTh::SignalLength;
- ndbrequire(req->dataOffset + req->dataSize <= tablePtr.p->tupheadsize);
- memcpy(buffer + req->dataOffset, data + req->dataOffset, req->dataSize << 2);
- }
- break;
- case TupStoreTh::OpInsert:
- ljam();
- {
- PagePtr pagePtr;
- if (! allocTh(fragPtr.p, tablePtr.p, NORMAL_PAGE, signal, req->pageOffset, pagePtr)) {
- ljam();
- req->errorCode = terrorCode;
- break;
- }
- req->pageId = pagePtr.i;
- Uint32 fragPageId = pagePtr.p->pageWord[ZPAGE_FRAG_PAGE_ID_POS];
- Uint32 pageIndex = ((req->pageOffset - ZPAGE_HEADER_SIZE) / tablePtr.p->tupheadsize) << 1;
- req->tupAddr = (fragPageId << MAX_TUPLES_BITS) | pageIndex;
- ndbrequire(req->dataOffset + req->dataSize <= tablePtr.p->tupheadsize);
- Uint32* data = &pagePtr.p->pageWord[req->pageOffset] + attrDataOffset;
- Uint32* buffer = (Uint32*)sig + TupStoreTh::SignalLength;
- memcpy(data + req->dataOffset, buffer + req->dataOffset, req->dataSize << 2);
+ return true;
}
- break;
- case TupStoreTh::OpUpdate:
- ljam();
- {
- PagePtr pagePtr;
- if (req->pageId == RNIL) {
- ljam();
- Uint32 fragPageId = req->tupAddr >> MAX_TUPLES_BITS;
- Uint32 pageIndex = req->tupAddr & ((1 << MAX_TUPLES_BITS ) - 1);
- ndbrequire((pageIndex & 0x1) == 0);
- req->pageId = getRealpid(fragPtr.p, fragPageId);
- req->pageOffset = ZPAGE_HEADER_SIZE + (pageIndex >> 1) * tablePtr.p->tupheadsize;
- }
- pagePtr.i = req->pageId;
- ptrCheckGuard(pagePtr, cnoOfPage, page);
- Uint32* data = &pagePtr.p->pageWord[req->pageOffset] + attrDataOffset;
- Uint32* buffer = (Uint32*)sig + TupStoreTh::SignalLength;
- ndbrequire(req->dataOffset + req->dataSize <= tablePtr.p->tupheadsize);
- memcpy(data + req->dataOffset, buffer + req->dataOffset, req->dataSize << 2);
- }
- break;
- case TupStoreTh::OpDelete:
- ljam();
- {
- PagePtr pagePtr;
- if (req->pageId == RNIL) {
- ljam();
- Uint32 fragPageId = req->tupAddr >> MAX_TUPLES_BITS;
- Uint32 pageIndex = req->tupAddr & ((1 << MAX_TUPLES_BITS ) - 1);
- ndbrequire((pageIndex & 0x1) == 0);
- req->pageId = getRealpid(fragPtr.p, fragPageId);
- req->pageOffset = ZPAGE_HEADER_SIZE + (pageIndex >> 1) * tablePtr.p->tupheadsize;
- }
- pagePtr.i = req->pageId;
- ptrCheckGuard(pagePtr, cnoOfPage, page);
- freeTh(fragPtr.p, tablePtr.p, signal, pagePtr.p, req->pageOffset);
- // null location
- req->tupAddr = (Uint32)-1;
- req->pageId = RNIL;
- req->pageOffset = 0;
- }
- break;
}
- // copy back
- *sig = *req;
+ return false;
}
// ordered index build
diff --git a/ndb/src/kernel/blocks/dbtup/DbtupLCP.cpp b/ndb/src/kernel/blocks/dbtup/DbtupLCP.cpp
index b74b2c00e3e..f8f2b9bdbd2 100644
--- a/ndb/src/kernel/blocks/dbtup/DbtupLCP.cpp
+++ b/ndb/src/kernel/blocks/dbtup/DbtupLCP.cpp
@@ -344,6 +344,8 @@ void Dbtup::lcpSaveDataPageLab(Signal* signal, Uint32 ciIndex)
if (ciPtr.p->lcpTabPtr == c_errorInsert4000TableId) {
// Delay writing of data pages during LCP
ndbout << "Delay writing of data pages during LCP" << endl;
+ signal->theData[0] = ZCONT_SAVE_DP;
+ signal->theData[1] = ciIndex;
sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 1000, 2);
return;
}//if
diff --git a/ndb/src/kernel/blocks/dbtup/DbtupPagMan.cpp b/ndb/src/kernel/blocks/dbtup/DbtupPagMan.cpp
index 410cafee161..9722aa437c0 100644
--- a/ndb/src/kernel/blocks/dbtup/DbtupPagMan.cpp
+++ b/ndb/src/kernel/blocks/dbtup/DbtupPagMan.cpp
@@ -123,6 +123,7 @@ void Dbtup::initializePage()
PagePtr pagePtr;
for (pagePtr.i = 0; pagePtr.i < cnoOfPage; pagePtr.i++) {
ljam();
+ refresh_watch_dog();
ptrAss(pagePtr, page);
pagePtr.p->pageWord[ZPAGE_PHYSICAL_INDEX] = pagePtr.i;
pagePtr.p->pageWord[ZPAGE_NEXT_POS] = pagePtr.i + 1;
@@ -138,20 +139,29 @@ void Dbtup::initializePage()
pagePtr.i = 0;
ptrAss(pagePtr, page);
pagePtr.p->pageWord[ZPAGE_STATE_POS] = ~ZFREE_COMMON;
+
+ for(size_t j = 0; j<MAX_PARALLELL_TUP_SRREQ; j++){
+ pagePtr.i = 1+j;
+ ptrAss(pagePtr, page);
+ pagePtr.p->pageWord[ZPAGE_STATE_POS] = ~ZFREE_COMMON;
+ }
- returnCommonArea(1, cnoOfPage - 1);
- cnoOfAllocatedPages = 1;
+ Uint32 tmp = 1 + MAX_PARALLELL_TUP_SRREQ;
+ returnCommonArea(tmp, cnoOfPage - tmp);
+ cnoOfAllocatedPages = tmp; // Is updated by returnCommonArea
+ c_sr_free_page_0 = ~0;
}//Dbtup::initializePage()
void Dbtup::allocConsPages(Uint32 noOfPagesToAllocate,
Uint32& noOfPagesAllocated,
Uint32& allocPageRef)
{
- if (noOfPagesToAllocate == 0) {
+ if (noOfPagesToAllocate == 0){
ljam();
noOfPagesAllocated = 0;
return;
}//if
+
Uint32 firstListToCheck = nextHigherTwoLog(noOfPagesToAllocate - 1);
for (Uint32 i = firstListToCheck; i < 16; i++) {
ljam();
diff --git a/ndb/src/kernel/blocks/dbtup/DbtupSystemRestart.cpp b/ndb/src/kernel/blocks/dbtup/DbtupSystemRestart.cpp
index 580d764c96f..ed835dc057a 100644
--- a/ndb/src/kernel/blocks/dbtup/DbtupSystemRestart.cpp
+++ b/ndb/src/kernel/blocks/dbtup/DbtupSystemRestart.cpp
@@ -92,12 +92,25 @@ void Dbtup::rfrReadRestartInfoLab(Signal* signal, RestartInfoRecordPtr riPtr)
seizeDiskBufferSegmentRecord(dbsiPtr);
riPtr.p->sriDataBufferSegmentP = dbsiPtr.i;
- Uint32 retPageRef;
+ Uint32 retPageRef = RNIL;
Uint32 noAllocPages = 1;
Uint32 noOfPagesAllocated;
- allocConsPages(noAllocPages, noOfPagesAllocated, retPageRef);
- ndbrequire(noOfPagesAllocated == 1);
-
+ {
+ /**
+ * Use low pages for 0-pages during SR
+ * bitmask of free pages is kept in c_sr_free_page_0
+ */
+ Uint32 tmp = c_sr_free_page_0;
+ for(Uint32 i = 1; i<(1+MAX_PARALLELL_TUP_SRREQ); i++){
+ if(tmp & (1 << i)){
+ retPageRef = i;
+ c_sr_free_page_0 = tmp & (~(1 << i));
+ break;
+ }
+ }
+ ndbrequire(retPageRef != RNIL);
+ }
+
dbsiPtr.p->pdxDataPage[0] = retPageRef;
dbsiPtr.p->pdxNumDataPages = 1;
dbsiPtr.p->pdxFilePage = 0;
@@ -150,7 +163,10 @@ Dbtup::rfrInitRestartInfoLab(Signal* signal, DiskBufferSegmentInfoPtr dbsiPtr)
/* LETS REMOVE IT AND REUSE THE SEGMENT FOR REAL DATA PAGES */
/* REMOVE ONE PAGE ONLY, PAGEP IS ALREADY SET TO THE RESTART INFO PAGE */
/************************************************************************/
- returnCommonArea(pagePtr.i, 1);
+ {
+ ndbrequire(pagePtr.i > 0 && pagePtr.i <= MAX_PARALLELL_TUP_SRREQ);
+ c_sr_free_page_0 |= (1 << pagePtr.i);
+ }
Uint32 undoFileVersion = TzeroDataPage[ZSRI_UNDO_FILE_VER];
lliPtr.i = (undoFileVersion << 2) + (regTabPtr.i & 0x3);
@@ -494,16 +510,17 @@ void Dbtup::readExecUndoLogLab(Signal* signal, DiskBufferSegmentInfoPtr dbsiPtr,
Uint32 dataPages[16];
ndbrequire(dbsiPtr.p->pdxFilePage > 0);
ndbrequire(dbsiPtr.p->pdxFilePage <= ZUB_SEGMENT_SIZE);
- for (Uint32 i = 0; i < dbsiPtr.p->pdxFilePage; i++) {
+ Uint32 i;
+ for (i = 0; i < dbsiPtr.p->pdxFilePage; i++) {
ljam();
dataPages[i] = dbsiPtr.p->pdxDataPage[i + ZUB_SEGMENT_SIZE];
}//for
- for (Uint32 i = 0; i < ZUB_SEGMENT_SIZE; i++) {
+ for (i = 0; i < ZUB_SEGMENT_SIZE; i++) {
ljam();
dataPages[i + dbsiPtr.p->pdxFilePage] = dbsiPtr.p->pdxDataPage[i];
}//for
Uint32 limitLoop = ZUB_SEGMENT_SIZE + dbsiPtr.p->pdxFilePage;
- for (Uint32 i = 0; i < limitLoop; i++) {
+ for (i = 0; i < limitLoop; i++) {
ljam();
dbsiPtr.p->pdxDataPage[i] = dataPages[i];
}//for
@@ -977,7 +994,8 @@ void Dbtup::allocRestartUndoBufferSegment(Signal* signal, DiskBufferSegmentInfoP
seizeDiskBufferSegmentRecord(dbsiPtr);
dbsiPtr.p->pdxBuffertype = UNDO_RESTART_PAGES;
dbsiPtr.p->pdxUndoBufferSet[0] = undoPagePtr.i;
- for (Uint32 i = 0; i < ZUB_SEGMENT_SIZE; i++) {
+ Uint32 i;
+ for (i = 0; i < ZUB_SEGMENT_SIZE; i++) {
dbsiPtr.p->pdxDataPage[i] = undoPagePtr.i + i;
}//for
@@ -994,7 +1012,7 @@ void Dbtup::allocRestartUndoBufferSegment(Signal* signal, DiskBufferSegmentInfoP
undoPagePtr.p->undoPageWord[ZPAGE_NEXT_POS] = RNIL;
dbsiPtr.p->pdxUndoBufferSet[1] = undoPagePtr.i;
// lliPtr.p->lliUndoPage = undoPagePtr.i;
- for (Uint32 i = ZUB_SEGMENT_SIZE; i < (2 * ZUB_SEGMENT_SIZE); i++) {
+ for (i = ZUB_SEGMENT_SIZE; i < (2 * ZUB_SEGMENT_SIZE); i++) {
dbsiPtr.p->pdxDataPage[i] = undoPagePtr.i + (i - ZUB_SEGMENT_SIZE);
}//for
return;
diff --git a/ndb/src/kernel/blocks/dbtux/Dbtux.hpp b/ndb/src/kernel/blocks/dbtux/Dbtux.hpp
index 25e85ba9f5f..1a3c7f64ac3 100644
--- a/ndb/src/kernel/blocks/dbtux/Dbtux.hpp
+++ b/ndb/src/kernel/blocks/dbtux/Dbtux.hpp
@@ -37,7 +37,6 @@
#include <signaldata/AlterIndx.hpp>
#include <signaldata/DropTab.hpp>
#include <signaldata/TuxMaint.hpp>
-#include <signaldata/TupAccess.hpp>
#include <signaldata/AccScan.hpp>
#include <signaldata/TuxBound.hpp>
#include <signaldata/NextScan.hpp>
@@ -77,10 +76,14 @@
#define jam() jamLine(60000 + __LINE__)
#define jamEntry() jamEntryLine(60000 + __LINE__)
#endif
-#ifdef DBTUX_CMP_CPP
+#ifdef DBTUX_SEARCH_CPP
#define jam() jamLine(70000 + __LINE__)
#define jamEntry() jamEntryLine(70000 + __LINE__)
#endif
+#ifdef DBTUX_CMP_CPP
+#define jam() jamLine(80000 + __LINE__)
+#define jamEntry() jamEntryLine(80000 + __LINE__)
+#endif
#ifdef DBTUX_DEBUG_CPP
#define jam() jamLine(90000 + __LINE__)
#define jamEntry() jamEntryLine(90000 + __LINE__)
@@ -112,6 +115,7 @@ public:
static const unsigned DescPageSize = 256;
private:
static const unsigned MaxTreeNodeSize = MAX_TTREE_NODE_SIZE;
+ static const unsigned MaxPrefSize = MAX_TTREE_PREF_SIZE;
static const unsigned ScanBoundSegmentSize = 7;
static const unsigned MaxAccLockOps = MAX_PARALLEL_OP_PER_SCAN;
BLOCK_DEFINES(Dbtux);
@@ -206,19 +210,19 @@ private:
unsigned m_fragBit : 1; // which duplicated table fragment
TreeEnt();
// methods
+ bool eq(const TreeEnt ent) const;
int cmp(const TreeEnt ent) const;
};
static const unsigned TreeEntSize = sizeof(TreeEnt) >> 2;
static const TreeEnt NullTreeEnt;
/*
- * Tree node has 1) fixed part 2) actual table data for min and max
- * prefix 3) max and min entries 4) rest of entries 5) one extra entry
+ * Tree node has 1) fixed part 2) a prefix of index key data for min
+ * entry 3) max and min entries 4) rest of entries 5) one extra entry
* used as work space.
*
* struct TreeNode part 1, size 6 words
* min prefix part 2, size TreeHead::m_prefSize
- * max prefix part 2, size TreeHead::m_prefSize
* max entry part 3
* min entry part 3
* rest of entries part 4
@@ -265,14 +269,14 @@ private:
friend struct TreeHead;
struct TreeHead {
Uint8 m_nodeSize; // words in tree node
- Uint8 m_prefSize; // words in min/max prefix each
+ Uint8 m_prefSize; // words in min prefix
Uint8 m_minOccup; // min entries in internal node
Uint8 m_maxOccup; // max entries in node
TupLoc m_root; // root node
TreeHead();
// methods
unsigned getSize(AccSize acc) const;
- Data getPref(TreeNode* node, unsigned i) const;
+ Data getPref(TreeNode* node) const;
TreeEnt* getEntList(TreeNode* node) const;
};
@@ -442,6 +446,7 @@ private:
Uint32 m_descPage; // descriptor page
Uint16 m_descOff; // offset within the page
Uint16 m_numAttrs;
+ bool m_storeNullKey;
union {
Uint32 nextPool;
};
@@ -465,6 +470,7 @@ private:
Uint32 m_descPage; // copy from index level
Uint16 m_descOff;
Uint16 m_numAttrs;
+ bool m_storeNullKey;
TreeHead m_tree;
TupLoc m_freeLoc; // one node pre-allocated for insert
DLList<ScanOp> m_scanList; // current scans on this fragment
@@ -514,6 +520,8 @@ private:
NodeHandle(Frag& frag);
NodeHandle(const NodeHandle& node);
NodeHandle& operator=(const NodeHandle& node);
+ // check if unassigned
+ bool isNull();
// getters
TupLoc getLink(unsigned i);
unsigned getChilds(); // cannot spell
@@ -528,56 +536,13 @@ private:
void setBalance(int b);
void setNodeScan(Uint32 scanPtrI);
// access other parts of the node
- Data getPref(unsigned i);
+ Data getPref();
TreeEnt getEnt(unsigned pos);
TreeEnt getMinMax(unsigned i);
// for ndbrequire and ndbassert
void progError(int line, int cause, const char* file);
};
- // parameters for methods
-
- /*
- * Copy attribute data.
- */
- struct CopyPar {
- unsigned m_items; // number of attributes
- bool m_headers; // copy headers flag (default true)
- unsigned m_maxwords; // limit size (default no limit)
- // output
- unsigned m_numitems; // number of attributes fully copied
- unsigned m_numwords; // number of words copied
- CopyPar();
- };
-
- /*
- * Read index key attributes.
- */
- struct ReadPar;
- friend struct ReadPar;
- struct ReadPar {
- TreeEnt m_ent; // tuple to read
- unsigned m_first; // first index attribute
- unsigned m_count; // number of consecutive index attributes
- Data m_data; // set pointer if 0 else copy result to it
- unsigned m_size; // number of words (set in read keys only)
- ReadPar();
- };
-
- /*
- * Scan bound comparison.
- */
- struct BoundPar;
- friend struct BoundPar;
- struct BoundPar {
- ConstData m_data1; // full bound data
- ConstData m_data2; // full or prefix data
- unsigned m_count1; // number of bounds
- unsigned m_len2; // words in data2 buffer
- unsigned m_dir; // 0-lower bound 1-upper bound
- BoundPar();
- };
-
// methods
/*
@@ -589,7 +554,7 @@ private:
// utils
void setKeyAttrs(const Frag& frag);
void readKeyAttrs(const Frag& frag, TreeEnt ent, unsigned start, TableData keyData);
- void copyAttrs(Data dst, ConstData src, CopyPar& copyPar);
+ void readTablePk(const Frag& frag, TreeEnt ent, unsigned& pkSize, Data pkData);
void copyAttrs(const Frag& frag, TableData data1, Data data2, unsigned maxlen2 = MaxAttrDataSize);
/*
@@ -607,8 +572,6 @@ private:
* DbtuxMaint.cpp
*/
void execTUX_MAINT_REQ(Signal* signal);
- void tupReadAttrs(Signal* signal, const Frag& frag, ReadPar& readPar);
- void tupReadKeys(Signal* signal, const Frag& frag, ReadPar& readPar);
/*
* DbtuxNode.cpp
@@ -618,7 +581,7 @@ private:
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, unsigned i);
+ void setNodePref(Signal* signal, 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);
@@ -633,7 +596,6 @@ private:
/*
* DbtuxTree.cpp
*/
- void treeSearch(Signal* signal, Frag& frag, TableData searchKey, TreeEnt searchEnt, TreePos& treePos);
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);
@@ -658,11 +620,19 @@ private:
void releaseScanOp(ScanOpPtr& scanPtr);
/*
+ * DbtuxSearch.cpp
+ */
+ void searchToAdd(Signal* signal, Frag& frag, TableData searchKey, TreeEnt searchEnt, TreePos& treePos);
+ void searchToRemove(Signal* signal, Frag& frag, TableData searchKey, TreeEnt searchEnt, TreePos& treePos);
+ void searchToScan(Signal* signal, Frag& frag, ConstData boundInfo, unsigned boundCount, TreePos& treePos);
+
+ /*
* DbtuxCmp.cpp
*/
- int cmpSearchKey(const Frag& frag, unsigned& start, TableData data1, ConstData data2, unsigned maxlen2 = MaxAttrDataSize);
- int cmpSearchKey(const Frag& frag, unsigned& start, TableData data1, TableData data2);
- int cmpScanBound(const Frag& frag, const BoundPar boundPar);
+ int cmpSearchKey(const Frag& frag, unsigned& start, TableData searchKey, ConstData entryData, unsigned maxlen = MaxAttrDataSize);
+ int cmpSearchKey(const Frag& frag, unsigned& start, TableData searchKey, TableData entryKey);
+ int cmpScanBound(const Frag& frag, unsigned dir, ConstData boundInfo, unsigned boundCount, ConstData entryData, unsigned maxlen = MaxAttrDataSize);
+ int cmpScanBound(const Frag& frag, unsigned dir, ConstData boundInfo, unsigned boundCount, TableData entryKey);
/*
* DbtuxDebug.cpp
@@ -675,6 +645,7 @@ private:
TupLoc m_parent; // expected parent address
int m_depth; // returned depth
unsigned m_occup; // returned occupancy
+ TreeEnt m_minmax[2]; // returned subtree min and max
bool m_ok; // returned status
PrintPar();
};
@@ -699,6 +670,8 @@ private:
DebugTree = 4, // log and check tree after each op
DebugScan = 8 // log scans
};
+ static const int DataFillByte = 0xa2;
+ static const int NodeFillByte = 0xa4;
#endif
// start up info
@@ -859,13 +832,18 @@ Dbtux::TreeEnt::TreeEnt() :
{
}
+inline bool
+Dbtux::TreeEnt::eq(const TreeEnt ent) const
+{
+ return
+ m_tupLoc == ent.m_tupLoc &&
+ m_tupVersion == ent.m_tupVersion &&
+ m_fragBit == ent.m_fragBit;
+}
+
inline int
Dbtux::TreeEnt::cmp(const TreeEnt ent) const
{
- if (m_fragBit < ent.m_fragBit)
- return -1;
- if (m_fragBit > ent.m_fragBit)
- return +1;
if (m_tupLoc.m_pageId < ent.m_tupLoc.m_pageId)
return -1;
if (m_tupLoc.m_pageId > ent.m_tupLoc.m_pageId)
@@ -878,6 +856,10 @@ Dbtux::TreeEnt::cmp(const TreeEnt ent) const
return -1;
if (m_tupVersion > ent.m_tupVersion)
return +1;
+ if (m_fragBit < ent.m_fragBit)
+ return -1;
+ if (m_fragBit > ent.m_fragBit)
+ return +1;
return 0;
}
@@ -920,25 +902,25 @@ Dbtux::TreeHead::getSize(AccSize acc) const
case AccHead:
return NodeHeadSize;
case AccPref:
- return NodeHeadSize + 2 * m_prefSize + 2 * TreeEntSize;
+ return NodeHeadSize + m_prefSize + 2 * TreeEntSize;
case AccFull:
return m_nodeSize;
}
- REQUIRE(false, "invalid Dbtux::AccSize");
+ abort();
return 0;
}
inline Dbtux::Data
-Dbtux::TreeHead::getPref(TreeNode* node, unsigned i) const
+Dbtux::TreeHead::getPref(TreeNode* node) const
{
- Uint32* ptr = (Uint32*)node + NodeHeadSize + i * m_prefSize;
+ Uint32* ptr = (Uint32*)node + NodeHeadSize;
return ptr;
}
inline Dbtux::TreeEnt*
Dbtux::TreeHead::getEntList(TreeNode* node) const
{
- Uint32* ptr = (Uint32*)node + NodeHeadSize + 2 * m_prefSize;
+ Uint32* ptr = (Uint32*)node + NodeHeadSize + m_prefSize;
return (TreeEnt*)ptr;
}
@@ -1013,7 +995,8 @@ Dbtux::Index::Index() :
m_numFrags(0),
m_descPage(RNIL),
m_descOff(0),
- m_numAttrs(0)
+ m_numAttrs(0),
+ m_storeNullKey(false)
{
for (unsigned i = 0; i < MaxIndexFragments; i++) {
m_fragId[i] = ZNIL;
@@ -1032,6 +1015,7 @@ Dbtux::Frag::Frag(ArrayPool<ScanOp>& scanOpPool) :
m_descPage(RNIL),
m_descOff(0),
m_numAttrs(ZNIL),
+ m_storeNullKey(false),
m_tree(),
m_freeLoc(),
m_scanList(scanOpPool),
@@ -1087,6 +1071,12 @@ Dbtux::NodeHandle::operator=(const NodeHandle& node)
return *this;
}
+inline bool
+Dbtux::NodeHandle::isNull()
+{
+ return m_node == 0;
+}
+
inline Dbtux::TupLoc
Dbtux::NodeHandle::getLink(unsigned i)
{
@@ -1161,11 +1151,11 @@ Dbtux::NodeHandle::setNodeScan(Uint32 scanPtrI)
}
inline Dbtux::Data
-Dbtux::NodeHandle::getPref(unsigned i)
+Dbtux::NodeHandle::getPref()
{
TreeHead& tree = m_frag.m_tree;
- ndbrequire(m_acc >= AccPref && i <= 1);
- return tree.getPref(m_node, i);
+ ndbrequire(m_acc >= AccPref);
+ return tree.getPref(m_node);
}
inline Dbtux::TreeEnt
@@ -1193,36 +1183,6 @@ Dbtux::NodeHandle::getMinMax(unsigned i)
// parameters for methods
-inline
-Dbtux::CopyPar::CopyPar() :
- m_items(0),
- m_headers(true),
- m_maxwords(~0), // max unsigned
- // output
- m_numitems(0),
- m_numwords(0)
-{
-}
-
-inline
-Dbtux::ReadPar::ReadPar() :
- m_first(0),
- m_count(0),
- m_data(0),
- m_size(0)
-{
-}
-
-inline
-Dbtux::BoundPar::BoundPar() :
- m_data1(0),
- m_data2(0),
- m_count1(0),
- m_len2(0),
- m_dir(255)
-{
-}
-
#ifdef VM_TRACE
inline
Dbtux::PrintPar::PrintPar() :
diff --git a/ndb/src/kernel/blocks/dbtux/DbtuxCmp.cpp b/ndb/src/kernel/blocks/dbtux/DbtuxCmp.cpp
index 7601a14a242..1b8755a1dc4 100644
--- a/ndb/src/kernel/blocks/dbtux/DbtuxCmp.cpp
+++ b/ndb/src/kernel/blocks/dbtux/DbtuxCmp.cpp
@@ -25,14 +25,14 @@
* prefix may be partial in which case CmpUnknown may be returned.
*/
int
-Dbtux::cmpSearchKey(const Frag& frag, unsigned& start, TableData data1, ConstData data2, unsigned maxlen2)
+Dbtux::cmpSearchKey(const Frag& frag, unsigned& start, TableData searchKey, ConstData entryData, unsigned maxlen)
{
const unsigned numAttrs = frag.m_numAttrs;
const DescEnt& descEnt = getDescEnt(frag.m_descPage, frag.m_descOff);
// number of words of attribute data left
- unsigned len2 = maxlen2;
+ unsigned len2 = maxlen;
// skip to right position in search key
- data1 += start;
+ searchKey += start;
int ret = 0;
while (start < numAttrs) {
if (len2 < AttributeHeaderSize) {
@@ -41,20 +41,20 @@ Dbtux::cmpSearchKey(const Frag& frag, unsigned& start, TableData data1, ConstDat
break;
}
len2 -= AttributeHeaderSize;
- if (*data1 != 0) {
- if (! data2.ah().isNULL()) {
+ if (*searchKey != 0) {
+ if (! entryData.ah().isNULL()) {
jam();
// current attribute
const DescAttr& descAttr = descEnt.m_descAttr[start];
const unsigned typeId = descAttr.m_typeId;
// full data size
const unsigned size1 = AttributeDescriptor::getSizeInWords(descAttr.m_attrDesc);
- ndbrequire(size1 != 0 && size1 == data2.ah().getDataSize());
+ ndbrequire(size1 != 0 && size1 == entryData.ah().getDataSize());
const unsigned size2 = min(size1, len2);
len2 -= size2;
// compare
- const Uint32* const p1 = *data1;
- const Uint32* const p2 = &data2[AttributeHeaderSize];
+ const Uint32* const p1 = *searchKey;
+ const Uint32* const p2 = &entryData[AttributeHeaderSize];
ret = NdbSqlUtil::cmp(typeId, p1, p2, size1, size2);
if (ret != 0) {
jam();
@@ -62,20 +62,20 @@ Dbtux::cmpSearchKey(const Frag& frag, unsigned& start, TableData data1, ConstDat
}
} else {
jam();
- // not NULL < NULL
- ret = -1;
+ // not NULL > NULL
+ ret = +1;
break;
}
} else {
- if (! data2.ah().isNULL()) {
+ if (! entryData.ah().isNULL()) {
jam();
- // NULL > not NULL
- ret = +1;
+ // NULL < not NULL
+ ret = -1;
break;
}
}
- data1 += 1;
- data2 += AttributeHeaderSize + data2.ah().getDataSize();
+ searchKey += 1;
+ entryData += AttributeHeaderSize + entryData.ah().getDataSize();
start++;
}
// XXX until data format errors are handled
@@ -89,17 +89,17 @@ Dbtux::cmpSearchKey(const Frag& frag, unsigned& start, TableData data1, ConstDat
* Start position is updated as in previous routine.
*/
int
-Dbtux::cmpSearchKey(const Frag& frag, unsigned& start, TableData data1, TableData data2)
+Dbtux::cmpSearchKey(const Frag& frag, unsigned& start, TableData searchKey, TableData entryKey)
{
const unsigned numAttrs = frag.m_numAttrs;
const DescEnt& descEnt = getDescEnt(frag.m_descPage, frag.m_descOff);
// skip to right position
- data1 += start;
- data2 += start;
+ searchKey += start;
+ entryKey += start;
int ret = 0;
while (start < numAttrs) {
- if (*data1 != 0) {
- if (*data2 != 0) {
+ if (*searchKey != 0) {
+ if (*entryKey != 0) {
jam();
// current attribute
const DescAttr& descAttr = descEnt.m_descAttr[start];
@@ -107,8 +107,8 @@ Dbtux::cmpSearchKey(const Frag& frag, unsigned& start, TableData data1, TableDat
// full data size
const unsigned size1 = AttributeDescriptor::getSizeInWords(descAttr.m_attrDesc);
// compare
- const Uint32* const p1 = *data1;
- const Uint32* const p2 = *data2;
+ const Uint32* const p1 = *searchKey;
+ const Uint32* const p2 = *entryKey;
ret = NdbSqlUtil::cmp(typeId, p1, p2, size1, size1);
if (ret != 0) {
jam();
@@ -116,20 +116,20 @@ Dbtux::cmpSearchKey(const Frag& frag, unsigned& start, TableData data1, TableDat
}
} else {
jam();
- // not NULL < NULL
- ret = -1;
+ // not NULL > NULL
+ ret = +1;
break;
}
} else {
- if (*data2 != 0) {
+ if (*entryKey != 0) {
jam();
- // NULL > not NULL
- ret = +1;
+ // NULL < not NULL
+ ret = -1;
break;
}
}
- data1 += 1;
- data2 += 1;
+ searchKey += 1;
+ entryKey += 1;
start++;
}
// XXX until data format errors are handled
@@ -137,94 +137,96 @@ Dbtux::cmpSearchKey(const Frag& frag, unsigned& start, TableData data1, TableDat
return ret;
}
-
/*
- * Scan bound vs tree entry.
+ * Scan bound vs node prefix.
*
* 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.
+ * 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.
*
- * 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.
+ * 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.
*
* 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.
+ * 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.
*/
int
-Dbtux::cmpScanBound(const Frag& frag, const BoundPar boundPar)
+Dbtux::cmpScanBound(const Frag& frag, unsigned dir, ConstData boundInfo, unsigned boundCount, ConstData entryData, unsigned maxlen)
{
- unsigned type = 4;
- int ret = 0;
- /*
- 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 initialising return value to 0 and set type to 4.
- */
const DescEnt& descEnt = getDescEnt(frag.m_descPage, frag.m_descOff);
- ConstData data1 = boundPar.m_data1;
- ConstData data2 = boundPar.m_data2;
// direction 0-lower 1-upper
- const unsigned dir = boundPar.m_dir;
ndbrequire(dir <= 1);
// number of words of data left
- unsigned len2 = boundPar.m_len2;
- for (unsigned i = 0; i < boundPar.m_count1; i++) {
+ 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.
+ */
+ unsigned type = 4;
+ while (boundCount != 0) {
if (len2 < AttributeHeaderSize) {
jam();
return NdbSqlUtil::CmpUnknown;
}
len2 -= AttributeHeaderSize;
// get and skip bound type
- type = data1[0];
- data1 += 1;
- ndbrequire(! data1.ah().isNULL());
- if (! data2.ah().isNULL()) {
- jam();
- // current attribute
- const unsigned index = data1.ah().getAttributeId();
- const DescAttr& descAttr = descEnt.m_descAttr[index];
- const unsigned typeId = descAttr.m_typeId;
- ndbrequire(data2.ah().getAttributeId() == descAttr.m_primaryAttrId);
- // full data size
- const unsigned size1 = data1.ah().getDataSize();
- ndbrequire(size1 != 0 && size1 == data2.ah().getDataSize());
- const unsigned size2 = min(size1, len2);
- len2 -= size2;
- // compare
- const Uint32* const p1 = &data1[AttributeHeaderSize];
- const Uint32* const p2 = &data2[AttributeHeaderSize];
- ret = NdbSqlUtil::cmp(typeId, p1, p2, size1, size2);
- if (ret != 0) {
+ type = boundInfo[0];
+ boundInfo += 1;
+ if (! boundInfo.ah().isNULL()) {
+ if (! entryData.ah().isNULL()) {
jam();
- return ret;
+ // current attribute
+ const unsigned index = boundInfo.ah().getAttributeId();
+ const DescAttr& descAttr = descEnt.m_descAttr[index];
+ const unsigned typeId = descAttr.m_typeId;
+ ndbrequire(entryData.ah().getAttributeId() == descAttr.m_primaryAttrId);
+ // full data size
+ const unsigned size1 = boundInfo.ah().getDataSize();
+ ndbrequire(size1 != 0 && size1 == entryData.ah().getDataSize());
+ const unsigned size2 = min(size1, len2);
+ len2 -= size2;
+ // compare
+ const Uint32* const p1 = &boundInfo[AttributeHeaderSize];
+ const Uint32* const p2 = &entryData[AttributeHeaderSize];
+ int ret = NdbSqlUtil::cmp(typeId, p1, p2, size1, size2);
+ // XXX until data format errors are handled
+ ndbrequire(ret != NdbSqlUtil::CmpError);
+ if (ret != 0) {
+ jam();
+ return ret;
+ }
+ } else {
+ jam();
+ // not NULL > NULL
+ return +1;
}
} else {
jam();
- /*
- NULL is bigger than any bound, thus the boundary is always to the
- left of NULL
- */
- return -1;
+ if (! entryData.ah().isNULL()) {
+ jam();
+ // NULL < not NULL
+ return -1;
+ }
}
- data1 += AttributeHeaderSize + data1.ah().getDataSize();
- data2 += AttributeHeaderSize + data2.ah().getDataSize();
+ boundInfo += AttributeHeaderSize + boundInfo.ah().getDataSize();
+ entryData += AttributeHeaderSize + entryData.ah().getDataSize();
+ boundCount -= 1;
}
- ndbassert(ret == 0);
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.
- */
+ * 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;
@@ -233,10 +235,11 @@ Dbtux::cmpScanBound(const Frag& frag, const BoundPar boundPar)
} 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.
- */
+ * 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;
@@ -245,3 +248,72 @@ Dbtux::cmpScanBound(const Frag& frag, const BoundPar boundPar)
}
}
+/*
+ * Scan bound vs tree entry.
+ */
+int
+Dbtux::cmpScanBound(const Frag& frag, unsigned dir, ConstData boundInfo, unsigned boundCount, TableData entryKey)
+{
+ const DescEnt& descEnt = getDescEnt(frag.m_descPage, frag.m_descOff);
+ // direction 0-lower 1-upper
+ ndbrequire(dir <= 1);
+ // initialize type to equality
+ unsigned type = 4;
+ while (boundCount != 0) {
+ // get and skip bound type
+ type = boundInfo[0];
+ boundInfo += 1;
+ if (! boundInfo.ah().isNULL()) {
+ if (*entryKey != 0) {
+ jam();
+ // current attribute
+ const unsigned index = boundInfo.ah().getAttributeId();
+ const DescAttr& descAttr = descEnt.m_descAttr[index];
+ const unsigned typeId = descAttr.m_typeId;
+ // full data size
+ const unsigned size1 = AttributeDescriptor::getSizeInWords(descAttr.m_attrDesc);
+ // compare
+ const Uint32* const p1 = &boundInfo[AttributeHeaderSize];
+ const Uint32* const p2 = *entryKey;
+ int ret = NdbSqlUtil::cmp(typeId, p1, p2, size1, size1);
+ // XXX until data format errors are handled
+ ndbrequire(ret != NdbSqlUtil::CmpError);
+ if (ret != 0) {
+ jam();
+ return ret;
+ }
+ } else {
+ jam();
+ // not NULL > NULL
+ return +1;
+ }
+ } else {
+ jam();
+ if (*entryKey != 0) {
+ jam();
+ // NULL < not NULL
+ return -1;
+ }
+ }
+ boundInfo += AttributeHeaderSize + boundInfo.ah().getDataSize();
+ entryKey += 1;
+ boundCount -= 1;
+ }
+ if (dir == 0) {
+ // lower bound
+ jam();
+ if (type == 1) {
+ jam();
+ return +1;
+ }
+ return -1;
+ } else {
+ // upper bound
+ jam();
+ if (type == 3) {
+ jam();
+ return -1;
+ }
+ return +1;
+ }
+}
diff --git a/ndb/src/kernel/blocks/dbtux/DbtuxDebug.cpp b/ndb/src/kernel/blocks/dbtux/DbtuxDebug.cpp
index c4931685305..11f4f12b7f6 100644
--- a/ndb/src/kernel/blocks/dbtux/DbtuxDebug.cpp
+++ b/ndb/src/kernel/blocks/dbtux/DbtuxDebug.cpp
@@ -137,16 +137,17 @@ Dbtux::printNode(Signal* signal, Frag& frag, NdbOut& out, TupLoc loc, PrintPar&
par.m_ok = false;
}
}
+ static const char* const sep = " *** ";
// check child-parent links
if (node.getLink(2) != par.m_parent) {
par.m_ok = false;
- out << par.m_path << " *** ";
+ out << par.m_path << sep;
out << "parent loc " << hex << node.getLink(2);
out << " should be " << hex << par.m_parent << endl;
}
if (node.getSide() != par.m_side) {
par.m_ok = false;
- out << par.m_path << " *** ";
+ out << par.m_path << sep;
out << "side " << dec << node.getSide();
out << " should be " << dec << par.m_side << endl;
}
@@ -154,26 +155,26 @@ Dbtux::printNode(Signal* signal, Frag& frag, NdbOut& out, TupLoc loc, PrintPar&
const int balance = -cpar[0].m_depth + cpar[1].m_depth;
if (node.getBalance() != balance) {
par.m_ok = false;
- out << par.m_path << " *** ";
+ out << par.m_path << sep;
out << "balance " << node.getBalance();
out << " should be " << balance << endl;
}
if (abs(node.getBalance()) > 1) {
par.m_ok = false;
- out << par.m_path << " *** ";
+ out << par.m_path << sep;
out << "balance " << node.getBalance() << " is invalid" << endl;
}
// check occupancy
- if (node.getOccup() > tree.m_maxOccup) {
+ if (node.getOccup() == 0 || node.getOccup() > tree.m_maxOccup) {
par.m_ok = false;
- out << par.m_path << " *** ";
+ out << par.m_path << sep;
out << "occupancy " << node.getOccup();
- out << " greater than max " << tree.m_maxOccup << endl;
+ out << " zero or greater than max " << tree.m_maxOccup << endl;
}
// check for occupancy of interior node
if (node.getChilds() == 2 && node.getOccup() < tree.m_minOccup) {
par.m_ok = false;
- out << par.m_path << " *** ";
+ out << par.m_path << sep;
out << "occupancy " << node.getOccup() << " of interior node";
out << " less than min " << tree.m_minOccup << endl;
}
@@ -183,13 +184,74 @@ Dbtux::printNode(Signal* signal, Frag& frag, NdbOut& out, TupLoc loc, PrintPar&
node.getLink(1 - i) == NullTupLoc &&
node.getOccup() + cpar[i].m_occup <= tree.m_maxOccup) {
par.m_ok = false;
- out << par.m_path << " *** ";
+ out << par.m_path << sep;
out << "missed merge with child " << i << endl;
}
}
+ // check inline prefix
+ { ConstData data1 = node.getPref();
+ Uint32 data2[MaxPrefSize];
+ memset(data2, DataFillByte, MaxPrefSize << 2);
+ readKeyAttrs(frag, node.getMinMax(0), 0, c_searchKey);
+ copyAttrs(frag, c_searchKey, data2, tree.m_prefSize);
+ for (unsigned n = 0; n < tree.m_prefSize; n++) {
+ if (data1[n] != data2[n]) {
+ par.m_ok = false;
+ out << par.m_path << sep;
+ out << "inline prefix mismatch word " << n;
+ out << " value " << hex << data1[n];
+ out << " should be " << hex << data2[n] << endl;
+ break;
+ }
+ }
+ }
+ // check ordering within node
+ for (unsigned j = 1; j < node.getOccup(); j++) {
+ unsigned start = 0;
+ const TreeEnt ent1 = node.getEnt(j - 1);
+ const TreeEnt ent2 = node.getEnt(j);
+ if (j == 1) {
+ readKeyAttrs(frag, ent1, start, c_searchKey);
+ } else {
+ memcpy(c_searchKey, c_entryKey, frag.m_numAttrs << 2);
+ }
+ readKeyAttrs(frag, ent2, start, c_entryKey);
+ int ret = cmpSearchKey(frag, start, c_searchKey, c_entryKey);
+ if (ret == 0)
+ ret = ent1.cmp(ent2);
+ if (ret != -1) {
+ par.m_ok = false;
+ out << par.m_path << sep;
+ out << " disorder within node at pos " << j << endl;
+ }
+ }
+ // check ordering wrt subtrees
+ for (unsigned i = 0; i <= 1; i++) {
+ if (node.getLink(i) == NullTupLoc)
+ continue;
+ const TreeEnt ent1 = cpar[i].m_minmax[1 - i];
+ const TreeEnt ent2 = node.getMinMax(i);
+ unsigned start = 0;
+ readKeyAttrs(frag, ent1, start, c_searchKey);
+ readKeyAttrs(frag, ent2, start, c_entryKey);
+ int ret = cmpSearchKey(frag, start, c_searchKey, c_entryKey);
+ if (ret == 0)
+ ret = ent1.cmp(ent2);
+ if (ret != (i == 0 ? -1 : +1)) {
+ par.m_ok = false;
+ out << par.m_path << sep;
+ out << " disorder wrt subtree " << i << endl;
+ }
+ }
// return values
par.m_depth = 1 + max(cpar[0].m_depth, cpar[1].m_depth);
par.m_occup = node.getOccup();
+ for (unsigned i = 0; i <= 1; i++) {
+ if (node.getLink(i) == NullTupLoc)
+ par.m_minmax[i] = node.getMinMax(i);
+ else
+ par.m_minmax[i] = cpar[i].m_minmax[i];
+ }
}
NdbOut&
@@ -355,20 +417,19 @@ operator<<(NdbOut& out, const Dbtux::NodeHandle& node)
out << " [acc " << dec << node.m_acc << "]";
out << " [node " << *node.m_node << "]";
if (node.m_acc >= Dbtux::AccPref) {
- for (unsigned i = 0; i <= 1; i++) {
- out << " [pref " << dec << i;
- const Uint32* data = (const Uint32*)node.m_node + Dbtux::NodeHeadSize + i * tree.m_prefSize;
- for (unsigned j = 0; j < node.m_frag.m_tree.m_prefSize; j++)
- out << " " << hex << data[j];
- 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;
if (node.m_acc < Dbtux::AccFull && numpos > 2) {
numpos = 2;
out << "(" << dec << numpos << ")";
}
- const Uint32* data = (const Uint32*)node.m_node + Dbtux::NodeHeadSize + 2 * tree.m_prefSize;
+ 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];
diff --git a/ndb/src/kernel/blocks/dbtux/DbtuxGen.cpp b/ndb/src/kernel/blocks/dbtux/DbtuxGen.cpp
index 93a5c78338c..f6f1610c8c1 100644
--- a/ndb/src/kernel/blocks/dbtux/DbtuxGen.cpp
+++ b/ndb/src/kernel/blocks/dbtux/DbtuxGen.cpp
@@ -26,8 +26,13 @@ Dbtux::Dbtux(const Configuration& conf) :
#ifdef VM_TRACE
debugFile(0),
debugOut(*new NullOutputStream()),
+ // until ndb_mgm supports dump
+#ifdef DBTUX_DEBUG_TREE
+ debugFlags(DebugTree),
+#else
debugFlags(0),
#endif
+#endif
c_internalStartPhase(0),
c_typeOfStart(NodeState::ST_ILLEGAL_TYPE),
c_dataBuffer(0)
@@ -187,6 +192,7 @@ Dbtux::execREAD_CONFIG_REQ(Signal* signal)
IndexPtr indexPtr;
while (1) {
jam();
+ refresh_watch_dog();
c_indexPool.seize(indexPtr);
if (indexPtr.i == RNIL) {
jam();
@@ -241,37 +247,14 @@ Dbtux::readKeyAttrs(const Frag& frag, TreeEnt ent, unsigned start, TableData key
}
void
-Dbtux::copyAttrs(Data dst, ConstData src, CopyPar& copyPar)
+Dbtux::readTablePk(const Frag& frag, TreeEnt ent, unsigned& pkSize, Data pkData)
{
- CopyPar c = copyPar;
- c.m_numitems = 0;
- c.m_numwords = 0;
- while (c.m_numitems < c.m_items) {
- jam();
- if (c.m_headers) {
- unsigned i = 0;
- while (i < AttributeHeaderSize) {
- if (c.m_numwords >= c.m_maxwords) {
- copyPar = c;
- return;
- }
- dst[c.m_numwords++] = src[i++];
- }
- }
- unsigned size = src.ah().getDataSize();
- src += AttributeHeaderSize;
- unsigned i = 0;
- while (i < size) {
- if (c.m_numwords >= c.m_maxwords) {
- copyPar = c;
- return;
- }
- dst[c.m_numwords++] = src[i++];
- }
- src += size;
- c.m_numitems++;
- }
- copyPar = c;
+ const Uint32 tableFragPtrI = frag.m_tupTableFragPtrI[ent.m_fragBit];
+ const TupLoc tupLoc = ent.m_tupLoc;
+ Uint32 size = 0;
+ c_tup->tuxReadKeys(tableFragPtrI, tupLoc.m_pageId, tupLoc.m_pageOffset, &size, pkData);
+ ndbrequire(size != 0);
+ pkSize = size;
}
/*
@@ -314,6 +297,9 @@ Dbtux::copyAttrs(const Frag& frag, TableData data1, Data data2, unsigned maxlen2
keyAttrs += 1;
data1 += 1;
}
+#ifdef VM_TRACE
+ memset(data2, DataFillByte, len2 << 2);
+#endif
}
BLOCK_FUNCTIONS(Dbtux);
diff --git a/ndb/src/kernel/blocks/dbtux/DbtuxMaint.cpp b/ndb/src/kernel/blocks/dbtux/DbtuxMaint.cpp
index fc72611a273..24b030bf8ec 100644
--- a/ndb/src/kernel/blocks/dbtux/DbtuxMaint.cpp
+++ b/ndb/src/kernel/blocks/dbtux/DbtuxMaint.cpp
@@ -82,8 +82,8 @@ Dbtux::execTUX_MAINT_REQ(Signal* signal)
ent.m_fragBit = fragBit;
// read search key
readKeyAttrs(frag, ent, 0, c_searchKey);
- // check if all keys are null
- {
+ if (! frag.m_storeNullKey) {
+ // check if all keys are null
const unsigned numAttrs = frag.m_numAttrs;
bool allNull = true;
for (unsigned i = 0; i < numAttrs; i++) {
@@ -111,19 +111,18 @@ Dbtux::execTUX_MAINT_REQ(Signal* signal)
debugOut << endl;
}
#endif
- // find position in tree
- TreePos treePos;
- treeSearch(signal, frag, c_searchKey, ent, treePos);
-#ifdef VM_TRACE
- if (debugFlags & DebugMaint) {
- debugOut << treePos << endl;
- }
-#endif
// do the operation
req->errorCode = 0;
+ TreePos treePos;
switch (opCode) {
case TuxMaintReq::OpAdd:
jam();
+ searchToAdd(signal, frag, c_searchKey, ent, treePos);
+#ifdef VM_TRACE
+ if (debugFlags & DebugMaint) {
+ debugOut << treePos << endl;
+ }
+#endif
if (treePos.m_match) {
jam();
// there is no "Building" state so this will have to do
@@ -152,6 +151,12 @@ Dbtux::execTUX_MAINT_REQ(Signal* signal)
break;
case TuxMaintReq::OpRemove:
jam();
+ searchToRemove(signal, frag, c_searchKey, ent, treePos);
+#ifdef VM_TRACE
+ if (debugFlags & DebugMaint) {
+ debugOut << treePos << endl;
+ }
+#endif
if (! treePos.m_match) {
jam();
// there is no "Building" state so this will have to do
@@ -167,7 +172,6 @@ Dbtux::execTUX_MAINT_REQ(Signal* signal)
ndbrequire(false);
break;
}
- // commit and release nodes
#ifdef VM_TRACE
if (debugFlags & DebugTree) {
printTree(signal, frag, debugOut);
@@ -176,89 +180,3 @@ Dbtux::execTUX_MAINT_REQ(Signal* signal)
// copy back
*sig = *req;
}
-
-/*
- * Read index key attributes from TUP. If buffer is provided the data
- * is copied to it. Otherwise pointer is set to signal data.
- */
-void
-Dbtux::tupReadAttrs(Signal* signal, const Frag& frag, ReadPar& readPar)
-{
- // define the direct signal
- const TreeEnt ent = readPar.m_ent;
- TupReadAttrs* const req = (TupReadAttrs*)signal->getDataPtrSend();
- req->errorCode = RNIL;
- req->requestInfo = 0;
- req->tableId = frag.m_tableId;
- req->fragId = frag.m_fragId | (ent.m_fragBit << frag.m_fragOff);
- req->fragPtrI = frag.m_tupTableFragPtrI[ent.m_fragBit];
- req->tupAddr = (Uint32)-1;
- req->tupVersion = ent.m_tupVersion;
- req->pageId = ent.m_tupLoc.m_pageId;
- req->pageOffset = ent.m_tupLoc.m_pageOffset;
- req->bufferId = 0;
- // add count and list of attribute ids
- Data data = (Uint32*)req + TupReadAttrs::SignalLength;
- data[0] = readPar.m_count;
- data += 1;
- const DescEnt& descEnt = getDescEnt(frag.m_descPage, frag.m_descOff);
- for (Uint32 i = 0; i < readPar.m_count; i++) {
- jam();
- const DescAttr& descAttr = descEnt.m_descAttr[readPar.m_first + i];
- data.ah() = AttributeHeader(descAttr.m_primaryAttrId, 0);
- data += 1;
- }
- // execute
- EXECUTE_DIRECT(DBTUP, GSN_TUP_READ_ATTRS, signal, TupReadAttrs::SignalLength);
- jamEntry();
- ndbrequire(req->errorCode == 0);
- // data is at output
- if (readPar.m_data == 0) {
- readPar.m_data = data;
- } else {
- jam();
- CopyPar copyPar;
- copyPar.m_items = readPar.m_count;
- copyPar.m_headers = true;
- copyAttrs(readPar.m_data, data, copyPar);
- }
-}
-
-/*
- * Read primary keys. Copy the data without attribute headers into the
- * given buffer. Number of words is returned in ReadPar argument.
- */
-void
-Dbtux::tupReadKeys(Signal* signal, const Frag& frag, ReadPar& readPar)
-{
- // define the direct signal
- const TreeEnt ent = readPar.m_ent;
- TupReadAttrs* const req = (TupReadAttrs*)signal->getDataPtrSend();
- req->errorCode = RNIL;
- req->requestInfo = TupReadAttrs::ReadKeys;
- req->tableId = frag.m_tableId;
- req->fragId = frag.m_fragId | (ent.m_fragBit << frag.m_fragOff);
- req->fragPtrI = frag.m_tupTableFragPtrI[ent.m_fragBit];
- req->tupAddr = (Uint32)-1;
- req->tupVersion = RNIL; // not used
- req->pageId = ent.m_tupLoc.m_pageId;
- req->pageOffset = ent.m_tupLoc.m_pageOffset;
- req->bufferId = 0;
- // execute
- EXECUTE_DIRECT(DBTUP, GSN_TUP_READ_ATTRS, signal, TupReadAttrs::SignalLength);
- jamEntry();
- ndbrequire(req->errorCode == 0);
- // copy out in special format
- ConstData data = (Uint32*)req + TupReadAttrs::SignalLength;
- const Uint32 numKeys = data[0];
- data += 1 + numKeys;
- // copy out without headers
- ndbrequire(readPar.m_data != 0);
- CopyPar copyPar;
- copyPar.m_items = numKeys;
- copyPar.m_headers = false;
- copyAttrs(readPar.m_data, data, copyPar);
- // return counts
- readPar.m_count = numKeys;
- readPar.m_size = copyPar.m_numwords;
-}
diff --git a/ndb/src/kernel/blocks/dbtux/DbtuxMeta.cpp b/ndb/src/kernel/blocks/dbtux/DbtuxMeta.cpp
index 0612f191830..b30b555ccad 100644
--- a/ndb/src/kernel/blocks/dbtux/DbtuxMeta.cpp
+++ b/ndb/src/kernel/blocks/dbtux/DbtuxMeta.cpp
@@ -85,6 +85,7 @@ Dbtux::execTUXFRAGREQ(Signal* signal)
fragPtr.p->m_fragOff = req->fragOff;
fragPtr.p->m_fragId = req->fragId;
fragPtr.p->m_numAttrs = req->noOfAttr;
+ fragPtr.p->m_storeNullKey = true; // not yet configurable
fragPtr.p->m_tupIndexFragPtrI = req->tupIndexFragPtrI;
fragPtr.p->m_tupTableFragPtrI[0] = req->tupTableFragPtrI[0];
fragPtr.p->m_tupTableFragPtrI[1] = req->tupTableFragPtrI[1];
@@ -111,6 +112,7 @@ Dbtux::execTUXFRAGREQ(Signal* signal)
indexPtr.p->m_tableId = req->primaryTableId;
indexPtr.p->m_fragOff = req->fragOff;
indexPtr.p->m_numAttrs = req->noOfAttr;
+ indexPtr.p->m_storeNullKey = true; // not yet configurable
// allocate attribute descriptors
if (! allocDescEnt(indexPtr)) {
jam();
@@ -405,14 +407,15 @@ Dbtux::freeDescEnt(IndexPtr indexPtr)
index2.m_descPage == pagePtr.i &&
index2.m_descOff == off + size);
// move the entry (overlapping copy if size < size2)
- for (unsigned i = 0; i < size2; i++) {
+ unsigned i;
+ for (i = 0; i < size2; i++) {
jam();
data[off + i] = data[off + size + i];
}
off += size2;
// adjust page offset in index and all fragments
index2.m_descOff -= size;
- for (unsigned i = 0; i < index2.m_numFrags; i++) {
+ for (i = 0; i < index2.m_numFrags; i++) {
jam();
Frag& frag2 = *c_fragPool.getPtr(index2.m_fragPtrI[i]);
frag2.m_descOff -= size;
diff --git a/ndb/src/kernel/blocks/dbtux/DbtuxNode.cpp b/ndb/src/kernel/blocks/dbtux/DbtuxNode.cpp
index c969e35dc82..a1bfa2179bb 100644
--- a/ndb/src/kernel/blocks/dbtux/DbtuxNode.cpp
+++ b/ndb/src/kernel/blocks/dbtux/DbtuxNode.cpp
@@ -85,10 +85,9 @@ Dbtux::insertNode(Signal* signal, NodeHandle& node, AccSize acc)
new (node.m_node) TreeNode();
#ifdef VM_TRACE
TreeHead& tree = frag.m_tree;
- memset(node.getPref(0), 0xa2, tree.m_prefSize << 2);
- memset(node.getPref(1), 0xa2, tree.m_prefSize << 2);
+ memset(node.getPref(), DataFillByte, tree.m_prefSize << 2);
TreeEnt* entList = tree.getEntList(node.m_node);
- memset(entList, 0xa4, (tree.m_maxOccup + 1) * (TreeEntSize << 2));
+ memset(entList, NodeFillByte, (tree.m_maxOccup + 1) * (TreeEntSize << 2));
#endif
}
@@ -116,12 +115,12 @@ Dbtux::deleteNode(Signal* signal, NodeHandle& node)
* attribute headers for now. XXX use null mask instead
*/
void
-Dbtux::setNodePref(Signal* signal, NodeHandle& node, unsigned i)
+Dbtux::setNodePref(Signal* signal, NodeHandle& node)
{
const Frag& frag = node.m_frag;
const TreeHead& tree = frag.m_tree;
- readKeyAttrs(frag, node.getMinMax(i), 0, c_entryKey);
- copyAttrs(frag, c_entryKey, node.getPref(i), tree.m_prefSize);
+ readKeyAttrs(frag, node.getMinMax(0), 0, c_entryKey);
+ copyAttrs(frag, c_entryKey, node.getPref(), tree.m_prefSize);
}
// node operations
@@ -173,11 +172,9 @@ Dbtux::nodePushUp(Signal* signal, NodeHandle& node, unsigned pos, const TreeEnt&
tmpList[pos] = ent;
entList[0] = entList[occup + 1];
node.setOccup(occup + 1);
- // fix prefixes
+ // fix prefix
if (occup == 0 || pos == 0)
- setNodePref(signal, node, 0);
- if (occup == 0 || pos == occup)
- setNodePref(signal, node, 1);
+ setNodePref(signal, node);
}
/*
@@ -248,11 +245,9 @@ Dbtux::nodePopDown(Signal* signal, NodeHandle& node, unsigned pos, TreeEnt& ent)
}
entList[0] = entList[occup - 1];
node.setOccup(occup - 1);
- // fix prefixes
+ // fix prefix
if (occup != 1 && pos == 0)
- setNodePref(signal, node, 0);
- if (occup != 1 && pos == occup - 1)
- setNodePref(signal, node, 1);
+ setNodePref(signal, node);
}
/*
@@ -325,11 +320,9 @@ Dbtux::nodePushDown(Signal* signal, NodeHandle& node, unsigned pos, TreeEnt& ent
tmpList[pos] = ent;
ent = oldMin;
entList[0] = entList[occup];
- // fix prefixes
+ // fix prefix
if (true)
- setNodePref(signal, node, 0);
- if (occup == 1 || pos == occup - 1)
- setNodePref(signal, node, 1);
+ setNodePref(signal, node);
}
/*
@@ -403,11 +396,9 @@ Dbtux::nodePopUp(Signal* signal, NodeHandle& node, unsigned pos, TreeEnt& ent)
}
tmpList[0] = newMin;
entList[0] = entList[occup];
- // fix prefixes
+ // fix prefix
if (true)
- setNodePref(signal, node, 0);
- if (occup == 1 || pos == occup - 1)
- setNodePref(signal, node, 1);
+ setNodePref(signal, node);
}
/*
diff --git a/ndb/src/kernel/blocks/dbtux/DbtuxScan.cpp b/ndb/src/kernel/blocks/dbtux/DbtuxScan.cpp
index 703b0abb683..c4c33ff931f 100644
--- a/ndb/src/kernel/blocks/dbtux/DbtuxScan.cpp
+++ b/ndb/src/kernel/blocks/dbtux/DbtuxScan.cpp
@@ -137,7 +137,7 @@ Dbtux::execTUX_BOUND_INFO(Signal* signal)
const Uint32* const data = (Uint32*)sig + TuxBoundInfo::SignalLength;
unsigned offset = 5;
// walk through entries
- while (offset + 2 < req->boundAiLength) {
+ while (offset + 2 <= req->boundAiLength) {
jam();
const unsigned type = data[offset];
if (type > 4) {
@@ -379,8 +379,8 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal)
scanNext(signal, scanPtr);
}
// for reading tuple key in Current or Locked state
- ReadPar keyPar;
- keyPar.m_data = 0; // indicates not yet done
+ Data pkData = c_dataBuffer;
+ unsigned pkSize = 0; // indicates not yet done
if (scan.m_state == ScanOp::Current) {
// found an entry to return
jam();
@@ -389,9 +389,7 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal)
jam();
const TreeEnt ent = scan.m_scanPos.m_ent;
// read tuple key
- keyPar.m_ent = ent;
- keyPar.m_data = c_dataBuffer;
- tupReadKeys(signal, frag, keyPar);
+ readTablePk(frag, ent, pkSize, pkData);
// get read lock or exclusive lock
AccLockReq* const lockReq = (AccLockReq*)signal->getDataPtrSend();
lockReq->returnCode = RNIL;
@@ -403,9 +401,9 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal)
lockReq->tableId = scan.m_tableId;
lockReq->fragId = frag.m_fragId | (ent.m_fragBit << frag.m_fragOff);
lockReq->fragPtrI = frag.m_accTableFragPtrI[ent.m_fragBit];
- const Uint32* const buf32 = static_cast<Uint32*>(keyPar.m_data);
+ const Uint32* const buf32 = static_cast<Uint32*>(pkData);
const Uint64* const buf64 = reinterpret_cast<const Uint64*>(buf32);
- lockReq->hashValue = md5_hash(buf64, keyPar.m_size);
+ lockReq->hashValue = md5_hash(buf64, pkSize);
lockReq->tupAddr = getTupAddr(frag, ent);
lockReq->transId1 = scan.m_transId1;
lockReq->transId2 = scan.m_transId2;
@@ -480,11 +478,9 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal)
const TreeEnt ent = scan.m_scanPos.m_ent;
if (scan.m_keyInfo) {
jam();
- if (keyPar.m_data == 0) {
+ if (pkSize == 0) {
jam();
- keyPar.m_ent = ent;
- keyPar.m_data = c_dataBuffer;
- tupReadKeys(signal, frag, keyPar);
+ readTablePk(frag, ent, pkSize, pkData);
}
}
// conf signal
@@ -510,10 +506,10 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal)
// add key info
if (scan.m_keyInfo) {
jam();
- conf->keyLength = keyPar.m_size;
+ conf->keyLength = pkSize;
// piggy-back first 4 words of key data
for (unsigned i = 0; i < 4; i++) {
- conf->key[i] = i < keyPar.m_size ? keyPar.m_data[i] : 0;
+ conf->key[i] = i < pkSize ? pkData[i] : 0;
}
signalLength = 11;
}
@@ -525,18 +521,18 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal)
EXECUTE_DIRECT(blockNo, GSN_NEXT_SCANCONF, signal, signalLength);
}
// send rest of key data
- if (scan.m_keyInfo && keyPar.m_size > 4) {
+ if (scan.m_keyInfo && pkSize > 4) {
unsigned total = 4;
- while (total < keyPar.m_size) {
+ while (total < pkSize) {
jam();
- unsigned length = keyPar.m_size - total;
+ unsigned length = pkSize - total;
if (length > 20)
length = 20;
signal->theData[0] = scan.m_userPtr;
signal->theData[1] = 0;
signal->theData[2] = 0;
signal->theData[3] = length;
- memcpy(&signal->theData[4], &keyPar.m_data[total], length << 2);
+ memcpy(&signal->theData[4], &pkData[total], length << 2);
sendSignal(scan.m_userRef, GSN_ACC_SCAN_INFO24,
signal, 4 + length, JBB);
total += length;
@@ -606,6 +602,8 @@ Dbtux::execACCKEYCONF(Signal* signal)
// LQH has the ball
return;
}
+ // lose the lock
+ scan.m_accLockOp = RNIL;
// continue at ACC_ABORTCONF
}
@@ -648,6 +646,8 @@ Dbtux::execACCKEYREF(Signal* signal)
// LQH has the ball
return;
}
+ // lose the lock
+ scan.m_accLockOp = RNIL;
// continue at ACC_ABORTCONF
}
@@ -689,16 +689,9 @@ Dbtux::scanFirst(Signal* signal, ScanOpPtr scanPtr)
ScanOp& scan = *scanPtr.p;
Frag& frag = *c_fragPool.getPtr(scan.m_fragPtrI);
TreeHead& tree = frag.m_tree;
- if (tree.m_root == NullTupLoc) {
- // tree may have become empty
- jam();
- scan.m_state = ScanOp::Last;
- return;
- }
- TreePos pos;
- pos.m_loc = tree.m_root;
- NodeHandle node(frag);
- // unpack lower bound
+ // set up index keys for this operation
+ setKeyAttrs(frag);
+ // unpack lower bound into c_dataBuffer
const ScanBound& bound = *scan.m_bound[0];
ScanBoundIterator iter;
bound.first(iter);
@@ -707,103 +700,22 @@ Dbtux::scanFirst(Signal* signal, ScanOpPtr scanPtr)
c_dataBuffer[j] = *iter.data;
bound.next(iter);
}
- // comparison parameters
- BoundPar boundPar;
- boundPar.m_data1 = c_dataBuffer;
- boundPar.m_count1 = scan.m_boundCnt[0];
- boundPar.m_dir = 0;
-loop: {
+ // search for scan start position
+ TreePos treePos;
+ searchToScan(signal, frag, c_dataBuffer, scan.m_boundCnt[0], treePos);
+ if (treePos.m_loc == NullTupLoc) {
+ // empty tree
jam();
- selectNode(signal, node, pos.m_loc, AccPref);
- const unsigned occup = node.getOccup();
- ndbrequire(occup != 0);
- for (unsigned i = 0; i <= 1; i++) {
- jam();
- // compare prefix
- boundPar.m_data2 = node.getPref(i);
- boundPar.m_len2 = tree.m_prefSize;
- int ret = cmpScanBound(frag, boundPar);
- if (ret == NdbSqlUtil::CmpUnknown) {
- jam();
- // read full value
- ReadPar readPar;
- readPar.m_ent = node.getMinMax(i);
- readPar.m_first = 0;
- readPar.m_count = frag.m_numAttrs;
- readPar.m_data = 0; // leave in signal data
- tupReadAttrs(signal, frag, readPar);
- // compare full value
- boundPar.m_data2 = readPar.m_data;
- boundPar.m_len2 = ZNIL; // big
- ret = cmpScanBound(frag, boundPar);
- ndbrequire(ret != NdbSqlUtil::CmpUnknown);
- }
- if (i == 0 && ret < 0) {
- jam();
- const TupLoc loc = node.getLink(i);
- if (loc != NullTupLoc) {
- jam();
- // continue to left subtree
- pos.m_loc = loc;
- goto loop;
- }
- // start scanning this node
- pos.m_pos = 0;
- pos.m_match = false;
- pos.m_dir = 3;
- scan.m_scanPos = pos;
- scan.m_state = ScanOp::Next;
- linkScan(node, scanPtr);
- return;
- }
- if (i == 1 && ret > 0) {
- jam();
- const TupLoc loc = node.getLink(i);
- if (loc != NullTupLoc) {
- jam();
- // continue to right subtree
- pos.m_loc = loc;
- goto loop;
- }
- // start scanning upwards
- pos.m_dir = 1;
- scan.m_scanPos = pos;
- scan.m_state = ScanOp::Next;
- linkScan(node, scanPtr);
- return;
- }
- }
- // read rest of current node
- accessNode(signal, node, AccFull);
- // look for first entry
- ndbrequire(occup >= 2);
- for (unsigned j = 1; j < occup; j++) {
- jam();
- ReadPar readPar;
- readPar.m_ent = node.getEnt(j);
- readPar.m_first = 0;
- readPar.m_count = frag.m_numAttrs;
- readPar.m_data = 0; // leave in signal data
- tupReadAttrs(signal, frag, readPar);
- // compare
- boundPar.m_data2 = readPar.m_data;
- boundPar.m_len2 = ZNIL; // big
- int ret = cmpScanBound(frag, boundPar);
- ndbrequire(ret != NdbSqlUtil::CmpUnknown);
- if (ret < 0) {
- jam();
- // start scanning this node
- pos.m_pos = j;
- pos.m_match = false;
- pos.m_dir = 3;
- scan.m_scanPos = pos;
- scan.m_state = ScanOp::Next;
- linkScan(node, scanPtr);
- return;
- }
- }
- ndbrequire(false);
+ scan.m_state = ScanOp::Last;
+ return;
}
+ // set position and state
+ scan.m_scanPos = treePos;
+ scan.m_state = ScanOp::Next;
+ // link the scan to node found
+ NodeHandle node(frag);
+ selectNode(signal, node, treePos.m_loc, AccFull);
+ linkScan(node, scanPtr);
}
/*
@@ -830,7 +742,9 @@ Dbtux::scanNext(Signal* signal, ScanOpPtr scanPtr)
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;
@@ -841,7 +755,9 @@ Dbtux::scanNext(Signal* signal, ScanOpPtr scanPtr)
scan.m_accLockOp = RNIL;
scan.m_state = ScanOp::Current;
}
- // unpack upper bound
+ // set up index keys for this operation
+ setKeyAttrs(frag);
+ // unpack upper bound into c_dataBuffer
const ScanBound& bound = *scan.m_bound[1];
ScanBoundIterator iter;
bound.first(iter);
@@ -850,11 +766,6 @@ Dbtux::scanNext(Signal* signal, ScanOpPtr scanPtr)
c_dataBuffer[j] = *iter.data;
bound.next(iter);
}
- // comparison parameters
- BoundPar boundPar;
- boundPar.m_data1 = c_dataBuffer;
- boundPar.m_count1 = scan.m_boundCnt[1];
- boundPar.m_dir = 1;
// use copy of position
TreePos pos = scan.m_scanPos;
// get and remember original node
@@ -912,17 +823,9 @@ Dbtux::scanNext(Signal* signal, ScanOpPtr scanPtr)
jam();
pos.m_ent = node.getEnt(pos.m_pos);
pos.m_dir = 3; // unchanged
- // XXX implement prefix optimization
- ReadPar readPar;
- readPar.m_ent = pos.m_ent;
- readPar.m_first = 0;
- readPar.m_count = frag.m_numAttrs;
- readPar.m_data = 0; // leave in signal data
- tupReadAttrs(signal, frag, readPar);
- // compare
- boundPar.m_data2 = readPar.m_data;
- boundPar.m_len2 = ZNIL; // big
- int ret = cmpScanBound(frag, boundPar);
+ // read and compare all attributes
+ readKeyAttrs(frag, pos.m_ent, 0, c_entryKey);
+ int ret = cmpScanBound(frag, 1, c_dataBuffer, scan.m_boundCnt[1], c_entryKey);
ndbrequire(ret != NdbSqlUtil::CmpUnknown);
if (ret < 0) {
jam();
@@ -994,35 +897,25 @@ Dbtux::scanNext(Signal* signal, ScanOpPtr scanPtr)
bool
Dbtux::scanVisible(Signal* signal, ScanOpPtr scanPtr, TreeEnt ent)
{
- TupQueryTh* const req = (TupQueryTh*)signal->getDataPtrSend();
const ScanOp& scan = *scanPtr.p;
const Frag& frag = *c_fragPool.getPtr(scan.m_fragPtrI);
- /* Assign table, fragment, tuple address + version */
- Uint32 tableId = frag.m_tableId;
Uint32 fragBit = ent.m_fragBit;
+ Uint32 tableFragPtrI = frag.m_tupTableFragPtrI[fragBit];
Uint32 fragId = frag.m_fragId | (fragBit << frag.m_fragOff);
Uint32 tupAddr = getTupAddr(frag, ent);
Uint32 tupVersion = ent.m_tupVersion;
- /* Check for same tuple twice in row */
+ // check for same tuple twice in row
if (scan.m_lastEnt.m_tupLoc == ent.m_tupLoc &&
scan.m_lastEnt.m_fragBit == fragBit) {
jam();
return false;
}
- req->tableId = tableId;
- req->fragId = fragId;
- req->tupAddr = tupAddr;
- req->tupVersion = tupVersion;
- /* Assign transaction info, trans id + savepoint id */
Uint32 transId1 = scan.m_transId1;
Uint32 transId2 = scan.m_transId2;
Uint32 savePointId = scan.m_savePointId;
- req->transId1 = transId1;
- req->transId2 = transId2;
- req->savePointId = savePointId;
- EXECUTE_DIRECT(DBTUP, GSN_TUP_QUERY_TH, signal, TupQueryTh::SignalLength);
+ bool ret = c_tup->tuxQueryTh(tableFragPtrI, tupAddr, tupVersion, transId1, transId2, savePointId);
jamEntry();
- return (bool)req->returnCode;
+ return ret;
}
/*
diff --git a/ndb/src/kernel/blocks/dbtux/DbtuxSearch.cpp b/ndb/src/kernel/blocks/dbtux/DbtuxSearch.cpp
new file mode 100644
index 00000000000..84048b308bc
--- /dev/null
+++ b/ndb/src/kernel/blocks/dbtux/DbtuxSearch.cpp
@@ -0,0 +1,333 @@
+/* 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 DBTUX_SEARCH_CPP
+#include "Dbtux.hpp"
+
+/*
+ * Search for entry to add.
+ *
+ * Similar to searchToRemove (see below).
+ *
+ * TODO optimize for initial equal attrs in node min/max
+ */
+void
+Dbtux::searchToAdd(Signal* signal, Frag& frag, TableData 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;
+ if (currNode.m_loc == NullTupLoc) {
+ // empty tree
+ jam();
+ treePos.m_match = false;
+ return;
+ }
+ NodeHandle glbNode(frag); // potential g.l.b of final node
+ /*
+ * In order to not (yet) change old behaviour, a position between
+ * 2 nodes returns the one at the bottom of the tree.
+ */
+ NodeHandle bottomNode(frag);
+ while (true) {
+ jam();
+ selectNode(signal, currNode, currNode.m_loc, AccPref);
+ int ret;
+ // compare prefix
+ unsigned start = 0;
+ ret = cmpSearchKey(frag, start, searchKey, currNode.getPref(), tree.m_prefSize);
+ if (ret == NdbSqlUtil::CmpUnknown) {
+ jam();
+ // read and compare remaining attributes
+ ndbrequire(start < numAttrs);
+ readKeyAttrs(frag, currNode.getMinMax(0), start, c_entryKey);
+ ret = cmpSearchKey(frag, start, searchKey, c_entryKey);
+ ndbrequire(ret != NdbSqlUtil::CmpUnknown);
+ }
+ if (ret == 0) {
+ jam();
+ // keys are equal, compare entry values
+ ret = searchEnt.cmp(currNode.getMinMax(0));
+ }
+ if (ret < 0) {
+ jam();
+ const TupLoc loc = currNode.getLink(0);
+ if (loc != NullTupLoc) {
+ jam();
+ // continue to left subtree
+ currNode.m_loc = loc;
+ continue;
+ }
+ if (! glbNode.isNull()) {
+ jam();
+ // move up to the g.l.b but remember the bottom node
+ bottomNode = currNode;
+ currNode = glbNode;
+ }
+ } else if (ret > 0) {
+ jam();
+ const TupLoc loc = currNode.getLink(1);
+ if (loc != NullTupLoc) {
+ jam();
+ // save potential g.l.b
+ glbNode = currNode;
+ // continue to right subtree
+ currNode.m_loc = loc;
+ continue;
+ }
+ } else {
+ 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);
+ for (unsigned j = 0, occup = currNode.getOccup(); j < occup; j++) {
+ jam();
+ int ret;
+ // read and compare attributes
+ unsigned start = 0;
+ readKeyAttrs(frag, currNode.getEnt(j), start, c_entryKey);
+ ret = cmpSearchKey(frag, start, searchKey, c_entryKey);
+ ndbrequire(ret != NdbSqlUtil::CmpUnknown);
+ if (ret == 0) {
+ jam();
+ // keys are equal, compare entry values
+ ret = searchEnt.cmp(currNode.getEnt(j));
+ }
+ if (ret <= 0) {
+ jam();
+ treePos.m_loc = currNode.m_loc;
+ treePos.m_pos = j;
+ treePos.m_match = (ret == 0);
+ return;
+ }
+ }
+ if (! bottomNode.isNull()) {
+ jam();
+ // backwards compatible for now
+ treePos.m_loc = bottomNode.m_loc;
+ treePos.m_pos = 0;
+ treePos.m_match = false;
+ return;
+ }
+ treePos.m_loc = currNode.m_loc;
+ treePos.m_pos = currNode.getOccup();
+ treePos.m_match = false;
+}
+
+/*
+ * Search for entry to remove.
+ *
+ * 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
+ * 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, TableData 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;
+ if (currNode.m_loc == NullTupLoc) {
+ // empty tree
+ jam();
+ 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);
+ int ret;
+ // compare prefix
+ unsigned start = 0;
+ ret = cmpSearchKey(frag, start, searchKey, currNode.getPref(), tree.m_prefSize);
+ if (ret == NdbSqlUtil::CmpUnknown) {
+ jam();
+ // read and compare remaining attributes
+ ndbrequire(start < numAttrs);
+ readKeyAttrs(frag, currNode.getMinMax(0), start, c_entryKey);
+ ret = cmpSearchKey(frag, start, searchKey, c_entryKey);
+ ndbrequire(ret != NdbSqlUtil::CmpUnknown);
+ }
+ if (ret == 0) {
+ jam();
+ // keys are equal, compare entry values
+ ret = searchEnt.cmp(currNode.getMinMax(0));
+ }
+ if (ret < 0) {
+ jam();
+ const TupLoc loc = currNode.getLink(0);
+ if (loc != NullTupLoc) {
+ jam();
+ // continue to left subtree
+ currNode.m_loc = loc;
+ continue;
+ }
+ if (! glbNode.isNull()) {
+ jam();
+ // move up to the g.l.b
+ currNode = glbNode;
+ }
+ } else if (ret > 0) {
+ jam();
+ const TupLoc loc = currNode.getLink(1);
+ if (loc != NullTupLoc) {
+ jam();
+ // save potential g.l.b
+ glbNode = currNode;
+ // continue to right subtree
+ currNode.m_loc = loc;
+ continue;
+ }
+ } else {
+ 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);
+ // 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();
+ treePos.m_match = false;
+}
+
+/*
+ * Search for scan start position.
+ *
+ * Similar to searchToAdd.
+ */
+void
+Dbtux::searchToScan(Signal* signal, Frag& frag, ConstData boundInfo, unsigned boundCount, TreePos& treePos)
+{
+ const TreeHead& tree = frag.m_tree;
+ NodeHandle currNode(frag);
+ currNode.m_loc = tree.m_root;
+ if (currNode.m_loc == NullTupLoc) {
+ // empty tree
+ jam();
+ treePos.m_match = false;
+ return;
+ }
+ NodeHandle glbNode(frag); // potential g.l.b of final node
+ NodeHandle bottomNode(frag);
+ while (true) {
+ jam();
+ selectNode(signal, currNode, currNode.m_loc, AccPref);
+ int ret;
+ // compare prefix
+ ret = cmpScanBound(frag, 0, boundInfo, boundCount, currNode.getPref(), tree.m_prefSize);
+ if (ret == NdbSqlUtil::CmpUnknown) {
+ jam();
+ // read and compare all attributes
+ readKeyAttrs(frag, currNode.getMinMax(0), 0, c_entryKey);
+ ret = cmpScanBound(frag, 0, boundInfo, boundCount, c_entryKey);
+ ndbrequire(ret != NdbSqlUtil::CmpUnknown);
+ }
+ if (ret < 0) {
+ jam();
+ const TupLoc loc = currNode.getLink(0);
+ if (loc != NullTupLoc) {
+ jam();
+ // continue to left subtree
+ currNode.m_loc = loc;
+ continue;
+ }
+ if (! glbNode.isNull()) {
+ jam();
+ // move up to the g.l.b but remember the bottom node
+ bottomNode = currNode;
+ currNode = glbNode;
+ } else {
+ // start scanning this node
+ treePos.m_loc = currNode.m_loc;
+ treePos.m_pos = 0;
+ treePos.m_match = false;
+ treePos.m_dir = 3;
+ return;
+ }
+ } else if (ret > 0) {
+ jam();
+ const TupLoc loc = currNode.getLink(1);
+ if (loc != NullTupLoc) {
+ jam();
+ // save potential g.l.b
+ glbNode = currNode;
+ // continue to right subtree
+ currNode.m_loc = loc;
+ continue;
+ }
+ } else {
+ ndbassert(false);
+ }
+ break;
+ }
+ // access rest of current node
+ accessNode(signal, currNode, AccFull);
+ for (unsigned j = 0, occup = currNode.getOccup(); j < occup; j++) {
+ jam();
+ int ret;
+ // read and compare attributes
+ readKeyAttrs(frag, currNode.getEnt(j), 0, c_entryKey);
+ ret = cmpScanBound(frag, 0, boundInfo, boundCount, c_entryKey);
+ ndbrequire(ret != NdbSqlUtil::CmpUnknown);
+ if (ret < 0) {
+ // start scanning from current entry
+ treePos.m_loc = currNode.m_loc;
+ treePos.m_pos = j;
+ treePos.m_match = false;
+ treePos.m_dir = 3;
+ return;
+ }
+ }
+ if (! bottomNode.isNull()) {
+ jam();
+ // start scanning the l.u.b
+ treePos.m_loc = bottomNode.m_loc;
+ treePos.m_pos = 0;
+ treePos.m_match = false;
+ treePos.m_dir = 3;
+ return;
+ }
+ // start scanning upwards (pretend we came from right child)
+ treePos.m_loc = currNode.m_loc;
+ treePos.m_dir = 1;
+}
diff --git a/ndb/src/kernel/blocks/dbtux/DbtuxTree.cpp b/ndb/src/kernel/blocks/dbtux/DbtuxTree.cpp
index 7c3f5fa36b8..3baa62998db 100644
--- a/ndb/src/kernel/blocks/dbtux/DbtuxTree.cpp
+++ b/ndb/src/kernel/blocks/dbtux/DbtuxTree.cpp
@@ -18,112 +18,6 @@
#include "Dbtux.hpp"
/*
- * Search for entry.
- *
- * Search key is index attribute data and tree entry value. Start from
- * root node and compare the key to min/max of each node. Use linear
- * search on the final (bounding) node. Initial attributes which are
- * same in min/max need not be checked.
- */
-void
-Dbtux::treeSearch(Signal* signal, Frag& frag, TableData searchKey, TreeEnt searchEnt, TreePos& treePos)
-{
- const TreeHead& tree = frag.m_tree;
- const unsigned numAttrs = frag.m_numAttrs;
- treePos.m_loc = tree.m_root;
- if (treePos.m_loc == NullTupLoc) {
- // empty tree
- jam();
- treePos.m_pos = 0;
- treePos.m_match = false;
- return;
- }
- NodeHandle node(frag);
-loop: {
- jam();
- selectNode(signal, node, treePos.m_loc, AccPref);
- const unsigned occup = node.getOccup();
- ndbrequire(occup != 0);
- // number of equal initial attributes in bounding node
- unsigned start = ZNIL;
- for (unsigned i = 0; i <= 1; i++) {
- jam();
- unsigned start1 = 0;
- // compare prefix
- int ret = cmpSearchKey(frag, start1, searchKey, node.getPref(i), tree.m_prefSize);
- if (ret == NdbSqlUtil::CmpUnknown) {
- jam();
- // read and compare remaining attributes
- readKeyAttrs(frag, node.getMinMax(i), start1, c_entryKey);
- ret = cmpSearchKey(frag, start1, searchKey, c_entryKey);
- ndbrequire(ret != NdbSqlUtil::CmpUnknown);
- }
- if (start > start1)
- start = start1;
- if (ret == 0) {
- jam();
- // keys are equal, compare entry values
- ret = searchEnt.cmp(node.getMinMax(i));
- }
- if (i == 0 ? (ret < 0) : (ret > 0)) {
- jam();
- const TupLoc loc = node.getLink(i);
- if (loc != NullTupLoc) {
- jam();
- // continue to left/right subtree
- treePos.m_loc = loc;
- goto loop;
- }
- // position is immediately before/after this node
- treePos.m_pos = (i == 0 ? 0 : occup);
- treePos.m_match = false;
- return;
- }
- if (ret == 0) {
- jam();
- // position is at first/last entry
- treePos.m_pos = (i == 0 ? 0 : occup - 1);
- treePos.m_match = true;
- return;
- }
- }
- // access rest of the bounding node
- accessNode(signal, node, AccFull);
- // position is strictly within the node
- ndbrequire(occup >= 2);
- const unsigned numWithin = occup - 2;
- for (unsigned j = 1; j <= numWithin; j++) {
- jam();
- int ret = 0;
- if (start < numAttrs) {
- jam();
- // read and compare remaining attributes
- unsigned start1 = start;
- readKeyAttrs(frag, node.getEnt(j), start1, c_entryKey);
- ret = cmpSearchKey(frag, start1, searchKey, c_entryKey);
- ndbrequire(ret != NdbSqlUtil::CmpUnknown);
- }
- if (ret == 0) {
- jam();
- // keys are equal, compare entry values
- ret = searchEnt.cmp(node.getEnt(j));
- }
- if (ret <= 0) {
- jam();
- // position is before or at this entry
- treePos.m_pos = j;
- treePos.m_match = (ret == 0);
- return;
- }
- }
- // position is before last entry
- treePos.m_pos = occup - 1;
- treePos.m_match = false;
- return;
- }
-}
-
-/*
* Add entry.
*/
void
@@ -283,7 +177,8 @@ Dbtux::treeRemove(Signal* signal, Frag& frag, TreePos treePos)
nodePopDown(signal, node, pos, ent);
ndbrequire(node.getChilds() <= 1);
// handle half-leaf
- for (unsigned i = 0; i <= 1; i++) {
+ unsigned i;
+ for (i = 0; i <= 1; i++) {
jam();
TupLoc childLoc = node.getLink(i);
if (childLoc != NullTupLoc) {
@@ -297,7 +192,7 @@ Dbtux::treeRemove(Signal* signal, Frag& frag, TreePos treePos)
// get parent if any
TupLoc parentLoc = node.getLink(2);
NodeHandle parentNode(frag);
- unsigned i = node.getSide();
+ i = node.getSide();
// move all that fits into parent
if (parentLoc != NullTupLoc) {
jam();
diff --git a/ndb/src/kernel/blocks/dbtux/Makefile.am b/ndb/src/kernel/blocks/dbtux/Makefile.am
index 0b48ad5724f..7d012924522 100644
--- a/ndb/src/kernel/blocks/dbtux/Makefile.am
+++ b/ndb/src/kernel/blocks/dbtux/Makefile.am
@@ -7,6 +7,7 @@ libdbtux_a_SOURCES = \
DbtuxNode.cpp \
DbtuxTree.cpp \
DbtuxScan.cpp \
+ DbtuxSearch.cpp \
DbtuxCmp.cpp \
DbtuxDebug.cpp
diff --git a/ndb/src/kernel/blocks/dbtux/Times.txt b/ndb/src/kernel/blocks/dbtux/Times.txt
index 16c4102249b..c4744a23c07 100644
--- a/ndb/src/kernel/blocks/dbtux/Times.txt
+++ b/ndb/src/kernel/blocks/dbtux/Times.txt
@@ -1,17 +1,32 @@
-index maintenance overhead
-==========================
+ordered index performance
+=========================
"mc02" 2x1700 MHz linux-2.4.9 gcc-2.96 -O3 one db-node
-case a: index on Unsigned
-testOIBasic -case u -table 1 -index 1 -fragtype small -threads 10 -rows 100000 -subloop 1 -nologging
+case a: maintenance: index on Unsigned
+testOIBasic -case u -table 1 -index 2 -fragtype small -threads 10 -rows 100000 -subloop 1 -nologging
-case b: index on Varchar(5) + Varchar(5) + Varchar(20) + Unsigned
-testOIBasic -case u -table 2 -index 4 -fragtype small -threads 10 -rows 100000 -subloop 1 -nologging
+case b: maintenance: index on Varchar(5) + Varchar(5) + Varchar(20) + Unsigned
+testOIBasic -case u -table 2 -index 5 -fragtype small -threads 10 -rows 100000 -subloop 1 -nologging
+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
+
+a, b
1 million rows, pk update without index, pk update with index
shows ms / 1000 rows for each and pct overhead
-the figures are based on single run on idle machine
+
+c
+1 million rows, index on PK, full table scan, full index scan
+shows ms / 1000 rows for each and index time overhead
+
+d
+1 million rows, index on PK, read table via each pk, scan index for each pk
+shows ms / 1000 rows for each and index time overhead
+samples 10% of all PKs (100,000 pk reads, 100,000 scans)
040616 mc02/a 40 ms 87 ms 114 pct
mc02/b 51 ms 128 ms 148 pct
@@ -49,4 +64,22 @@ optim 10 mc02/a 44 ms 65 ms 46 pct
optim 11 mc02/a 43 ms 63 ms 46 pct
mc02/b 52 ms 86 ms 63 pct
+optim 12 mc02/a 38 ms 55 ms 43 pct
+ mc02/b 47 ms 77 ms 63 pct
+ mc02/c 10 ms 14 ms 47 pct
+ mc02/d 176 ms 281 ms 59 pct
+
+optim 13 mc02/a 40 ms 57 ms 42 pct
+ mc02/b 47 ms 77 ms 61 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)
+[ what happened to PK read performance? ]
+
+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
+
vim: set et:
diff --git a/ndb/src/kernel/blocks/dbutil/DbUtil.cpp b/ndb/src/kernel/blocks/dbutil/DbUtil.cpp
index 92410e1a784..ecaead3ba5a 100644
--- a/ndb/src/kernel/blocks/dbutil/DbUtil.cpp
+++ b/ndb/src/kernel/blocks/dbutil/DbUtil.cpp
@@ -2581,3 +2581,5 @@ DbUtil::execUTIL_DESTORY_LOCK_REQ(Signal* signal){
sendSignal(req.senderRef, GSN_UTIL_DESTROY_LOCK_REF, signal,
UtilDestroyLockRef::SignalLength, JBB);
}
+
+template class ArrayPool<DbUtil::Page32>;
diff --git a/ndb/src/kernel/blocks/grep/Grep.cpp b/ndb/src/kernel/blocks/grep/Grep.cpp
index ee506ce922a..8b93ef9cd20 100644
--- a/ndb/src/kernel/blocks/grep/Grep.cpp
+++ b/ndb/src/kernel/blocks/grep/Grep.cpp
@@ -73,7 +73,7 @@ Grep::getNodeGroupMembers(Signal* signal) {
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++) {
@@ -253,7 +253,8 @@ Grep::execREAD_NODESCONF(Signal* signal)
/******************************
* Check which REP nodes exist
******************************/
- for (Uint32 i = 1; i < MAX_NODES; i++)
+ Uint32 i;
+ for (i = 1; i < MAX_NODES; i++)
{
jam();
#if 0
@@ -279,7 +280,7 @@ Grep::execREAD_NODESCONF(Signal* signal)
m_aliveNodes.clear();
Uint32 count = 0;
- for(Uint32 i = 0; i<MAX_NDB_NODES; i++)
+ for(i = 0; i<MAX_NDB_NODES; i++)
{
if (NodeBitmask::get(conf->allNodes, i))
{
diff --git a/ndb/src/kernel/blocks/grep/Grep.hpp b/ndb/src/kernel/blocks/grep/Grep.hpp
index ba8f5780522..eeabac36966 100644
--- a/ndb/src/kernel/blocks/grep/Grep.hpp
+++ b/ndb/src/kernel/blocks/grep/Grep.hpp
@@ -148,7 +148,7 @@ private:
*/
class Grep : public SimulatedBlock //GrepParticipant
{
- //BLOCK_DEFINES(Grep);
+ BLOCK_DEFINES(Grep);
public:
Grep(const Configuration & conf);
@@ -519,19 +519,6 @@ public:
typedef void (Grep::* ExecSignalLocal1) (Signal* signal);
typedef void (Grep::PSCoord::* ExecSignalLocal2) (Signal* signal);
typedef void (Grep::PSPart::* ExecSignalLocal4) (Signal* signal);
-
- void
- addRecSignal(GlobalSignalNumber gsn, ExecSignalLocal1 f, bool force = false){
- addRecSignalImpl(gsn, (ExecFunction)f, force);
- }
- void
- addRecSignal(GlobalSignalNumber gsn, ExecSignalLocal2 f, bool force = false){
- addRecSignalImpl(gsn, (ExecFunction)f, force);
- }
- void
- addRecSignal(GlobalSignalNumber gsn, ExecSignalLocal4 f, bool force = false){
- addRecSignalImpl(gsn, (ExecFunction)f, force);
- }
};
diff --git a/ndb/src/kernel/blocks/grep/GrepInit.cpp b/ndb/src/kernel/blocks/grep/GrepInit.cpp
index 70bf6678754..cfb454a1f9b 100644
--- a/ndb/src/kernel/blocks/grep/GrepInit.cpp
+++ b/ndb/src/kernel/blocks/grep/GrepInit.cpp
@@ -132,7 +132,7 @@ Grep::~Grep()
{
}
-//BLOCK_FUNCTIONS(Grep);
+BLOCK_FUNCTIONS(Grep);
Grep::PSPart::PSPart(Grep * sb) :
BlockComponent(sb),
diff --git a/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp b/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp
index 06453155f33..ff4876b1506 100644
--- a/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp
+++ b/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp
@@ -554,11 +554,13 @@ Ndbcntr::execCNTR_START_REP(Signal* signal){
}
if(cmasterNodeId != getOwnNodeId()){
+ jam();
c_start.reset();
return;
}
if(c_start.m_waiting.isclear()){
+ jam();
c_start.reset();
return;
}
@@ -597,6 +599,7 @@ Ndbcntr::execCNTR_START_REQ(Signal * signal){
ndbrequire(false);
case NodeState::SL_STARTING:
case NodeState::SL_STARTED:
+ jam();
break;
case NodeState::SL_STOPPING_1:
@@ -616,9 +619,11 @@ Ndbcntr::execCNTR_START_REQ(Signal * signal){
c_start.m_waiting.set(nodeId);
switch(st){
case NodeState::ST_INITIAL_START:
+ jam();
c_start.m_withoutLog.set(nodeId);
break;
case NodeState::ST_SYSTEM_RESTART:
+ jam();
c_start.m_withLog.set(nodeId);
if(starting && lastGci > c_start.m_lastGci){
jam();
@@ -631,6 +636,7 @@ Ndbcntr::execCNTR_START_REQ(Signal * signal){
return;
}
if(starting){
+ jam();
Uint32 i = c_start.m_logNodesCount++;
c_start.m_logNodes[i].m_nodeId = nodeId;
c_start.m_logNodes[i].m_lastGci = req->lastGci;
@@ -652,11 +658,12 @@ Ndbcntr::execCNTR_START_REQ(Signal * signal){
}
if(starting){
+ jam();
trySystemRestart(signal);
} else {
+ jam();
startWaitingNodes(signal);
}
-
return;
}
@@ -670,6 +677,7 @@ Ndbcntr::startWaitingNodes(Signal * signal){
NodeState::StartType nrType = NodeState::ST_NODE_RESTART;
if(c_start.m_withoutLog.get(nodeId)){
+ jam();
nrType = NodeState::ST_INITIAL_NODE_RESTART;
}
@@ -706,6 +714,7 @@ Ndbcntr::startWaitingNodes(Signal * signal){
char buf[100];
if(!c_start.m_withLog.isclear()){
+ jam();
ndbout_c("Starting nodes w/ log: %s", c_start.m_withLog.getText(buf));
NodeReceiverGroup rg(NDBCNTR, c_start.m_withLog);
@@ -716,6 +725,7 @@ Ndbcntr::startWaitingNodes(Signal * signal){
}
if(!c_start.m_withoutLog.isclear()){
+ jam();
ndbout_c("Starting nodes wo/ log: %s", c_start.m_withoutLog.getText(buf));
NodeReceiverGroup rg(NDBCNTR, c_start.m_withoutLog);
conf->startType = NodeState::ST_INITIAL_NODE_RESTART;
@@ -777,6 +787,7 @@ Ndbcntr::trySystemRestart(Signal* signal){
jam();
return false;
}
+ jam();
srType = NodeState::ST_INITIAL_START;
c_start.m_starting = c_start.m_withoutLog; // Used for starting...
c_start.m_withoutLog.clear();
@@ -793,13 +804,11 @@ Ndbcntr::trySystemRestart(Signal* signal){
// If we lose with all nodes, then we're in trouble
ndbrequire(!allNodes);
return false;
- break;
case CheckNodeGroups::Partitioning:
jam();
bool allowPartition = (c_start.m_startPartitionedTimeout != (Uint64)~0);
if(allNodes){
- jam();
if(allowPartition){
jam();
break;
@@ -1043,8 +1052,10 @@ void Ndbcntr::ph5ALab(Signal* signal)
return;
case NodeState::ST_NODE_RESTART:
case NodeState::ST_INITIAL_NODE_RESTART:
+ jam();
break;
case NodeState::ST_ILLEGAL_TYPE:
+ jam();
break;
}
ndbrequire(false);
@@ -1602,6 +1613,7 @@ void Ndbcntr::startInsertTransactions(Signal* signal)
ckey = 1;
ctransidPhase = ZTRUE;
+ signal->theData[0] = 0;
signal->theData[1] = reference();
sendSignal(DBTC_REF, GSN_TCSEIZEREQ, signal, 2, JBB);
return;
@@ -1661,7 +1673,7 @@ void Ndbcntr::crSystab7Lab(Signal* signal)
tcKeyReq->requestInfo = reqInfo;
tcKeyReq->tableSchemaVersion = ZSYSTAB_VERSION;
tcKeyReq->transId1 = 0;
- tcKeyReq->transId2 = 0;
+ tcKeyReq->transId2 = ckey;
//-------------------------------------------------------------
// There is no optional part in this TCKEYREQ. There is one
@@ -1729,6 +1741,7 @@ void Ndbcntr::crSystab8Lab(Signal* signal)
}//if
signal->theData[0] = ctcConnectionP;
signal->theData[1] = reference();
+ signal->theData[2] = 0;
sendSignal(DBTC_REF, GSN_TCRELEASEREQ, signal, 2, JBB);
return;
}//Ndbcntr::crSystab8Lab()
@@ -2313,6 +2326,18 @@ void Ndbcntr::execWAIT_GCP_REF(Signal* signal){
void Ndbcntr::execWAIT_GCP_CONF(Signal* signal){
jamEntry();
+ ndbrequire(StopReq::getSystemStop(c_stopRec.stopReq.requestInfo));
+ NodeState newState(NodeState::SL_STOPPING_3, true);
+
+ /**
+ * Inform QMGR so that arbitrator won't kill us
+ */
+ NodeStateRep * rep = (NodeStateRep *)&signal->theData[0];
+ rep->nodeState = newState;
+ rep->nodeState.masterNodeId = cmasterNodeId;
+ rep->nodeState.setNodeGroup(c_nodeGroup);
+ EXECUTE_DIRECT(QMGR, GSN_NODE_STATE_REP, signal, NodeStateRep::SignalLength);
+
if(StopReq::getPerformRestart(c_stopRec.stopReq.requestInfo)){
jam();
StartOrd * startOrd = (StartOrd *)&signal->theData[0];
diff --git a/ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp b/ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp
index 7ba7d0d25c6..18e46d2d004 100644
--- a/ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp
+++ b/ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp
@@ -108,8 +108,8 @@ AsyncFile::AsyncFile() :
}
void
-AsyncFile::doStart(const char * filesystemPath) {
- theFileName.init(filesystemPath);
+AsyncFile::doStart(Uint32 nodeId, const char * filesystemPath) {
+ theFileName.init(nodeId, filesystemPath);
// Stacksize for filesystem threads
// An 8k stack should be enough
@@ -229,7 +229,7 @@ AsyncFile::run()
endReq();
return;
default:
- THREAD_REQUIRE(false, "Using default switch in AsyncFile::run");
+ abort();
break;
}//switch
theReportTo->writeChannel(request);
diff --git a/ndb/src/kernel/blocks/ndbfs/AsyncFile.hpp b/ndb/src/kernel/blocks/ndbfs/AsyncFile.hpp
index caa03e52d0c..9a405bc1580 100644
--- a/ndb/src/kernel/blocks/ndbfs/AsyncFile.hpp
+++ b/ndb/src/kernel/blocks/ndbfs/AsyncFile.hpp
@@ -181,7 +181,7 @@ public:
void execute( Request* request );
- void doStart(const char * fspath);
+ void doStart(Uint32 nodeId, const char * fspath);
// its a thread so its always running
void run();
diff --git a/ndb/src/kernel/blocks/ndbfs/Filename.cpp b/ndb/src/kernel/blocks/ndbfs/Filename.cpp
index 494c9c74eb9..660fe6eee94 100644
--- a/ndb/src/kernel/blocks/ndbfs/Filename.cpp
+++ b/ndb/src/kernel/blocks/ndbfs/Filename.cpp
@@ -46,7 +46,7 @@ Filename::Filename() :
}
void
-Filename::init(const char * pFileSystemPath){
+Filename::init(Uint32 nodeid, const char * pFileSystemPath){
if (pFileSystemPath == NULL) {
ERROR_SET(fatal, AFS_ERROR_NOPATH, ""," Filename::init()");
return;
@@ -75,8 +75,15 @@ Filename::init(const char * pFileSystemPath){
DIR_SEPARATOR) != 0)
strcat(theBaseDirectory, DIR_SEPARATOR);
-}
+ snprintf(buf2, sizeof(buf2), "ndb_%u_fs%s", nodeid, DIR_SEPARATOR);
+ strcat(theBaseDirectory, buf2);
+#ifdef NDB_WIN32
+ CreateDirectory(theBaseDirectory, 0);
+#else
+ mkdir(theBaseDirectory, S_IRUSR | S_IWUSR | S_IXUSR | S_IXGRP | S_IRGRP);
+#endif
+}
Filename::~Filename(){
}
diff --git a/ndb/src/kernel/blocks/ndbfs/Filename.hpp b/ndb/src/kernel/blocks/ndbfs/Filename.hpp
index 29aba79c9dc..25c06092436 100644
--- a/ndb/src/kernel/blocks/ndbfs/Filename.hpp
+++ b/ndb/src/kernel/blocks/ndbfs/Filename.hpp
@@ -68,7 +68,7 @@ public:
int levels() const;
const char* c_str() const;
- void init(const char * fileSystemPath);
+ void init(Uint32 nodeid, const char * fileSystemPath);
private:
int theLevelDepth;
diff --git a/ndb/src/kernel/blocks/ndbfs/MemoryChannel.hpp b/ndb/src/kernel/blocks/ndbfs/MemoryChannel.hpp
index 435a6a6b208..03911d195ec 100644
--- a/ndb/src/kernel/blocks/ndbfs/MemoryChannel.hpp
+++ b/ndb/src/kernel/blocks/ndbfs/MemoryChannel.hpp
@@ -120,8 +120,7 @@ template <class T> void MemoryChannel<T>::writeChannel( T *t)
{
NdbMutex_Lock(theMutexPtr);
- REQUIRE(!full(theWriteIndex, theReadIndex), "Memory Channel Full");
- REQUIRE(theChannel != NULL, "Memory Channel Full");
+ if(full(theWriteIndex, theReadIndex) || theChannel == NULL) abort();
theChannel[theWriteIndex]= t;
++theWriteIndex;
NdbMutex_Unlock(theMutexPtr);
diff --git a/ndb/src/kernel/blocks/ndbfs/Ndbfs.cpp b/ndb/src/kernel/blocks/ndbfs/Ndbfs.cpp
index fe737fc584b..3b8cb20fe5c 100644
--- a/ndb/src/kernel/blocks/ndbfs/Ndbfs.cpp
+++ b/ndb/src/kernel/blocks/ndbfs/Ndbfs.cpp
@@ -559,7 +559,7 @@ Ndbfs::createAsyncFile(){
}
AsyncFile* file = new AsyncFile;
- file->doStart(theFileSystemPath);
+ file->doStart(getOwnNodeId(), theFileSystemPath);
// Put the file in list of all files
theFiles.push_back(file);
@@ -1010,3 +1010,7 @@ Ndbfs::execDUMP_STATE_ORD(Signal* signal)
BLOCK_FUNCTIONS(Ndbfs);
+template class Vector<AsyncFile*>;
+template class Vector<OpenFiles::OpenFileItem>;
+template class MemoryChannel<Request>;
+template class Pool<Request>;
diff --git a/ndb/src/kernel/blocks/ndbfs/Pool.hpp b/ndb/src/kernel/blocks/ndbfs/Pool.hpp
index a26fa730727..0410673af6f 100644
--- a/ndb/src/kernel/blocks/ndbfs/Pool.hpp
+++ b/ndb/src/kernel/blocks/ndbfs/Pool.hpp
@@ -215,7 +215,6 @@ protected:
T** tList = theList;
int i;
theList = new T*[aSize+theCurrentSize];
- REQUIRE(theList != 0, "Allocate in Pool.hpp failed");
// allocate full list
for (i = 0; i < theTop; i++) {
theList[i] = tList[i];
diff --git a/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp b/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp
index f2d2edb615d..6017365a463 100644
--- a/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp
+++ b/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp
@@ -258,7 +258,6 @@ void Qmgr::execCONNECT_REP(Signal* signal)
{
const Uint32 nodeId = signal->theData[0];
c_connectedNodes.set(nodeId);
-
NodeRecPtr nodePtr;
nodePtr.i = getOwnNodeId();
ptrCheckGuard(nodePtr, MAX_NODES, nodeRec);
@@ -679,7 +678,6 @@ void Qmgr::execCM_REGREF(Signal* signal)
UintR TaddNodeno = signal->theData[1];
UintR TrefuseReason = signal->theData[2];
Uint32 candidate = signal->theData[3];
-
DEBUG_START3(signal, TrefuseReason);
if(candidate != cpresidentCandidate){
@@ -768,7 +766,6 @@ void Qmgr::execCM_REGREF(Signal* signal)
Uint64 now = NdbTick_CurrentMillisecond();
if((c_regReqReqRecv == cnoOfNodes) || now > c_stopElectionTime){
jam();
-
electionWon();
sendSttorryLab(signal);
@@ -1704,6 +1701,7 @@ void Qmgr::sendApiFailReq(Signal* signal, Uint16 failedNodeNo)
sendSignal(DBTC_REF, GSN_API_FAILREQ, signal, 2, JBA);
sendSignal(DBDICT_REF, GSN_API_FAILREQ, signal, 2, JBA);
sendSignal(SUMA_REF, GSN_API_FAILREQ, signal, 2, JBA);
+
/**
* GREP also need the information that an API node
* (actually a REP node) has failed.
@@ -1978,8 +1976,10 @@ void Qmgr::execAPI_REGREQ(Signal* signal)
apiRegConf->nodeState.dynamicId = -dynamicId;
}
}
+ apiRegConf->nodeState.m_connected_nodes.assign(c_connectedNodes);
+
sendSignal(ref, GSN_API_REGCONF, signal, ApiRegConf::SignalLength, JBB);
-
+
if ((getNodeState().startLevel == NodeState::SL_STARTED ||
getNodeState().getSingleUserMode())
&& apiNodePtr.p->phase == ZAPI_INACTIVE) {
@@ -2138,7 +2138,8 @@ void Qmgr::execPREP_FAILREQ(Signal* signal)
Uint16 TfailureNr = prepFail->failNo;
cnoPrepFailedNodes = prepFail->noOfNodes;
UintR arrayIndex = 0;
- for (Uint32 Tindex = 0; Tindex < MAX_NDB_NODES; Tindex++) {
+ Uint32 Tindex;
+ for (Tindex = 0; Tindex < MAX_NDB_NODES; Tindex++) {
if (NodeBitmask::get(prepFail->theNodes, Tindex)){
cprepFailedNodes[arrayIndex] = Tindex;
arrayIndex++;
@@ -2166,7 +2167,7 @@ void Qmgr::execPREP_FAILREQ(Signal* signal)
guard0 = cnoPrepFailedNodes - 1;
arrGuard(guard0, MAX_NDB_NODES);
- for (Uint32 Tindex = 0; Tindex <= guard0; Tindex++) {
+ for (Tindex = 0; Tindex <= guard0; Tindex++) {
jam();
failReport(signal,
cprepFailedNodes[Tindex],
@@ -2308,6 +2309,15 @@ void Qmgr::execPREP_FAILCONF(Signal* signal)
* Continues via sendCommitFailReq() if successful.
*/
arbitRec.failureNr = cfailureNr;
+ const NodeState & s = getNodeState();
+ if(s.startLevel == NodeState::SL_STOPPING_3 && s.stopping.systemShutdown){
+ jam();
+ /**
+ * We're performing a system shutdown,
+ * don't let artibtrator shut us down
+ */
+ return;
+ }
handleArbitCheck(signal);
return;
}//Qmgr::execPREP_FAILCONF()
diff --git a/ndb/src/kernel/blocks/suma/Suma.cpp b/ndb/src/kernel/blocks/suma/Suma.cpp
index 9718845de43..24e264291e7 100644
--- a/ndb/src/kernel/blocks/suma/Suma.cpp
+++ b/ndb/src/kernel/blocks/suma/Suma.cpp
@@ -267,6 +267,40 @@ Suma::execREAD_NODESCONF(Signal* signal){
sendSTTORRY(signal);
}
+#if 0
+void
+Suma::execREAD_CONFIG_REQ(Signal* signal)
+{
+ const ReadConfigReq * req = (ReadConfigReq*)signal->getDataPtr();
+ Uint32 ref = req->senderRef;
+ Uint32 senderData = req->senderData;
+ ndbrequire(req->noOfParameters == 0);
+
+ jamEntry();
+
+ const ndb_mgm_configuration_iterator * p =
+ theConfiguration.getOwnConfigIterator();
+ ndbrequire(p != 0);
+
+ ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_DB_NO_REDOLOG_FILES,
+ &cnoLogFiles));
+ ndbrequire(cnoLogFiles > 0);
+
+ ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_LQH_FRAG, &cfragrecFileSize));
+ ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_LQH_TABLE, &ctabrecFileSize));
+ ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_LQH_TC_CONNECT,
+ &ctcConnectrecFileSize));
+ clogFileFileSize = 4 * cnoLogFiles;
+ ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_LQH_SCAN, &cscanrecFileSize));
+ cmaxAccOps = cscanrecFileSize * MAX_PARALLEL_SCANS_PER_FRAG;
+
+ initRecords();
+ initialiseRecordsLab(signal, 0, ref, senderData);
+
+ return;
+}//Dblqh::execSIZEALT_REP()
+#endif
+
void
Suma::sendSTTORRY(Signal* signal){
signal->theData[0] = 0;
@@ -581,34 +615,33 @@ Suma::execDUMP_STATE_ORD(Signal* signal){
jamEntry();
Uint32 tCase = signal->theData[0];
- if(tCase < 8000 || tCase > 8004)
- return;
-
- SubscriptionPtr subPtr;
- c_subscriptions.getPtr(subPtr, g_subPtrI);
-
- Ptr<SyncRecord> syncPtr;
- c_syncPool.getPtr(syncPtr, subPtr.p->m_syncPtrI);
-
- if(tCase == 8000){
- syncPtr.p->startMeta(signal);
- }
-
- if(tCase == 8001){
- syncPtr.p->startScan(signal);
- }
-
- if(tCase == 8002){
- syncPtr.p->startTrigger(signal);
- }
+ if(tCase >= 8000 && tCase <= 8003){
+ SubscriptionPtr subPtr;
+ c_subscriptions.getPtr(subPtr, g_subPtrI);
+
+ Ptr<SyncRecord> syncPtr;
+ c_syncPool.getPtr(syncPtr, subPtr.p->m_syncPtrI);
+
+ if(tCase == 8000){
+ syncPtr.p->startMeta(signal);
+ }
+
+ if(tCase == 8001){
+ syncPtr.p->startScan(signal);
+ }
- if(tCase == 8003){
- subPtr.p->m_subscriptionType = SubCreateReq::SingleTableScan;
- LocalDataBuffer<15> attrs(c_dataBufferPool, syncPtr.p->m_attributeList);
- Uint32 tab = 0;
- Uint32 att[] = { 0, 1, 1 };
- syncPtr.p->m_tableList.append(&tab, 1);
- attrs.append(att, 3);
+ if(tCase == 8002){
+ syncPtr.p->startTrigger(signal);
+ }
+
+ if(tCase == 8003){
+ subPtr.p->m_subscriptionType = SubCreateReq::SingleTableScan;
+ LocalDataBuffer<15> attrs(c_dataBufferPool, syncPtr.p->m_attributeList);
+ Uint32 tab = 0;
+ Uint32 att[] = { 0, 1, 1 };
+ syncPtr.p->m_tableList.append(&tab, 1);
+ attrs.append(att, 3);
+ }
}
if(tCase == 8004){
@@ -1229,6 +1262,9 @@ SumaParticipant::parseTable(Signal* signal, GetTabInfoConf* conf, Uint32 tableId
if(!tabPtr.isNull() &&
tabPtr.p->m_schemaVersion != tableDesc.TableVersion){
jam();
+
+ tabPtr.p->release(* this);
+
// oops wrong schema version in stored tabledesc
// we need to find all subscriptions with old table desc
// and all subscribers to this
@@ -3972,3 +4008,6 @@ Suma::execSUMA_HANDOVER_CONF(Signal* signal) {
}
}
}
+
+template void append(DataBuffer<11>&,SegmentedSectionPtr,SectionSegmentPool&);
+
diff --git a/ndb/src/kernel/blocks/trix/Trix.cpp b/ndb/src/kernel/blocks/trix/Trix.cpp
index f058433840c..4088d55c76d 100644
--- a/ndb/src/kernel/blocks/trix/Trix.cpp
+++ b/ndb/src/kernel/blocks/trix/Trix.cpp
@@ -814,8 +814,8 @@ void Trix::executeInsertTransaction(Signal* signal,
for(Uint32 i = 0; i < headerPtr.sz; i++) {
AttributeHeader* keyAttrHead = (AttributeHeader *) headerBuffer + i;
- // Filter out single NULL attributes
- if (keyAttrHead->isNULL() && (i == (Uint32)0) && (headerPtr.sz == (Uint32)2))
+ // Filter out NULL attributes
+ if (keyAttrHead->isNULL())
return;
if (i < subRec->noOfIndexColumns)
@@ -965,3 +965,5 @@ void Trix::checkParallelism(Signal* signal, SubscriptionRecord* subRec)
}
BLOCK_FUNCTIONS(Trix);
+
+template void append(DataBuffer<15>&,SegmentedSectionPtr,SectionSegmentPool&);
diff --git a/ndb/src/kernel/error/ErrorReporter.cpp b/ndb/src/kernel/error/ErrorReporter.cpp
index 20a9dd8a993..f1320c44e09 100644
--- a/ndb/src/kernel/error/ErrorReporter.cpp
+++ b/ndb/src/kernel/error/ErrorReporter.cpp
@@ -27,6 +27,8 @@
#include <NdbConfig.h>
#include <Configuration.hpp>
+#include <NdbAutoPtr.hpp>
+
#define MESSAGE_LENGTH 400
const char* errorType[] = {
@@ -66,23 +68,23 @@ ErrorReporter::formatTimeStampString(){
return (const char *)&theDateTimeString;
}
-void
-ErrorReporter::formatTraceFileName(char* theName, int maxLen){
+int
+ErrorReporter::get_trace_no(){
FILE *stream;
unsigned int traceFileNo;
- char fileNameBuf[255];
- char buf[255];
+
+ char *file_name= NdbConfig_NextTraceFileName(globalData.ownId);
+ NdbAutoPtr<char> tmp_aptr(file_name);
- NdbConfig_HomePath(fileNameBuf, 255);
- strncat(fileNameBuf, "NextTraceFileNo.log", 255);
/*
* Read last number from tracefile
*/
- stream = fopen(fileNameBuf, "r+");
+ stream = fopen(file_name, "r+");
if (stream == NULL){
traceFileNo = 1;
} else {
+ char buf[255];
fgets(buf, 255, stream);
const int scan = sscanf(buf, "%u", &traceFileNo);
if(scan != 1){
@@ -103,16 +105,13 @@ ErrorReporter::formatTraceFileName(char* theName, int maxLen){
/**
* Save new number to the file
*/
- stream = fopen(fileNameBuf, "w");
+ stream = fopen(file_name, "w");
if(stream != NULL){
fprintf(stream, "%u", traceFileNo);
fclose(stream);
}
- /**
- * Format trace file name
- */
- snprintf(theName, maxLen, "%sNDB_TraceFile_%u.trace",
- NdbConfig_HomePath(fileNameBuf, 255), traceFileNo);
+
+ return traceFileNo;
}
@@ -214,16 +213,22 @@ WriteMessage(ErrorCategory thrdType, int thrdMessageID,
unsigned offset;
unsigned long maxOffset; // Maximum size of file.
char theMessage[MESSAGE_LENGTH];
- char theTraceFileName[255];
- char theErrorFileName[255];
- ErrorReporter::formatTraceFileName(theTraceFileName, 255);
+
+ /**
+ * Format trace file name
+ */
+ int file_no= ErrorReporter::get_trace_no();
+ char *theTraceFileName= NdbConfig_TraceFileName(globalData.ownId, file_no);
+ NdbAutoPtr<char> tmp_aptr1(theTraceFileName);
// The first 69 bytes is info about the current offset
Uint32 noMsg = globalEmulatorData.theConfiguration->maxNoOfErrorLogs();
maxOffset = (69 + (noMsg * MESSAGE_LENGTH));
- NdbConfig_ErrorFileName(theErrorFileName, 255);
+ char *theErrorFileName= (char *)NdbConfig_ErrorFileName(globalData.ownId);
+ NdbAutoPtr<char> tmp_aptr2(theErrorFileName);
+
stream = fopen(theErrorFileName, "r+");
if (stream == NULL) { /* If the file could not be opened. */
diff --git a/ndb/src/kernel/error/ErrorReporter.hpp b/ndb/src/kernel/error/ErrorReporter.hpp
index b43b30f1873..2c79f242eea 100644
--- a/ndb/src/kernel/error/ErrorReporter.hpp
+++ b/ndb/src/kernel/error/ErrorReporter.hpp
@@ -23,35 +23,6 @@
#include "Error.hpp"
#include <Emulator.hpp>
-
-#ifdef ASSERT
-#undef ASSERT
-#endif
-
-#define REQUIRE(trueToContinue, message) \
- if ( (trueToContinue) ) { } else { \
- ErrorReporter::handleAssert(message, __FILE__, __LINE__); }
-
-#define THREAD_REQUIRE(trueToContinue, message) \
- if ( (trueToContinue) ) { } else { \
- ErrorReporter::handleThreadAssert(message, __FILE__, __LINE__); }
-
-#ifdef NDEBUG
-#define NDB_ASSERT(trueToContinue, message)
-#else
-#define NDB_ASSERT(trueToContinue, message) \
- if ( !(trueToContinue) ) { \
- ErrorReporter::handleAssert(message, __FILE__, __LINE__); }
-#endif
-
- // Description:
- // This macro is used to report programming errors.
- // Parameters:
- // trueToContinue IN An expression. If it evaluates to 0
- // execution is stopped.
- // message IN A message from the programmer
- // explaining what went wrong.
-
class ErrorReporter
{
public:
@@ -81,7 +52,7 @@ public:
const char* theNameOfTheTraceFile,
char* messptr);
- static void formatTraceFileName(char* theName, int maxLen);
+ static int get_trace_no();
static const char* formatTimeStampString();
diff --git a/ndb/src/kernel/Main.cpp b/ndb/src/kernel/main.cpp
index 7bd4e75ca18..4d3a0afe6ed 100644
--- a/ndb/src/kernel/Main.cpp
+++ b/ndb/src/kernel/main.cpp
@@ -20,7 +20,7 @@
#include "Configuration.hpp"
#include <TransporterRegistry.hpp>
-#include "SimBlockList.hpp"
+#include "vm/SimBlockList.hpp"
#include "ThreadConfig.hpp"
#include <SignalLoggerManager.hpp>
#include <NdbOut.hpp>
@@ -31,20 +31,19 @@
#include <LogLevel.hpp>
#include <EventLogger.hpp>
-#include <NodeState.hpp>
+
+#include <NdbAutoPtr.hpp>
#if defined NDB_SOLARIS // ok
#include <sys/processor.h> // For system informatio
#endif
-#if !defined NDB_SOFTOSE && !defined NDB_OSE
-#include <signal.h> // For process signals
-#endif
-
extern EventLogger g_eventLogger;
void catchsigs(bool ignore); // for process signal handling
-extern "C" void handler(int signo); // for process signal handling
+
+extern "C" void handler_shutdown(int signum); // for process signal handling
+extern "C" void handler_error(int signum); // for process signal handling
// Shows system information
void systemInfo(const Configuration & conf,
@@ -68,18 +67,16 @@ NDB_MAIN(ndb_kernel){
}
{ // Do configuration
- theConfig->setupConfiguration();
+ signal(SIGPIPE, SIG_IGN);
+ theConfig->fetch_configuration();
}
-
- // Get NDB_HOME path
- char homePath[255];
- NdbConfig_HomePath(homePath, 255);
-
+
if (theConfig->getDaemonMode()) {
// Become a daemon
- char lockfile[255], logfile[255];
- snprintf(lockfile, 255, "%snode%d.pid", homePath, globalData.ownId);
- snprintf(logfile, 255, "%snode%d.out", homePath, globalData.ownId);
+ char *lockfile= NdbConfig_PidFileName(globalData.ownId);
+ char *logfile= NdbConfig_StdoutFileName(globalData.ownId);
+ NdbAutoPtr<char> tmp_aptr1(lockfile), tmp_aptr2(logfile);
+
if (NdbDaemon_Make(lockfile, logfile, 0) == -1) {
ndbout << "Cannot become daemon: " << NdbDaemon_ErrorText << endl;
return 1;
@@ -132,24 +129,26 @@ NDB_MAIN(ndb_kernel){
exit(0);
}
g_eventLogger.info("Ndb has terminated (pid %d) restarting", child);
+ theConfig->fetch_configuration();
}
g_eventLogger.info("Angel pid: %d ndb pid: %d", getppid(), getpid());
+ theConfig->setupConfiguration();
systemInfo(* theConfig, * theConfig->m_logLevel);
-
+
// Load blocks
globalEmulatorData.theSimBlockList->load(* theConfig);
// Set thread concurrency for Solaris' light weight processes
int status;
status = NdbThread_SetConcurrencyLevel(30);
- NDB_ASSERT(status == 0, "Can't set appropriate concurrency level.");
+ assert(status == 0);
#ifdef VM_TRACE
// Create a signal logger
- char buf[255];
- strcpy(buf, homePath);
- FILE * signalLog = fopen(strncat(buf,"Signal.log", 255), "a");
+ char *buf= NdbConfig_SignalLogFileName(globalData.ownId);
+ NdbAutoPtr<char> tmp_aptr(buf);
+ FILE * signalLog = fopen(buf, "a");
globalSignalLoggers.setOwnNodeId(globalData.ownId);
globalSignalLoggers.setOutputStream(signalLog);
#endif
@@ -168,16 +167,38 @@ NDB_MAIN(ndb_kernel){
globalEmulatorData.theThreadConfig->doStart(NodeState::SL_STARTING);
break;
default:
- NDB_ASSERT(0, "Illegal state globalData.theRestartFlag");
+ assert("Illegal state globalData.theRestartFlag" == 0);
}
+ SocketServer socket_server;
+
globalTransporterRegistry.startSending();
globalTransporterRegistry.startReceiving();
+ if (!globalTransporterRegistry.start_service(socket_server)){
+ ndbout_c("globalTransporterRegistry.start_service() failed");
+ exit(-1);
+ }
+
+ if (!globalTransporterRegistry.start_clients()){
+ ndbout_c("globalTransporterRegistry.start_clients() failed");
+ exit(-1);
+ }
+
globalEmulatorData.theWatchDog->doStart();
+ socket_server.startServer();
+
+ // theConfig->closeConfiguration();
+
globalEmulatorData.theThreadConfig->ipControlLoop();
NdbShutdown(NST_Normal);
+
+ socket_server.stopServer();
+ socket_server.stopSessions();
+
+ globalTransporterRegistry.stop_clients();
+
return NRT_Default;
}
@@ -229,74 +250,91 @@ systemInfo(const Configuration & config, const LogLevel & logLevel){
}
+#define handler_register(signum, handler, ignore)\
+{\
+ if (ignore) {\
+ if(signum != SIGCHLD)\
+ signal(signum, SIG_IGN);\
+ } else\
+ signal(signum, handler);\
+}
+
void
catchsigs(bool ignore){
#if ! defined NDB_SOFTOSE && !defined NDB_OSE
-#if defined SIGRTMIN
- #define MAX_SIG_CATCH SIGRTMIN
-#elif defined NSIG
- #define MAX_SIG_CATCH NSIG
-#else
- #error "neither SIGRTMIN or NSIG is defined on this platform, please report bug at bugs.mysql.com"
+ static const int signals_shutdown[] = {
+#ifdef SIGBREAK
+ SIGBREAK,
#endif
-
- // Makes the main process catch process signals, eg installs a
- // handler named "handler". "handler" will then be called is instead
- // of the defualt process signal handler)
- if(ignore){
- for(int i = 1; i < MAX_SIG_CATCH; i++){
- if(i != SIGCHLD)
- signal(i, SIG_IGN);
- }
- } else {
- for(int i = 1; i < MAX_SIG_CATCH; i++){
- signal(i, handler);
- }
- }
+ SIGHUP,
+ SIGINT,
+#if defined SIGPWR
+ SIGPWR,
+#elif defined SIGINFO
+ SIGINFO,
#endif
-}
-
-extern "C"
-void
-handler(int sig){
- switch(sig){
- case SIGHUP: /* 1 - Hang up */
- case SIGINT: /* 2 - Interrupt */
- case SIGQUIT: /* 3 - Quit */
- case SIGTERM: /* 15 - Terminate */
-#ifdef SIGPWR
- case SIGPWR: /* 19 - Power fail */
+ SIGQUIT,
+ SIGTERM,
+#ifdef SIGTSTP
+ SIGTSTP,
+#endif
+ SIGTTIN,
+ SIGTTOU
+ };
+
+ static const int signals_error[] = {
+ SIGABRT,
+ SIGALRM,
+#ifdef SIGBUS
+ SIGBUS,
+#endif
+ SIGCHLD,
+ SIGFPE,
+ SIGILL,
+#ifdef SIGIO
+ SIGIO,
#endif
#ifdef SIGPOLL
- case SIGPOLL: /* 22 */
+ SIGPOLL,
#endif
- case SIGSTOP: /* 23 */
- case SIGTSTP: /* 24 */
- case SIGTTIN: /* 26 */
- case SIGTTOU: /* 27 */
- globalData.theRestartFlag = perform_stop;
- break;
-#ifdef SIGWINCH
- case SIGWINCH:
+ SIGSEGV,
+#ifdef SIGTRAP
+ SIGTRAP
#endif
- case SIGPIPE:
- /**
- * Can happen in TCP Transporter
- *
- * Just ignore
- */
- break;
- default:
- // restart the system
- char errorData[40];
- snprintf(errorData, 40, "Signal %d received", sig);
- ERROR_SET(fatal, 0, errorData, __FILE__);
- break;
- }
+ };
+#endif
+
+ static const int signals_ignore[] = {
+ SIGPIPE
+ };
+
+ size_t i;
+ for(i = 0; i < sizeof(signals_shutdown)/sizeof(signals_shutdown[0]); i++)
+ handler_register(signals_shutdown[i], handler_shutdown, ignore);
+ for(i = 0; i < sizeof(signals_error)/sizeof(signals_error[0]); i++)
+ handler_register(signals_error[i], handler_error, ignore);
+ for(i = 0; i < sizeof(signals_ignore)/sizeof(signals_ignore[0]); i++)
+ handler_register(signals_ignore[i], SIG_IGN, ignore);
+}
+
+extern "C"
+void
+handler_shutdown(int signum){
+ g_eventLogger.info("Received signal %d. Performing stop.", signum);
+ globalData.theRestartFlag = perform_stop;
+}
+
+extern "C"
+void
+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);
+ ERROR_SET(fatal, 0, errorData, __FILE__);
}
-
diff --git a/ndb/src/kernel/vm/ArrayPool.hpp b/ndb/src/kernel/vm/ArrayPool.hpp
index 4fc6bb97f73..924ed51ee15 100644
--- a/ndb/src/kernel/vm/ArrayPool.hpp
+++ b/ndb/src/kernel/vm/ArrayPool.hpp
@@ -148,24 +148,6 @@ public:
void releaseList(Uint32 n, Uint32 first, Uint32 last);
//private:
- /**
- * Print
- * (Run operator NdbOut<< on every element)
- */
- void print(NdbOut & out){
- out << "FirstFree = " << firstFree << endl;
- for(Uint32 i = 0; i<size; i++){
-#ifdef ARRAY_GUARD
- if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i))
- out << "A ";
- else
- out << "F ";
-#endif
- out << i << ": " << theArray[i] << " ";
- }
- out << endl;
- }
-
#ifdef DEBUG
Uint32 getNoOfFree2() const {
Uint32 c2 = size;
diff --git a/ndb/src/kernel/vm/Configuration.cpp b/ndb/src/kernel/vm/Configuration.cpp
index c97ad951cf3..257b7a098e0 100644
--- a/ndb/src/kernel/vm/Configuration.cpp
+++ b/ndb/src/kernel/vm/Configuration.cpp
@@ -35,6 +35,7 @@
#include <ndb_limits.h>
#include "pc.hpp"
#include <LogLevel.hpp>
+#include <NdbSleep.h>
extern "C" {
void ndbSetOwnVersion();
@@ -49,7 +50,7 @@ Configuration::init(int argc, const char** argv){
/**
* Default values for arguments
*/
- int _start = 1;
+ int _no_start = 0;
int _initial = 0;
const char* _connect_str = NULL;
int _deamon = 0;
@@ -59,14 +60,18 @@ Configuration::init(int argc, const char** argv){
/**
* Arguments to NDB process
*/
- struct getargs args[] = {
- { "version", 'v', arg_flag, &_print_version, "Print version", "" },
- { "start", 's', arg_flag, &_start, "Start ndb immediately", "" },
- { "nostart", 'n', arg_negative_flag, &_start, "Don't start ndb immediately", "" },
- { "deamon", 'd', arg_flag, &_deamon, "Start ndb as deamon", "" },
- { "initial", 'i', arg_flag, &_initial, "Start ndb immediately", "" },
- { "connect-string", 'c', arg_string, &_connect_str, "\"nodeid=<id>;host=<hostname:port>\"\n", "constr" },
+ struct getargs args[] = {
+ { "version", 'v', arg_flag, &_print_version, "Print ndbd version", "" },
+ { "nostart", 'n', arg_flag, &_no_start,
+ "Don't start ndbd immediately. Ndbd will await command from ndb_mgmd", "" },
+ { "daemon", 'd', arg_flag, &_deamon, "Start ndbd as daemon", "" },
+ { "initial", 'i', arg_flag, &_initial,
+ "Perform initial start of ndbd, including cleaning the file system. Consult documentation before using this", "" },
+
+ { "connect-string", 'c', arg_string, &_connect_str,
+ "Set connect string for connecting to ndb_mgmd. <constr>=\"host=<hostname:port>[;nodeid=<id>]\". Overides specifying entries in NDB_CONNECTSTRING and config file",
+ "<constr>" },
{ "usage", '?', arg_flag, &_help, "Print help", "" }
};
int num_args = sizeof(args) / sizeof(args[0]);
@@ -80,7 +85,7 @@ Configuration::init(int argc, const char** argv){
}
#if 0
- ndbout << "start=" <<_start<< endl;
+ ndbout << "no_start=" <<_no_start<< endl;
ndbout << "initial=" <<_initial<< endl;
ndbout << "deamon=" <<_deamon<< endl;
ndbout << "connect_str="<<_connect_str<<endl;
@@ -96,27 +101,18 @@ Configuration::init(int argc, const char** argv){
}
// Check the start flag
- if (_start)
- globalData.theRestartFlag = perform_start;
- else
+ if (_no_start)
globalData.theRestartFlag = initial_state;
+ else
+ globalData.theRestartFlag = perform_start;
// Check the initial flag
if (_initial)
_initialStart = true;
// Check connectstring
- if (_connect_str){
-
- if(_connect_str[0] == '-' ||
- strstr(_connect_str, "host") == 0 ||
- strstr(_connect_str, "nodeid") == 0) {
- ndbout << "Illegal/empty connectString: " << _connect_str << endl;
- arg_printusage(args, num_args, argv[0], desc);
- return false;
- }
+ if (_connect_str)
_connectString = strdup(_connect_str);
- }
// Check deamon flag
if (_deamon)
@@ -138,6 +134,7 @@ Configuration::Configuration()
_fsPath = 0;
_initialStart = false;
_daemonMode = false;
+ m_config_retriever= 0;
}
Configuration::~Configuration(){
@@ -146,37 +143,97 @@ Configuration::~Configuration(){
if(_fsPath != NULL)
free(_fsPath);
+
+ if (m_config_retriever) {
+ delete m_config_retriever;
+ }
}
void
-Configuration::setupConfiguration(){
+Configuration::closeConfiguration(){
+ if (m_config_retriever) {
+ delete m_config_retriever;
+ }
+ m_config_retriever= 0;
+}
+
+void
+Configuration::fetch_configuration(){
/**
* Fetch configuration from management server
*/
- ConfigRetriever cr;
- cr.setConnectString(_connectString);
- stopOnError(true);
- ndb_mgm_configuration * p = cr.getConfig(NDB_VERSION, NODE_TYPE_DB);
+ if (m_config_retriever) {
+ delete m_config_retriever;
+ }
+
+ m_config_retriever= new ConfigRetriever(NDB_VERSION, NODE_TYPE_DB);
+ m_config_retriever->setConnectString(_connectString ? _connectString : "");
+ if(m_config_retriever->init() == -1 ||
+ m_config_retriever->do_connect() == -1){
+
+ const char * s = m_config_retriever->getErrorString();
+ if(s == 0)
+ s = "No error given!";
+
+ /* 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);
+ }
+
+ ConfigRetriever &cr= *m_config_retriever;
+
+ if((globalData.ownId = cr.allocNodeId()) == 0){
+ for(Uint32 i = 0; i<3; i++){
+ NdbSleep_SecSleep(3);
+ if(globalData.ownId = cr.allocNodeId())
+ break;
+ }
+ }
+
+ if(globalData.ownId == 0){
+ ERROR_SET(fatal, ERR_INVALID_CONFIG,
+ "Unable to alloc node id", m_config_retriever->getErrorString());
+ }
+
+ ndb_mgm_configuration * p = cr.getConfig();
if(p == 0){
const char * s = cr.getErrorString();
if(s == 0)
s = "No error given!";
-
+
/* Set stop on error to true otherwise NDB will
go into an restart loop...
- */
-
+ */
+
ERROR_SET(fatal, ERR_INVALID_CONFIG, "Could not fetch configuration"
"/invalid configuration", s);
}
+ if(m_clusterConfig)
+ free(m_clusterConfig);
+
+ m_clusterConfig = p;
+
+ ndb_mgm_configuration_iterator iter(* p, CFG_SECTION_NODE);
+ if (iter.find(CFG_NODE_ID, globalData.ownId)){
+ ERROR_SET(fatal, ERR_INVALID_CONFIG, "Invalid configuration fetched", "DB missing");
+ }
+
+ if(iter.get(CFG_DB_STOP_ON_ERROR, &_stopOnError)){
+ ERROR_SET(fatal, ERR_INVALID_CONFIG, "Invalid configuration fetched",
+ "StopOnError missing");
+ }
+}
- Uint32 nodeId = globalData.ownId = cr.getOwnNodeId();
+void
+Configuration::setupConfiguration(){
+ ndb_mgm_configuration * p = m_clusterConfig;
/**
* Configure transporters
*/
{
- int res = IPCConfig::configureTransporters(nodeId,
+ int res = IPCConfig::configureTransporters(globalData.ownId,
* p,
globalTransporterRegistry);
if(res <= 0){
@@ -238,11 +295,6 @@ Configuration::setupConfiguration(){
}
}
- if(iter.get(CFG_DB_STOP_ON_ERROR, &_stopOnError)){
- ERROR_SET(fatal, ERR_INVALID_CONFIG, "Invalid configuration fetched",
- "StopOnError missing");
- }
-
if(iter.get(CFG_DB_STOP_ON_ERROR_INSERT, &m_restartOnErrorInsert)){
ERROR_SET(fatal, ERR_INVALID_CONFIG, "Invalid configuration fetched",
"RestartOnErrorInsert missing");
@@ -259,7 +311,6 @@ Configuration::setupConfiguration(){
ConfigValues* cf = ConfigValuesFactory::extractCurrentSection(iter.m_config);
- m_clusterConfig = p;
m_clusterConfigIter = ndb_mgm_create_configuration_iterator
(p, CFG_SECTION_NODE);
@@ -501,7 +552,7 @@ Configuration::calcSizeAlt(ConfigValues * ownConfig){
// The remainder are allowed for use by the scan processes.
/*-----------------------------------------------------------------------*/
cfg.put(CFG_ACC_OP_RECS,
- noOfReplicas*((16 * noOfOperations) / 10 + 50) +
+ ((11 * noOfOperations) / 10 + 50) +
(noOfLocalScanRecords * MAX_PARALLEL_SCANS_PER_FRAG) +
NODE_RECOVERY_SCAN_OP_RECORDS);
@@ -526,18 +577,9 @@ Configuration::calcSizeAlt(ConfigValues * ownConfig){
*/
cfg.put(CFG_DICT_ATTRIBUTE,
noOfAttributes);
-
- cfg.put(CFG_DICT_CONNECT,
- noOfOperations + 32);
-
- cfg.put(CFG_DICT_FRAG_CONNECT,
- NO_OF_FRAG_PER_NODE * noOfDBNodes * noOfReplicas);
cfg.put(CFG_DICT_TABLE,
noOfTables);
-
- cfg.put(CFG_DICT_TC_CONNECT,
- 2* noOfOperations);
}
{
@@ -548,7 +590,7 @@ Configuration::calcSizeAlt(ConfigValues * ownConfig){
2 * noOfTransactions);
cfg.put(CFG_DIH_CONNECT,
- noOfOperations + 46);
+ noOfOperations + noOfTransactions + 46);
cfg.put(CFG_DIH_FRAG_CONNECT,
NO_OF_FRAG_PER_NODE * noOfTables * noOfDBNodes);
@@ -578,18 +620,12 @@ Configuration::calcSizeAlt(ConfigValues * ownConfig){
cfg.put(CFG_LQH_FRAG,
NO_OF_FRAG_PER_NODE * noOfTables * noOfReplicas);
- cfg.put(CFG_LQH_CONNECT,
- noOfReplicas*((11 * noOfOperations) / 10 + 50));
-
cfg.put(CFG_LQH_TABLE,
noOfTables);
cfg.put(CFG_LQH_TC_CONNECT,
- noOfReplicas*((16 * noOfOperations) / 10 + 50));
+ (11 * noOfOperations) / 10 + 50);
- cfg.put(CFG_LQH_REPLICAS,
- noOfReplicas);
-
cfg.put(CFG_LQH_SCAN,
noOfLocalScanRecords);
}
@@ -602,7 +638,7 @@ Configuration::calcSizeAlt(ConfigValues * ownConfig){
3 * noOfTransactions);
cfg.put(CFG_TC_TC_CONNECT,
- noOfOperations + 16 + noOfTransactions);
+ (2 * noOfOperations) + 16 + noOfTransactions);
cfg.put(CFG_TC_TABLE,
noOfTables);
@@ -622,7 +658,7 @@ Configuration::calcSizeAlt(ConfigValues * ownConfig){
2 * NO_OF_FRAG_PER_NODE * noOfTables* noOfReplicas);
cfg.put(CFG_TUP_OP_RECS,
- noOfReplicas*((16 * noOfOperations) / 10 + 50));
+ (11 * noOfOperations) / 10 + 50);
cfg.put(CFG_TUP_PAGE,
noOfDataPages);
diff --git a/ndb/src/kernel/vm/Configuration.hpp b/ndb/src/kernel/vm/Configuration.hpp
index 1706ad05867..bd91f3fa74b 100644
--- a/ndb/src/kernel/vm/Configuration.hpp
+++ b/ndb/src/kernel/vm/Configuration.hpp
@@ -20,6 +20,8 @@
#include <mgmapi.h>
#include <ndb_types.h>
+class ConfigRetriever;
+
class Configuration {
public:
Configuration();
@@ -30,7 +32,9 @@ public:
*/
bool init(int argc, const char** argv);
+ void fetch_configuration();
void setupConfiguration();
+ void closeConfiguration();
bool lockPagesInMainMemory() const;
@@ -78,6 +82,8 @@ private:
ndb_mgm_configuration_iterator * m_clusterConfigIter;
ndb_mgm_configuration_iterator * m_ownConfigIterator;
+ ConfigRetriever *m_config_retriever;
+
/**
* arguments to NDB process
*/
diff --git a/ndb/src/kernel/vm/DataBuffer.hpp b/ndb/src/kernel/vm/DataBuffer.hpp
index 7dc89aa638c..7f553898eb5 100644
--- a/ndb/src/kernel/vm/DataBuffer.hpp
+++ b/ndb/src/kernel/vm/DataBuffer.hpp
@@ -33,7 +33,7 @@ public:
Uint32 data[sz];
NdbOut& print(NdbOut& out){
out << "[DataBuffer<" << sz << ">::Segment this="
- << hex << (Uint32)this << dec << " nextPool= "
+ << this << dec << " nextPool= "
<< nextPool << " ]";
return out;
}
diff --git a/ndb/src/kernel/vm/Emulator.cpp b/ndb/src/kernel/vm/Emulator.cpp
index 07998794d01..75aea2bda7f 100644
--- a/ndb/src/kernel/vm/Emulator.cpp
+++ b/ndb/src/kernel/vm/Emulator.cpp
@@ -35,8 +35,6 @@
#include <NdbSleep.h>
#include <new>
-#include <signal.h> // For process signals
-
extern "C" {
extern void (* ndb_new_handler)();
}
@@ -202,7 +200,7 @@ NdbShutdown(NdbShutdownType type,
if(type != NST_Normal && type != NST_Restart){
ndbout << "Error handler shutdown completed - " << exitAbort << endl;
-#if defined VM_TRACE && ( ! ( defined NDB_OSE || defined NDB_SOFTOSE) )
+#if ( defined VM_TRACE || defined ERROR_INSERT ) && ( ! ( defined NDB_OSE || defined NDB_SOFTOSE) )
signal(6, SIG_DFL);
abort();
#else
diff --git a/ndb/src/kernel/vm/MetaData.cpp b/ndb/src/kernel/vm/MetaData.cpp
index bcde6c63272..51afbf21503 100644
--- a/ndb/src/kernel/vm/MetaData.cpp
+++ b/ndb/src/kernel/vm/MetaData.cpp
@@ -47,7 +47,7 @@ MetaData::MetaData(SimulatedBlock* block) :
MetaData::~MetaData()
{
for (int i = false; i <= true; i++) {
- NDB_ASSERT(m_common.m_lock[i] >= m_lock[i], "invalid lock count");
+ assert(m_common.m_lock[i] >= m_lock[i]);
m_common.m_lock[i] -= m_lock[i];
m_lock[i] = 0;
}
diff --git a/ndb/src/kernel/vm/SimulatedBlock.cpp b/ndb/src/kernel/vm/SimulatedBlock.cpp
index a6a8a6242cd..18b7f474ddc 100644
--- a/ndb/src/kernel/vm/SimulatedBlock.cpp
+++ b/ndb/src/kernel/vm/SimulatedBlock.cpp
@@ -104,6 +104,11 @@ SimulatedBlock::SimulatedBlock(BlockNumber blockNumber,
UpgradeStartup::installEXEC(this);
CLEAR_ERROR_INSERT_VALUE;
+
+#ifdef VM_TRACE
+ m_global_variables = new Ptr<void> * [1];
+ m_global_variables[0] = 0;
+#endif
}
SimulatedBlock::~SimulatedBlock()
@@ -112,6 +117,10 @@ SimulatedBlock::~SimulatedBlock()
#ifdef VM_TRACE_TIME
printTimes(stdout);
#endif
+
+#ifdef VM_TRACE
+ delete [] m_global_variables;
+#endif
}
void
@@ -136,12 +145,12 @@ SimulatedBlock::installSimulatedBlockFunctions(){
void
SimulatedBlock::addRecSignalImpl(GlobalSignalNumber gsn,
ExecFunction f, bool force){
- REQUIRE(gsn <= MAX_GSN, "Illegal signal added in block (GSN too high)");
- char probData[255];
- snprintf(probData, 255,
- "Signal (%d) already added in block",
- gsn);
- REQUIRE(force || theExecArray[gsn] == 0, probData);
+ if(gsn > MAX_GSN || (!force && theExecArray[gsn] != 0)){
+ char errorMsg[255];
+ snprintf(errorMsg, 255,
+ "Illeagal signal (%d %d)", gsn, MAX_GSN);
+ ERROR_SET(fatal, ERR_ERROR_PRGERR, errorMsg, errorMsg);
+ }
theExecArray[gsn] = f;
}
@@ -636,12 +645,12 @@ SimulatedBlock::getBatSize(Uint16 blockNo){
}
void*
-SimulatedBlock::allocRecord(const char * type, size_t s, size_t n) const
+SimulatedBlock::allocRecord(const char * type, size_t s, size_t n, bool clear)
{
- void* p = NULL;
+ void * p = NULL;
size_t size = n*s;
-
+ refresh_watch_dog();
if (size > 0){
#ifdef VM_TRACE_MEM
ndbout_c("%s::allocRecord(%s, %u, %u) = %u bytes",
@@ -656,43 +665,31 @@ SimulatedBlock::allocRecord(const char * type, size_t s, size_t n) const
char buf1[255];
char buf2[255];
snprintf(buf1, sizeof(buf1), "%s could not allocate memory for %s",
- getBlockName(number()), type);
- snprintf(buf2, sizeof(buf2), "Requested: %ux%u = %u bytes", (Uint32)s, (Uint32)n, (Uint32)size);
+ getBlockName(number()), type);
+ snprintf(buf2, sizeof(buf2), "Requested: %ux%u = %u bytes",
+ (Uint32)s, (Uint32)n, (Uint32)size);
ERROR_SET(fatal, ERR_MEMALLOC, buf1, buf2);
}
-
-
- // Set the allocated memory to zero
-#ifndef NDB_PURIFY
-#if defined NDB_OSE
- int pages = (size / 4096);
- if ((size % 4096)!=0)
- pages++;
-
- char* p2 =(char*) p;
- for (int i = 0; i < pages; i++){
- memset(p2, 0, 4096);
- p2 = p2 + 4096;
+
+ if(clear){
+ char * ptr = (char*)p;
+ const Uint32 chunk = 128 * 1024;
+ while(size > chunk){
+ refresh_watch_dog();
+ memset(ptr, 0, chunk);
+ ptr += chunk;
+ size -= chunk;
+ }
+ refresh_watch_dog();
+ memset(ptr, 0, size);
}
-#elif 1
- /**
- * This code should be enabled in order to find logical errors and not
- * initalised errors in the kernel.
- *
- * NOTE! It's not just "uninitialised errors" that are found by doing this
- * it will also find logical errors that have been hidden by all the zeros.
- */
-
- memset(p, 0xF1, size);
-#endif
-#endif
}
return p;
}
void
SimulatedBlock::deallocRecord(void ** ptr,
- const char * type, size_t s, size_t n) const {
+ const char * type, size_t s, size_t n){
(void)type;
(void)s;
(void)n;
@@ -704,6 +701,12 @@ SimulatedBlock::deallocRecord(void ** ptr,
}
void
+SimulatedBlock::refresh_watch_dog()
+{
+ globalData.incrementWatchDogCounter(1);
+}
+
+void
SimulatedBlock::progError(int line, int err_code, const char* extra) const {
jamLine(line);
@@ -1005,7 +1008,8 @@ SimulatedBlock::assembleFragments(Signal * signal){
/**
* FragInfo == 2 or 3
*/
- for(Uint32 i = 0; i<secs; i++){
+ Uint32 i;
+ for(i = 0; i<secs; i++){
Uint32 sectionNo = secNos[i];
ndbassert(sectionNo < 3);
Uint32 sectionPtrI = signal->m_sectionPtr[i].i;
@@ -1027,7 +1031,6 @@ SimulatedBlock::assembleFragments(Signal * signal){
/**
* fragInfo = 3
*/
- Uint32 i;
for(i = 0; i<3; i++){
Uint32 ptrI = fragPtr.p->m_sectionPtrI[i];
if(ptrI != RNIL){
@@ -1777,3 +1780,25 @@ SimulatedBlock::execUPGRADE(Signal* signal){
break;
}
}
+
+#ifdef VM_TRACE
+void
+SimulatedBlock::clear_global_variables(){
+ Ptr<void> ** tmp = m_global_variables;
+ while(* tmp != 0){
+ (* tmp)->i = RNIL;
+ (* tmp)->p = 0;
+ tmp++;
+ }
+}
+
+void
+SimulatedBlock::init_globals_list(void ** tmp, size_t cnt){
+ m_global_variables = new Ptr<void> * [cnt+1];
+ for(size_t i = 0; i<cnt; i++){
+ m_global_variables[i] = (Ptr<void>*)tmp[i];
+ }
+ m_global_variables[cnt] = 0;
+}
+
+#endif
diff --git a/ndb/src/kernel/vm/SimulatedBlock.hpp b/ndb/src/kernel/vm/SimulatedBlock.hpp
index 491d432625e..6d46e9cc377 100644
--- a/ndb/src/kernel/vm/SimulatedBlock.hpp
+++ b/ndb/src/kernel/vm/SimulatedBlock.hpp
@@ -96,7 +96,7 @@ protected:
* Handling of execFunctions
*/
typedef void (SimulatedBlock::* ExecFunction)(Signal* signal);
- void addRecSignalImpl(GlobalSignalNumber g, ExecFunction fun, bool f = false);
+ void addRecSignalImpl(GlobalSignalNumber g, ExecFunction fun, bool f =false);
void installSimulatedBlockFunctions();
ExecFunction theExecArray[MAX_GSN+1];
public:
@@ -304,7 +304,13 @@ protected:
BlockNumber number() const;
BlockReference reference() const;
NodeId getOwnNodeId() const;
-
+
+ /**
+ * Refresh Watch Dog in initialising code
+ *
+ */
+ void refresh_watch_dog();
+
/**
* Prog error
* This function should be called when this node should be shutdown
@@ -344,14 +350,14 @@ protected:
* Allocates memory for the datastructures where ndb keeps the data
*
*/
- void* allocRecord(const char * type, size_t s, size_t n) const ;
+ void* allocRecord(const char * type, size_t s, size_t n, bool clear = true);
/**
* Deallocate record
*
* NOTE: Also resets pointer
*/
- void deallocRecord(void **, const char * type, size_t s, size_t n) const ;
+ void deallocRecord(void **, const char * type, size_t s, size_t n);
/**
* General info event (sent to cluster log)
@@ -441,6 +447,12 @@ public:
} m_timeTrace[MAX_GSN+1];
Uint32 m_currentGsn;
#endif
+
+#ifdef VM_TRACE
+ Ptr<void> **m_global_variables;
+ void clear_global_variables();
+ void init_globals_list(void ** tmp, size_t cnt);
+#endif
};
inline
@@ -448,6 +460,9 @@ void
SimulatedBlock::executeFunction(GlobalSignalNumber gsn, Signal* signal){
ExecFunction f = theExecArray[gsn];
if(gsn <= MAX_GSN && f != 0){
+#ifdef VM_TRACE
+ clear_global_variables();
+#endif
(this->*f)(signal);
return;
}
@@ -458,11 +473,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);
- REQUIRE(false, errorMsg);
+ ERROR_SET(fatal, ERR_ERROR_PRGERR, errorMsg, errorMsg);
}
if (!(theExecArray[gsn] != 0)) {
snprintf(errorMsg, 255, "Illegal signal received (GSN %d not added)", gsn);
- REQUIRE(false, errorMsg);
+ ERROR_SET(fatal, ERR_ERROR_PRGERR, errorMsg, errorMsg);
}
ndbrequire(false);
}
@@ -673,6 +688,5 @@ BLOCK::addRecSignal(GlobalSignalNumber gsn, ExecSignalLocal f, bool force){ \
addRecSignalImpl(gsn, (ExecFunction)f, force);\
}
-
#endif
diff --git a/ndb/src/kernel/vm/ThreadConfig.cpp b/ndb/src/kernel/vm/ThreadConfig.cpp
index d18b20a5bb5..4844bb9a477 100644
--- a/ndb/src/kernel/vm/ThreadConfig.cpp
+++ b/ndb/src/kernel/vm/ThreadConfig.cpp
@@ -147,8 +147,8 @@ void ThreadConfig::ipControlLoop()
// plus checking for any received messages.
//--------------------------------------------------------------------
if (i++ >= 20) {
+ globalTransporterRegistry.update_connections();
globalData.incrementWatchDogCounter(5);
- globalTransporterRegistry.checkConnections();
i = 0;
}//if
diff --git a/ndb/src/kernel/vm/TransporterCallback.cpp b/ndb/src/kernel/vm/TransporterCallback.cpp
index eb7d138895c..158de64c87f 100644
--- a/ndb/src/kernel/vm/TransporterCallback.cpp
+++ b/ndb/src/kernel/vm/TransporterCallback.cpp
@@ -434,5 +434,28 @@ reportDisconnect(void * callbackObj, NodeId nodeId, Uint32 errNo){
globalScheduler.execute(&signal, JBA, CMVMI, GSN_DISCONNECT_REP);
}
-
+void
+SignalLoggerManager::printSegmentedSection(FILE * output,
+ const SignalHeader & sh,
+ const SegmentedSectionPtr ptr[3],
+ unsigned i)
+{
+ fprintf(output, "SECTION %u type=segmented", i);
+ if (i >= 3) {
+ fprintf(output, " *** invalid ***\n");
+ return;
+ }
+ const Uint32 len = ptr[i].sz;
+ SectionSegment * ssp = ptr[i].p;
+ Uint32 pos = 0;
+ fprintf(output, " size=%u\n", (unsigned)len);
+ while (pos < len) {
+ if (pos > 0 && pos % SectionSegment::DataLength == 0) {
+ ssp = g_sectionSegmentPool.getPtr(ssp->m_nextSegment);
+ }
+ printDataWord(output, pos, ssp->theData[pos % SectionSegment::DataLength]);
+ }
+ if (len > 0)
+ putc('\n', output);
+}
diff --git a/ndb/src/mgmapi/Makefile.am b/ndb/src/mgmapi/Makefile.am
index e4fa1d449c6..0f0e1cea5d8 100644
--- a/ndb/src/mgmapi/Makefile.am
+++ b/ndb/src/mgmapi/Makefile.am
@@ -9,5 +9,7 @@ DEFS_LOC = -DNO_DEBUG_MESSAGES
include $(top_srcdir)/ndb/config/common.mk.am
include $(top_srcdir)/ndb/config/type_util.mk.am
+#ndbtest_PROGRAMS = ndb_test_mgmapi
+
# Don't update the files from bitkeeper
%::SCCS/s.%
diff --git a/ndb/src/mgmapi/mgmapi.cpp b/ndb/src/mgmapi/mgmapi.cpp
index bb4b6be8221..e78b0d41cf2 100644
--- a/ndb/src/mgmapi/mgmapi.cpp
+++ b/ndb/src/mgmapi/mgmapi.cpp
@@ -24,6 +24,7 @@
#include <NdbOut.hpp>
#include <SocketServer.hpp>
+#include <SocketClient.hpp>
#include <Parser.hpp>
#include <OutputStream.hpp>
#include <InputStream.hpp>
@@ -63,7 +64,7 @@
0, \
0, 0 }
-class ParserDummy : SocketServer::Session
+class ParserDummy : private SocketServer::Session
{
public:
ParserDummy(NDB_SOCKET_TYPE sock);
@@ -282,6 +283,7 @@ ndb_mgm_call(NdbMgmHandle handle, const ParserRow<ParserDummy> *command_reply,
while((name = iter.next()) != NULL) {
PropertiesType t;
Uint32 val_i;
+ Uint64 val_64;
BaseString val_s;
cmd_args->getTypeOf(name, &t);
@@ -290,11 +292,15 @@ ndb_mgm_call(NdbMgmHandle handle, const ParserRow<ParserDummy> *command_reply,
cmd_args->get(name, &val_i);
out.println("%s: %d", name, val_i);
break;
+ case PropertiesType_Uint64:
+ cmd_args->get(name, &val_64);
+ out.println("%s: %Ld", name, val_64);
+ break;
case PropertiesType_char:
cmd_args->get(name, val_s);
out.println("%s: %s", name, val_s.c_str());
break;
- default:
+ case PropertiesType_Properties:
/* Ignore */
break;
}
@@ -318,8 +324,8 @@ ndb_mgm_call(NdbMgmHandle handle, const ParserRow<ParserDummy> *command_reply,
/**
* Print some info about why the parser returns NULL
*/
-// ndbout << " status=" << ctx.m_status << ", curr="
-// << ctx.m_currentToken << endl;
+ //ndbout << " status=" << ctx.m_status << ", curr="
+ //<< ctx.m_currentToken << endl;
}
#ifdef MGMAPI_LOG
else {
@@ -362,30 +368,11 @@ ndb_mgm_connect(NdbMgmHandle handle, const char * mgmsrv)
/**
* Do connect
*/
- const NDB_SOCKET_TYPE sockfd = socket(AF_INET, SOCK_STREAM, 0);
- if (sockfd == NDB_INVALID_SOCKET) {
- SET_ERROR(handle, NDB_MGM_ILLEGAL_SOCKET, "");
- return -1;
- }
-
- struct sockaddr_in servaddr;
- memset(&servaddr, 0, sizeof(servaddr));
- servaddr.sin_family = AF_INET;
- servaddr.sin_port = htons(handle->port);
- // Convert ip address presentation format to numeric format
- const int res1 = Ndb_getInAddr(&servaddr.sin_addr, handle->hostname);
- if (res1 != 0) {
- DEBUG("Ndb_getInAddr(...) == -1");
- setError(handle, EINVAL, __LINE__, "Invalid hostname/address");
- return -1;
- }
-
- const int res2 = connect(sockfd, (struct sockaddr*) &servaddr,
- sizeof(servaddr));
- if (res2 == -1) {
- NDB_CLOSE_SOCKET(sockfd);
- setError(handle, NDB_MGM_COULD_NOT_CONNECT_TO_SOCKET, __LINE__, "Unable to connect to %s",
- mgmsrv);
+ SocketClient s(handle->hostname, handle->port);
+ const NDB_SOCKET_TYPE sockfd = s.connect();
+ if (sockfd < 0) {
+ setError(handle, NDB_MGM_COULD_NOT_CONNECT_TO_SOCKET, __LINE__,
+ "Unable to connect to %s", mgmsrv);
return -1;
}
@@ -491,11 +478,12 @@ extern "C"
const char *
ndb_mgm_get_node_status_string(enum ndb_mgm_node_status status)
{
- for(int i = 0; i<no_of_status_values; i++)
+ int i;
+ for(i = 0; i<no_of_status_values; i++)
if(status_values[i].value == status)
return status_values[i].str;
- for(int i = 0; i<no_of_status_values; i++)
+ for(i = 0; i<no_of_status_values; i++)
if(status_values[i].value == NDB_MGM_NODE_STATUS_UNKNOWN)
return status_values[i].str;
@@ -562,7 +550,7 @@ ndb_mgm_get_status(NdbMgmHandle handle)
buf[strlen(buf)-1] = '\0';
if(strcmp("node status", buf) != 0) {
- SET_ERROR(handle, NDB_MGM_ILLEGAL_NODE_STATUS, "");
+ SET_ERROR(handle, NDB_MGM_ILLEGAL_NODE_STATUS, buf);
return NULL;
}
@@ -1450,11 +1438,7 @@ ndb_mgm_get_configuration(NdbMgmHandle handle, unsigned int version) {
const Properties *prop;
prop = ndb_mgm_call(handle, reply, "get config", &args);
-
- if(prop == NULL) {
- SET_ERROR(handle, EIO, "Unable to fetch config");
- return 0;
- }
+ CHECK_REPLY(prop, 0);
do {
const char * buf;
@@ -1515,7 +1499,8 @@ ndb_mgm_get_configuration(NdbMgmHandle handle, unsigned int version) {
ndbout_c("Failed to unpack buffer");
break;
}
-
+
+ delete prop;
return (ndb_mgm_configuration*)cvf.m_cfg;
} while(0);
@@ -1523,6 +1508,52 @@ ndb_mgm_get_configuration(NdbMgmHandle handle, unsigned int version) {
return 0;
}
+extern "C"
+int
+ndb_mgm_alloc_nodeid(NdbMgmHandle handle, unsigned int version, unsigned *pnodeid, int nodetype)
+{
+
+ CHECK_HANDLE(handle, 0);
+ CHECK_CONNECTED(handle, 0);
+
+ Properties args;
+ args.put("version", version);
+ args.put("nodetype", nodetype);
+ args.put("nodeid", *pnodeid);
+ args.put("user", "mysqld");
+ args.put("password", "mysqld");
+ args.put("public key", "a public key");
+
+ const ParserRow<ParserDummy> reply[]= {
+ MGM_CMD("get nodeid reply", NULL, ""),
+ MGM_ARG("nodeid", Int, Optional, "Error message"),
+ MGM_ARG("result", String, Mandatory, "Error message"),
+ MGM_END()
+ };
+
+ const Properties *prop;
+ prop= ndb_mgm_call(handle, reply, "get nodeid", &args);
+ CHECK_REPLY(prop, -1);
+
+ int res= -1;
+ do {
+ const char * buf;
+ if(!prop->get("result", &buf) || strcmp(buf, "Ok") != 0){
+ setError(handle, NDB_MGM_COULD_NOT_CONNECT_TO_SOCKET, __LINE__,
+ "Could not alloc node id: %s",buf);
+ break;
+ }
+ if(!prop->get("nodeid", pnodeid) != 0){
+ ndbout_c("ERROR Message: <nodeid Unspecified>\n");
+ break;
+ }
+ res= 0;
+ }while(0);
+
+ delete prop;
+ return res;
+}
+
/*****************************************************************************
* Global Replication
******************************************************************************/
@@ -1559,3 +1590,130 @@ ndb_mgm_rep_command(NdbMgmHandle handle, unsigned int request,
delete reply;
return 0;
}
+
+extern "C"
+int
+ndb_mgm_set_int_parameter(NdbMgmHandle handle,
+ int node,
+ int param,
+ unsigned value,
+ struct ndb_mgm_reply*){
+ CHECK_HANDLE(handle, 0);
+ CHECK_CONNECTED(handle, 0);
+
+ Properties args;
+ args.put("node: ", node);
+ args.put("param: ", param);
+ args.put("value: ", value);
+
+ const ParserRow<ParserDummy> reply[]= {
+ MGM_CMD("set parameter reply", NULL, ""),
+ MGM_ARG("result", String, Mandatory, "Error message"),
+ MGM_END()
+ };
+
+ const Properties *prop;
+ prop= ndb_mgm_call(handle, reply, "set parameter", &args);
+ CHECK_REPLY(prop, -1);
+
+ int res= -1;
+ do {
+ const char * buf;
+ if(!prop->get("result", &buf) || strcmp(buf, "Ok") != 0){
+ ndbout_c("ERROR Message: %s\n", buf);
+ break;
+ }
+ res= 0;
+ } while(0);
+
+ delete prop;
+ return res;
+}
+
+extern "C"
+int
+ndb_mgm_set_int64_parameter(NdbMgmHandle handle,
+ int node,
+ int param,
+ unsigned long long value,
+ struct ndb_mgm_reply*){
+ CHECK_HANDLE(handle, 0);
+ CHECK_CONNECTED(handle, 0);
+
+ Properties args;
+ args.put("node: ", node);
+ args.put("param: ", param);
+ args.put("value: ", value);
+
+ const ParserRow<ParserDummy> reply[]= {
+ MGM_CMD("set parameter reply", NULL, ""),
+ MGM_ARG("result", String, Mandatory, "Error message"),
+ MGM_END()
+ };
+
+ const Properties *prop;
+ prop= ndb_mgm_call(handle, reply, "set parameter", &args);
+
+ if(prop == NULL) {
+ SET_ERROR(handle, EIO, "Unable set parameter");
+ return -1;
+ }
+
+ int res= -1;
+ do {
+ const char * buf;
+ if(!prop->get("result", &buf) || strcmp(buf, "Ok") != 0){
+ ndbout_c("ERROR Message: %s\n", buf);
+ break;
+ }
+ res= 0;
+ } while(0);
+
+ delete prop;
+ return res;
+}
+
+extern "C"
+int
+ndb_mgm_set_string_parameter(NdbMgmHandle handle,
+ int node,
+ int param,
+ const char * value,
+ struct ndb_mgm_reply*){
+ CHECK_HANDLE(handle, 0);
+ CHECK_CONNECTED(handle, 0);
+
+ Properties args;
+ args.put("node: ", node);
+ args.put("parameter: ", param);
+ args.put("value: ", value);
+
+ const ParserRow<ParserDummy> reply[]= {
+ MGM_CMD("set parameter reply", NULL, ""),
+ MGM_ARG("result", String, Mandatory, "Error message"),
+ MGM_END()
+ };
+
+ const Properties *prop;
+ prop= ndb_mgm_call(handle, reply, "set parameter", &args);
+
+ if(prop == NULL) {
+ SET_ERROR(handle, EIO, "Unable set parameter");
+ return -1;
+ }
+
+ int res= -1;
+ do {
+ const char * buf;
+ if(!prop->get("result", &buf) || strcmp(buf, "Ok") != 0){
+ ndbout_c("ERROR Message: %s\n", buf);
+ break;
+ }
+ res= 0;
+ } while(0);
+
+ delete prop;
+ return res;
+}
+
+template class Vector<const ParserRow<ParserDummy>*>;
diff --git a/ndb/src/mgmclient/CommandInterpreter.cpp b/ndb/src/mgmclient/CommandInterpreter.cpp
index cf9d885847a..141a0be0eff 100644
--- a/ndb/src/mgmclient/CommandInterpreter.cpp
+++ b/ndb/src/mgmclient/CommandInterpreter.cpp
@@ -634,7 +634,8 @@ CommandInterpreter::executeHelp(char* parameters)
void
CommandInterpreter::executeShow(char* parameters)
-{
+{
+ int i;
connect();
if (emptyString(parameters)) {
ndbout << "Cluster Configuration" << endl
@@ -648,16 +649,27 @@ CommandInterpreter::executeShow(char* parameters)
}
int
- ndb_nodes = 0,
- api_nodes = 0,
- mgm_nodes = 0;
-
- for(int i=0; i < state->no_of_nodes; i++) {
+ master_id= 0,
+ ndb_nodes= 0,
+ api_nodes= 0,
+ mgm_nodes= 0;
+
+ for(i=0; i < state->no_of_nodes; i++) {
+ if(state->node_states[i].node_type == NDB_MGM_NODE_TYPE_NDB &&
+ state->node_states[i].version != 0){
+ master_id= state->node_states[i].dynamic_id;
+ break;
+ }
+ }
+
+ for(i=0; i < state->no_of_nodes; i++) {
switch(state->node_states[i].node_type) {
case NDB_MGM_NODE_TYPE_API:
api_nodes++;
break;
case NDB_MGM_NODE_TYPE_NDB:
+ if (state->node_states[i].dynamic_id < master_id)
+ master_id= state->node_states[i].dynamic_id;
ndb_nodes++;
break;
case NDB_MGM_NODE_TYPE_MGM:
@@ -673,15 +685,18 @@ CommandInterpreter::executeShow(char* parameters)
<< " NDB Node(s)"
<< endl;
- for(int i=0; i < state->no_of_nodes; i++) {
+ for(i=0; i < state->no_of_nodes; i++) {
if(state->node_states[i].node_type == NDB_MGM_NODE_TYPE_NDB) {
ndbout << "DB node:\t" << state->node_states[i].node_id;
if(state->node_states[i].version != 0) {
ndbout << " (Version: "
<< getMajor(state->node_states[i].version) << "."
<< getMinor(state->node_states[i].version) << "."
- << getBuild(state->node_states[i].version) << ")" << endl;
-
+ << getBuild(state->node_states[i].version) << ","
+ << " Nodegroup: " << state->node_states[i].node_group;
+ if (state->node_states[i].dynamic_id == master_id)
+ ndbout << ", Master";
+ ndbout << ")" << endl;
} else
{
ndbout << " (not connected) " << endl;
@@ -691,13 +706,13 @@ CommandInterpreter::executeShow(char* parameters)
}
ndbout << endl;
- ndbout << api_nodes
- << " API Node(s)"
+ ndbout << mgm_nodes
+ << " MGM Node(s)"
<< endl;
- for(int i=0; i < state->no_of_nodes; i++) {
- if(state->node_states[i].node_type == NDB_MGM_NODE_TYPE_API) {
- ndbout << "API node:\t" << state->node_states[i].node_id;
+ for(i=0; i < state->no_of_nodes; i++) {
+ if(state->node_states[i].node_type == NDB_MGM_NODE_TYPE_MGM) {
+ ndbout << "MGM node:\t" << state->node_states[i].node_id;
if(state->node_states[i].version != 0) {
ndbout << " (Version: "
<< getMajor(state->node_states[i].version) << "."
@@ -706,19 +721,19 @@ CommandInterpreter::executeShow(char* parameters)
} else
{
- ndbout << " (not connected) " << endl;
+ ndbout << " (no version information available) " << endl;
}
}
}
ndbout << endl;
-
- ndbout << mgm_nodes
- << " MGM Node(s)"
+
+ ndbout << api_nodes
+ << " API Node(s)"
<< endl;
- for(int i=0; i < state->no_of_nodes; i++) {
- if(state->node_states[i].node_type == NDB_MGM_NODE_TYPE_MGM) {
- ndbout << "MGM node:\t" << state->node_states[i].node_id;
+ for(i=0; i < state->no_of_nodes; i++) {
+ if(state->node_states[i].node_type == NDB_MGM_NODE_TYPE_API) {
+ ndbout << "API node:\t" << state->node_states[i].node_id;
if(state->node_states[i].version != 0) {
ndbout << " (Version: "
<< getMajor(state->node_states[i].version) << "."
@@ -727,11 +742,12 @@ CommandInterpreter::executeShow(char* parameters)
} else
{
- ndbout << " (no version information available) " << endl;
+ ndbout << " (not connected) " << endl;
}
}
}
ndbout << endl;
+
// ndbout << helpTextShow;
return;
} else if (strcmp(parameters, "PROPERTIES") == 0 ||
@@ -759,6 +775,7 @@ CommandInterpreter::executeShow(char* parameters)
void
CommandInterpreter::executeClusterLog(char* parameters)
{
+ int i;
connect();
if (parameters != 0 && strlen(parameters) != 0) {
enum ndb_mgm_clusterlog_level severity = NDB_MGM_CLUSTERLOG_ALL;
@@ -846,10 +863,10 @@ CommandInterpreter::executeClusterLog(char* parameters)
ndbout << "Cluster logging is disabled." << endl;
- for(int i = 0; i<7;i++)
+ for(i = 0; i<7;i++)
printf("enabled[%d] = %d\n", i, enabled[i]);
ndbout << "Severities enabled: ";
- for(int i = 1; i < 7; i++) {
+ for(i = 1; i < 7; i++) {
if(enabled[i])
ndbout << names[i] << " ";
}
@@ -1298,14 +1315,15 @@ CommandInterpreter::executeLog(int processId,
return;
}
int len=0;
- for(Uint32 i=0; i<blocks.size(); i++) {
+ Uint32 i;
+ for(i=0; i<blocks.size(); i++) {
ndbout_c("blocks %s %d",blocks[i], strlen(blocks[i]));
len += strlen(blocks[i]);
}
len += blocks.size()*2;
char * blockNames = (char*)malloc(len);
- for(Uint32 i=0; i<blocks.size(); i++) {
+ for(i=0; i<blocks.size(); i++) {
strcat(blockNames, blocks[i]);
strcat(blockNames, "|");
}
@@ -1478,7 +1496,7 @@ CommandInterpreter::executeSet(int /*processId*/,
<< endl;
}
else {
- NDB_ASSERT(false, "");
+ assert(false);
}
}
else {
@@ -1497,7 +1515,7 @@ CommandInterpreter::executeSet(int /*processId*/,
}
else {
// The primary is not tried to write if the write of backup file fails
- NDB_ASSERT(false, "");
+ abort();
}
}
free(newpar);
@@ -2020,3 +2038,5 @@ CmdBackupCallback(const MgmtSrvr::BackupEvent & event){
ndbout << str << endl;
}
#endif
+
+template class Vector<char const*>;
diff --git a/ndb/src/mgmclient/CpcClient.cpp b/ndb/src/mgmclient/CpcClient.cpp
index 74fa1a828ed..0291573a704 100644
--- a/ndb/src/mgmclient/CpcClient.cpp
+++ b/ndb/src/mgmclient/CpcClient.cpp
@@ -478,9 +478,9 @@ SimpleCpcClient::connect() {
if (::connect(cpc_sock, (struct sockaddr*) &sa, sizeof(sa)) < 0)
return -1;
- cpc_in = new SocketInputStream(cpc_sock);
+ cpc_in = new SocketInputStream(cpc_sock, 60000);
cpc_out = new SocketOutputStream(cpc_sock);
-
+
return 0;
}
@@ -557,4 +557,6 @@ SimpleCpcClient::cpc_call(const char *cmd,
SimpleCpcClient::ParserDummy::ParserDummy(NDB_SOCKET_TYPE sock)
: SocketServer::Session(sock) {
}
-
+
+template class Vector<SimpleCpcClient::Process>;
+template class Vector<ParserRow<SimpleCpcClient::ParserDummy> const*>;
diff --git a/ndb/src/mgmclient/main.cpp b/ndb/src/mgmclient/main.cpp
index 2dcadf9369d..df6659df0b1 100644
--- a/ndb/src/mgmclient/main.cpp
+++ b/ndb/src/mgmclient/main.cpp
@@ -24,9 +24,7 @@
#include "CommandInterpreter.hpp"
-#include <signal.h>
-
-const char *progname = "mgmtclient";
+const char *progname = "ndb_mgm";
static CommandInterpreter* com;
@@ -47,14 +45,13 @@ handler(int sig){
int main(int argc, const char** argv){
int optind = 0;
- const char *_default_connectstring = "host=localhost:2200;nodeid=0";
const char *_host = 0;
int _port = 0;
int _help = 0;
int _try_reconnect = 0;
struct getargs args[] = {
- { "try-reconnect", 0, arg_integer, &_try_reconnect, "", "" },
+ { "try-reconnect", 't', arg_integer, &_try_reconnect, "Specify number of retries for connecting to ndb_mgmd, default infinite", "#" },
{ "usage", '?', arg_flag, &_help, "Print help", "" },
};
int num_args = sizeof(args) / sizeof(args[0]); /* Number of arguments */
@@ -76,9 +73,9 @@ int main(int argc, const char** argv){
_port = atoi(argv[1]);
}
} else {
- if(cfg.init(false, 0, 0, _default_connectstring) && cfg.items > 0 && cfg.ids[0]->type == MgmId_TCP){
- _host = cfg.ids[0]->data.tcp.remoteHost;
- _port = cfg.ids[0]->data.tcp.port;
+ if(cfg.init(0, 0) && cfg.ids.size() > 0 && cfg.ids[0].type == MgmId_TCP){
+ _host = cfg.ids[0].name.c_str();
+ _port = cfg.ids[0].port;
} else {
cfg.printError();
cfg.printUsage();
diff --git a/ndb/src/mgmsrv/CommandInterpreter.cpp b/ndb/src/mgmsrv/CommandInterpreter.cpp
index 004fc463b70..316b6d5795e 100644
--- a/ndb/src/mgmsrv/CommandInterpreter.cpp
+++ b/ndb/src/mgmsrv/CommandInterpreter.cpp
@@ -378,7 +378,8 @@ void CommandInterpreter::executeHelp(char* parameters) {
(void)parameters; // Don't want compiler warning
if (emptyString(parameters)) {
- for (int i = 0; i<noOfHelpTexts; i++) {
+ unsigned i;
+ for (i = 0; i<noOfHelpTexts; i++) {
ndbout << helpTexts[i] << endl;
}
@@ -388,7 +389,7 @@ void CommandInterpreter::executeHelp(char* parameters) {
<< endl;
ndbout << "<category> = ";
- for(Uint32 i = 0; i<EventLogger::noOfEventCategoryNames; i++){
+ for(i = 0; i<EventLogger::noOfEventCategoryNames; i++){
ndbout << EventLogger::eventCategoryNames[i].name;
if (i < EventLogger::noOfEventCategoryNames - 1) {
ndbout << " | ";
@@ -1195,11 +1196,12 @@ CommandInterpreter::jonas(int processId, const char* parameters, bool all) {
data[0] = 12;
data[1] = 13;
-
- for(Uint32 i = 0; i<70; i++)
+
+ unsigned i;
+ for(i = 0; i<70; i++)
sec0[i] = i;
- for(Uint32 i = 0; i<123; i++)
+ for(i = 0; i<123; i++)
sec1[i] = 70+i;
signal.set(0, CMVMI, GSN_TESTSIG, 3);
diff --git a/ndb/src/mgmsrv/MgmtSrvr.cpp b/ndb/src/mgmsrv/MgmtSrvr.cpp
index 713433cb8e9..0936ec234cf 100644
--- a/ndb/src/mgmsrv/MgmtSrvr.cpp
+++ b/ndb/src/mgmsrv/MgmtSrvr.cpp
@@ -43,10 +43,12 @@
#include <DebuggerNames.hpp>
#include <ndb_version.h>
-#include "SocketServer.hpp"
+#include <SocketServer.hpp>
#include "NodeLogLevel.hpp"
#include <NdbConfig.h>
+#include <NdbAutoPtr.hpp>
+
#include <mgmapi.h>
#include <mgmapi_configuration.hpp>
#include <mgmapi_config_parameters.h>
@@ -170,7 +172,7 @@ MgmtSrvr::signalRecvThreadRun()
siglist.push_back(SigMatch(GSN_MGM_UNLOCK_CONFIG_REQ,
&MgmtSrvr::handle_MGM_UNLOCK_CONFIG_REQ));
- while(1) {
+ while(!_isStopThread) {
SigMatch *handler = NULL;
NdbApiSignal *signal = NULL;
if(m_signalRecvQueue.waitFor(siglist, handler, signal)) {
@@ -240,23 +242,20 @@ MgmtSrvr::startEventLog()
const char * tmp;
BaseString logdest;
- char clusterLog[MAXPATHLEN];
- NdbConfig_ClusterLogFileName(clusterLog, sizeof(clusterLog));
-
-
+ char *clusterLog= NdbConfig_ClusterLogFileName(_ownNodeId);
+ NdbAutoPtr<char> tmp_aptr(clusterLog);
+
if(ndb_mgm_get_string_parameter(iter, CFG_LOG_DESTINATION, &tmp) == 0){
logdest.assign(tmp);
}
ndb_mgm_destroy_iterator(iter);
- if(logdest.length()==0) {
+ if(logdest.length() == 0 || logdest == "") {
logdest.assfmt("FILE:filename=%s,maxsize=1000000,maxfiles=6",
clusterLog);
}
-
if(!g_EventLogger.addHandler(logdest)) {
- ndbout << "ERROR: cannot parse \"" << logdest << "\"" << endl;
- exit(1);
+ ndbout << "Warning: could not add log destination \"" << logdest.c_str() << "\"" << endl;
}
}
@@ -391,6 +390,99 @@ MgmtSrvr::getNodeCount(enum ndb_mgm_node_type type) const
}
int
+MgmtSrvr::getPort() const {
+ const Properties *mgmProps;
+
+ ndb_mgm_configuration_iterator * iter =
+ ndb_mgm_create_configuration_iterator(_config->m_configValues,
+ CFG_SECTION_NODE);
+ if(iter == 0)
+ return 0;
+
+ if(ndb_mgm_find(iter, CFG_NODE_ID, getOwnNodeId()) != 0){
+ ndbout << "Could not retrieve configuration for Node "
+ << getOwnNodeId() << " in config file." << endl
+ << "Have you set correct NodeId for this node?" << endl;
+ ndb_mgm_destroy_iterator(iter);
+ return 0;
+ }
+
+ unsigned type;
+ if(ndb_mgm_get_int_parameter(iter, CFG_TYPE_OF_SECTION, &type) != 0 ||
+ type != NODE_TYPE_MGM){
+ ndbout << "Local node id " << getOwnNodeId()
+ << " is not defined as management server" << endl
+ << "Have you set correct NodeId for this node?" << endl;
+ ndb_mgm_destroy_iterator(iter);
+ return 0;
+ }
+
+ Uint32 port = 0;
+ if(ndb_mgm_get_int_parameter(iter, CFG_MGM_PORT, &port) != 0){
+ ndbout << "Could not find PortNumber in the configuration file." << endl;
+ ndb_mgm_destroy_iterator(iter);
+ return 0;
+ }
+
+ ndb_mgm_destroy_iterator(iter);
+
+ /*****************
+ * Set Stat Port *
+ *****************/
+#if 0
+ if (!mgmProps->get("PortNumberStats", &tmp)){
+ ndbout << "Could not find PortNumberStats in the configuration file."
+ << endl;
+ return false;
+ }
+ glob.port_stats = tmp;
+#endif
+
+#if 0
+ const char * host;
+ if(ndb_mgm_get_string_parameter(iter, mgmProps->get("ExecuteOnComputer", host)){
+ ndbout << "Failed to find \"ExecuteOnComputer\" for my node" << endl;
+ ndbout << "Unable to verify own hostname" << endl;
+ return false;
+ }
+
+ const char * hostname;
+ {
+ const Properties * p;
+ char buf[255];
+ snprintf(buf, sizeof(buf), "Computer_%s", host.c_str());
+ if(!glob.cluster_config->get(buf, &p)){
+ ndbout << "Failed to find computer " << host << " in config" << endl;
+ ndbout << "Unable to verify own hostname" << endl;
+ return false;
+ }
+ if(!p->get("HostName", &hostname)){
+ ndbout << "Failed to find \"HostName\" for computer " << host
+ << " in config" << endl;
+ ndbout << "Unable to verify own hostname" << endl;
+ return false;
+ }
+ if(NdbHost_GetHostName(buf) != 0){
+ ndbout << "Unable to get own hostname" << endl;
+ ndbout << "Unable to verify own hostname" << endl;
+ return false;
+ }
+ }
+
+ const char * ip_address;
+ if(mgmProps->get("IpAddress", &ip_address)){
+ glob.use_specific_ip = true;
+ glob.interface_name = strdup(ip_address);
+ return true;
+ }
+
+ glob.interface_name = strdup(hostname);
+#endif
+
+ return port;
+}
+
+int
MgmtSrvr::getStatPort() const {
#if 0
const Properties *mgmProps;
@@ -417,9 +509,9 @@ MgmtSrvr::MgmtSrvr(NodeId nodeId,
_ownReference(0),
theSignalIdleList(NULL),
theWaitState(WAIT_SUBSCRIBE_CONF),
- theConfCount(0) {
+ theConfCount(0),
+ m_allocated_resources(*this) {
- _ownNodeId = nodeId;
_config = NULL;
_isStatPortActive = false;
_isClusterLogStatActive = false;
@@ -427,8 +519,11 @@ MgmtSrvr::MgmtSrvr(NodeId nodeId,
_isStopThread = false;
_logLevelThread = NULL;
_logLevelThreadSleep = 500;
+ m_signalRecvThread = NULL;
_startedNodeId = 0;
+ theFacade = 0;
+
m_newConfig = NULL;
m_configFilename = configFilename;
setCallback(CmdBackupCallback);
@@ -486,6 +581,14 @@ MgmtSrvr::MgmtSrvr(NodeId nodeId,
_clusterLogLevelList = new NodeLogLevelList();
_props = NULL;
+
+ _ownNodeId= 0;
+ NodeId tmp= nodeId;
+ if (!alloc_node_id(&tmp, NDB_MGM_NODE_TYPE_MGM, 0, 0)){
+ ndbout << "Unable to obtain requested nodeid " << nodeId;
+ exit(-1);
+ }
+ _ownNodeId = tmp;
}
@@ -510,8 +613,7 @@ MgmtSrvr::start()
return false;
}
theFacade = TransporterFacade::start_instance
- (_ownNodeId,
- (ndb_mgm_configuration*)_config->m_configValues);
+ (_ownNodeId,(ndb_mgm_configuration*)_config->m_configValues);
if(theFacade == 0) {
DEBUG("MgmtSrvr.cpp: theFacade is NULL.");
@@ -573,8 +675,7 @@ MgmtSrvr::~MgmtSrvr()
stopEventLog();
- NdbCondition_Destroy(theMgmtWaitForResponseCondPtr);
- NdbMutex_Destroy(m_configMutex);
+ NdbCondition_Destroy(theMgmtWaitForResponseCondPtr); NdbMutex_Destroy(m_configMutex);
if(m_newConfig != NULL)
free(m_newConfig);
@@ -593,6 +694,11 @@ MgmtSrvr::~MgmtSrvr()
NdbThread_WaitFor(_logLevelThread, &res);
NdbThread_Destroy(&_logLevelThread);
}
+
+ if (m_signalRecvThread != NULL) {
+ NdbThread_WaitFor(m_signalRecvThread, &res);
+ NdbThread_Destroy(&m_signalRecvThread);
+ }
}
//****************************************************************************
@@ -818,7 +924,7 @@ MgmtSrvr::restart(bool nostart, bool initalStart, bool abort,
return 0;
}
- TransporterFacade::instance()->lock_mutex();
+ theFacade->lock_mutex();
int waitTime = timeOut/m_stopRec.sentCount;
if (receiveOptimisedResponse(waitTime) != 0) {
m_stopRec.inUse = false;
@@ -985,16 +1091,15 @@ MgmtSrvr::version(int * stopCount, bool abort,
m_versionRec.callback = callback;
m_versionRec.inUse = true ;
-
- for(Uint32 i = 0; i<MAX_NODES; i++) {
+ Uint32 i;
+ for(i = 0; i<MAX_NODES; i++) {
if (getNodeType(i) == NDB_MGM_NODE_TYPE_MGM) {
m_versionRec.callback(i, NDB_VERSION, this,0);
}
}
- for(Uint32 i = 0; i<MAX_NODES; i++) {
+ for(i = 0; i<MAX_NODES; i++) {
if (getNodeType(i) == NDB_MGM_NODE_TYPE_NDB) {
- node =
- TransporterFacade::instance()->theClusterMgr->getNodeInfo(i);
+ node = theFacade->theClusterMgr->getNodeInfo(i);
version = node.m_info.m_version;
if(theFacade->theClusterMgr->getNodeInfo(i).connected)
m_versionRec.callback(i, version, this,0);
@@ -1003,7 +1108,7 @@ MgmtSrvr::version(int * stopCount, bool abort,
}
}
- for(Uint32 i = 0; i<MAX_NODES; i++) {
+ for(i = 0; i<MAX_NODES; i++) {
if (getNodeType(i) == NDB_MGM_NODE_TYPE_API) {
return sendVersionReq(i);
}
@@ -1148,7 +1253,7 @@ MgmtSrvr::stop(int * stopCount, bool abort, StopCallback callback,
if(m_stopRec.sentCount > 0){
if(callback == 0){
- TransporterFacade::instance()->lock_mutex();
+ theFacade->lock_mutex();
receiveOptimisedResponse(timeOut / m_stopRec.sentCount);
} else {
return 0;
@@ -1178,7 +1283,7 @@ MgmtSrvr::enterSingleUser(int * stopCount, Uint32 singleUserNodeId,
for(Uint32 i = 0; i<MAX_NODES; i++) {
if (getNodeType(i) == NDB_MGM_NODE_TYPE_NDB) {
- node = TransporterFacade::instance()->theClusterMgr->getNodeInfo(i);
+ node = theFacade->theClusterMgr->getNodeInfo(i);
if((node.m_state.startLevel != NodeState::SL_STARTED) &&
(node.m_state.startLevel != NodeState::SL_NOTHING)) {
return 5063;
@@ -1337,7 +1442,7 @@ MgmtSrvr::status(int processId,
}
const ClusterMgr::Node node =
- TransporterFacade::instance()->theClusterMgr->getNodeInfo(processId);
+ theFacade->theClusterMgr->getNodeInfo(processId);
if(!node.connected){
* _status = NDB_MGM_NODE_STATUS_NO_CONTACT;
@@ -1463,7 +1568,8 @@ MgmtSrvr::setEventReportingLevelImpl(int processId,
const SetLogLevelOrd & ll,
bool isResend)
{
- for(Uint32 i = 0; i<ll.noOfEntries; i++){
+ Uint32 i;
+ for(i = 0; i<ll.noOfEntries; i++){
// Save log level for the cluster log
if (!isResend) {
NodeLogLevel* n = NULL;
@@ -1494,7 +1600,7 @@ MgmtSrvr::setEventReportingLevelImpl(int processId,
EventSubscribeReq * dst =
CAST_PTR(EventSubscribeReq, signal->getDataPtrSend());
- for(Uint32 i = 0; i<ll.noOfEntries; i++){
+ for(i = 0; i<ll.noOfEntries; i++){
dst->theCategories[i] = ll.theCategories[i];
dst->theLevels[i] = ll.theLevels[i];
}
@@ -1523,7 +1629,8 @@ int
MgmtSrvr::setNodeLogLevel(int processId, const SetLogLevelOrd & ll,
bool isResend)
{
- for(Uint32 i = 0; i<ll.noOfEntries; i++){
+ Uint32 i;
+ for(i = 0; i<ll.noOfEntries; i++){
// Save log level for the cluster log
if (!isResend) {
NodeLogLevel* n = NULL;
@@ -1554,7 +1661,7 @@ MgmtSrvr::setNodeLogLevel(int processId, const SetLogLevelOrd & ll,
SetLogLevelOrd * dst = CAST_PTR(SetLogLevelOrd, signal->getDataPtrSend());
- for(Uint32 i = 0; i<ll.noOfEntries; i++){
+ for(i = 0; i<ll.noOfEntries; i++){
dst->theCategories[i] = ll.theCategories[i];
dst->theLevels[i] = ll.theLevels[i];
}
@@ -1698,7 +1805,7 @@ MgmtSrvr::setSignalLoggingMode(int processId, LogMode mode,
logSpec = TestOrd::InputOutputSignals;
break;
default:
- NDB_ASSERT(false, "Unexpected value, MgmtSrvr::setSignalLoggingMode");
+ assert("Unexpected value, MgmtSrvr::setSignalLoggingMode" == 0);
}
NdbApiSignal* signal = getSignal();
@@ -1896,6 +2003,7 @@ MgmtSrvr::handleReceivedSignal(NdbApiSignal* signal)
int returnCode;
int gsn = signal->readSignalNumber();
+
switch (gsn) {
case GSN_API_VERSION_CONF: {
if (theWaitState == WAIT_VERSION) {
@@ -2000,8 +2108,7 @@ MgmtSrvr::handleReceivedSignal(NdbApiSignal* signal)
req->senderData = 19;
req->backupDataLen = 0;
- int i = TransporterFacade::instance()->sendSignalUnCond(&aSignal,
- aNodeId);
+ int i = theFacade->sendSignalUnCond(&aSignal, aNodeId);
if(i == 0){
return;
}
@@ -2083,7 +2190,7 @@ MgmtSrvr::handleStopReply(NodeId nodeId, Uint32 errCode)
bool failure = true;
for(Uint32 i = 0; i<MAX_NODES; i++) {
if (getNodeType(i) == NDB_MGM_NODE_TYPE_NDB) {
- node = TransporterFacade::instance()->theClusterMgr->getNodeInfo(i);
+ node = theFacade->theClusterMgr->getNodeInfo(i);
if((node.m_state.startLevel == NodeState::SL_NOTHING))
failure = true;
else
@@ -2187,6 +2294,89 @@ MgmtSrvr::getNodeType(NodeId nodeId) const
return nodeTypes[nodeId];
}
+#ifdef NDB_WIN32
+static NdbMutex & f_node_id_mutex = * NdbMutex_Create();
+#else
+static NdbMutex f_node_id_mutex = NDB_MUTEX_INITIALIZER;
+#endif
+
+bool
+MgmtSrvr::alloc_node_id(NodeId * nodeId,
+ enum ndb_mgm_node_type type,
+ struct sockaddr *client_addr,
+ SOCKET_SIZE_TYPE *client_addr_len)
+{
+ Guard g(&f_node_id_mutex);
+#if 0
+ ndbout << "MgmtSrvr::getFreeNodeId type=" << type
+ << " *nodeid=" << *nodeId << endl;
+#endif
+
+ NodeBitmask connected_nodes(m_reserved_nodes);
+ if (theFacade && theFacade->theClusterMgr) {
+ for(Uint32 i = 0; i < MAX_NODES; i++)
+ if (getNodeType(i) == NDB_MGM_NODE_TYPE_NDB) {
+ const ClusterMgr::Node &node= theFacade->theClusterMgr->getNodeInfo(i);
+ if (node.connected)
+ connected_nodes.bitOR(node.m_state.m_connected_nodes);
+ }
+ }
+
+ ndb_mgm_configuration_iterator iter(*(ndb_mgm_configuration *)_config->m_configValues,
+ CFG_SECTION_NODE);
+ for(iter.first(); iter.valid(); iter.next()) {
+ unsigned tmp= 0;
+ if(iter.get(CFG_NODE_ID, &tmp)) abort();
+ if (connected_nodes.get(tmp))
+ continue;
+ if (*nodeId && *nodeId != tmp)
+ continue;
+ unsigned type_c;
+ if(iter.get(CFG_TYPE_OF_SECTION, &type_c)) abort();
+ if(type_c != type)
+ continue;
+ const char *config_hostname = 0;
+ if(iter.get(CFG_NODE_HOST, &config_hostname)) abort();
+
+ if (config_hostname && config_hostname[0] != 0 && client_addr) {
+ // check hostname compatability
+ struct in_addr config_addr;
+ const void *tmp= &(((sockaddr_in*)client_addr)->sin_addr);
+ if(Ndb_getInAddr(&config_addr, config_hostname) != 0
+ || memcmp(&config_addr, tmp, sizeof(config_addr)) != 0) {
+ struct in_addr tmp_addr;
+ if(Ndb_getInAddr(&tmp_addr, "localhost") != 0
+ || memcmp(&tmp_addr, tmp, sizeof(config_addr)) != 0) {
+ // not localhost
+#if 0
+ ndbout << "MgmtSrvr::getFreeNodeId compare failed for \"" << config_hostname
+ << "\" id=" << tmp << endl;
+#endif
+ continue;
+ }
+ // connecting through localhost
+ // check if config_hostname match hostname
+ char my_hostname[256];
+ if (gethostname(my_hostname, sizeof(my_hostname)) != 0)
+ continue;
+ if(Ndb_getInAddr(&tmp_addr, my_hostname) != 0
+ || memcmp(&tmp_addr, &config_addr, sizeof(config_addr)) != 0) {
+ // no match
+ continue;
+ }
+ }
+ }
+ *nodeId= tmp;
+ m_reserved_nodes.set(tmp);
+#if 0
+ ndbout << "MgmtSrvr::getFreeNodeId found type=" << type
+ << " *nodeid=" << *nodeId << endl;
+#endif
+ return true;
+ }
+ return false;
+}
+
bool
MgmtSrvr::getNextNodeId(NodeId * nodeId, enum ndb_mgm_node_type type) const
{
@@ -2573,3 +2763,128 @@ MgmtSrvr::getPrimaryNode() const {
return 0;
#endif
}
+
+
+MgmtSrvr::Allocated_resources::Allocated_resources(MgmtSrvr &m)
+ : m_mgmsrv(m)
+{
+}
+
+MgmtSrvr::Allocated_resources::~Allocated_resources()
+{
+ Guard g(&f_node_id_mutex);
+ m_mgmsrv.m_reserved_nodes.bitANDC(m_reserved_nodes);
+}
+
+void
+MgmtSrvr::Allocated_resources::reserve_node(NodeId id)
+{
+ m_reserved_nodes.set(id);
+}
+
+int
+MgmtSrvr::setDbParameter(int node, int param, const char * value,
+ BaseString& msg){
+ /**
+ * Check parameter
+ */
+ ndb_mgm_configuration_iterator iter(* _config->m_configValues,
+ CFG_SECTION_NODE);
+ if(iter.first() != 0){
+ msg.assign("Unable to find node section (iter.first())");
+ return -1;
+ }
+
+ Uint32 type = NODE_TYPE_DB + 1;
+ if(node != 0){
+ if(iter.find(CFG_NODE_ID, node) != 0){
+ msg.assign("Unable to find node (iter.find())");
+ return -1;
+ }
+ if(iter.get(CFG_TYPE_OF_SECTION, &type) != 0){
+ msg.assign("Unable to get node type(iter.get(CFG_TYPE_OF_SECTION))");
+ return -1;
+ }
+ } else {
+ do {
+ if(iter.get(CFG_TYPE_OF_SECTION, &type) != 0){
+ msg.assign("Unable to get node type(iter.get(CFG_TYPE_OF_SECTION))");
+ return -1;
+ }
+ if(type == NODE_TYPE_DB)
+ break;
+ } while(iter.next() == 0);
+ }
+
+ if(type != NODE_TYPE_DB){
+ msg.assfmt("Invalid node type or no such node (%d %d)",
+ type, NODE_TYPE_DB);
+ return -1;
+ }
+
+ int p_type;
+ unsigned val_32;
+ unsigned long long val_64;
+ const char * val_char;
+ do {
+ p_type = 0;
+ if(iter.get(param, &val_32) == 0){
+ val_32 = atoi(value);
+ break;
+ }
+
+ p_type++;
+ if(iter.get(param, &val_64) == 0){
+ val_64 = strtoll(value, 0, 10);
+ break;
+ }
+ p_type++;
+ if(iter.get(param, &val_char) == 0){
+ val_char = value;
+ break;
+ }
+ msg.assign("Could not get parameter");
+ return -1;
+ } while(0);
+
+ bool res = false;
+ do {
+ int ret = iter.get(CFG_TYPE_OF_SECTION, &type);
+ assert(ret == 0);
+
+ if(type != NODE_TYPE_DB)
+ continue;
+
+ Uint32 node;
+ ret = iter.get(CFG_NODE_ID, &node);
+ assert(ret == 0);
+
+ ConfigValues::Iterator i2(_config->m_configValues->m_config,
+ iter.m_config);
+ switch(p_type){
+ case 0:
+ res = i2.set(param, val_32);
+ ndbout_c("Updateing node %d param: %d to %d", node, param, val_32);
+ break;
+ case 1:
+ res = i2.set(param, val_64);
+ ndbout_c("Updateing node %d param: %d to %Ld", node, param, val_32);
+ break;
+ case 2:
+ res = i2.set(param, val_char);
+ ndbout_c("Updateing node %d param: %d to %s", node, param, val_char);
+ break;
+ default:
+ abort();
+ }
+ assert(res);
+ } while(node == 0 && iter.next() == 0);
+
+ msg.assign("Success");
+ return 0;
+}
+
+template class Vector<SigMatch>;
+#if __SUNPRO_CC != 0x560
+template bool SignalQueue::waitFor<SigMatch>(Vector<SigMatch>&, SigMatch*&, NdbApiSignal*&, unsigned);
+#endif
diff --git a/ndb/src/mgmsrv/MgmtSrvr.hpp b/ndb/src/mgmsrv/MgmtSrvr.hpp
index 1d394a14857..b26eaeb4ab9 100644
--- a/ndb/src/mgmsrv/MgmtSrvr.hpp
+++ b/ndb/src/mgmsrv/MgmtSrvr.hpp
@@ -68,6 +68,22 @@ public:
virtual void println_statistics(const BaseString &s) = 0;
};
+ // some compilers need all of this
+ class Allocated_resources;
+ friend class Allocated_resources;
+ class Allocated_resources {
+ public:
+ Allocated_resources(class MgmtSrvr &m);
+ ~Allocated_resources();
+ // methods to reserve/allocate resources which
+ // will be freed when running destructor
+ void reserve_node(NodeId id);
+ bool is_reserved(NodeId nodeId) { return m_reserved_nodes.get(nodeId);}
+ private:
+ MgmtSrvr &m_mgmsrv;
+ NodeBitmask m_reserved_nodes;
+ };
+
/**
* Set a reference to the socket server.
*/
@@ -150,10 +166,12 @@ public:
enum LogMode {In, Out, InOut, Off};
/* Constructor */
+
MgmtSrvr(NodeId nodeId, /* Local nodeid */
const BaseString &config_filename, /* Where to save config */
const BaseString &ndb_config_filename, /* Ndb.cfg filename */
Config * config);
+ NodeId getOwnNodeId() const {return _ownNodeId;};
/**
* Read (initial) config file, create TransporterFacade,
@@ -448,6 +466,8 @@ public:
* @return false if none found
*/
bool getNextNodeId(NodeId * _nodeId, enum ndb_mgm_node_type type) const ;
+ bool alloc_node_id(NodeId * _nodeId, enum ndb_mgm_node_type type,
+ struct sockaddr *client_addr, SOCKET_SIZE_TYPE *client_addr_len);
/**
*
@@ -492,8 +512,14 @@ public:
* @return statistic port number.
*/
int getStatPort() const;
+ /**
+ * Returns the port number.
+ * @return port number.
+ */
+ int getPort() const;
-
+ int setDbParameter(int node, int parameter, const char * value, BaseString&);
+
//**************************************************************************
private:
//**************************************************************************
@@ -530,13 +556,14 @@ private:
BaseString m_configFilename;
BaseString m_localNdbConfigFilename;
Uint32 m_nextConfigGenerationNumber;
+
+ NodeBitmask m_reserved_nodes;
+ Allocated_resources m_allocated_resources;
int _setVarReqResult; // The result of the SET_VAR_REQ response
Statistics _statistics; // handleSTATISTICS_CONF store the result here,
// and getStatistics reads it.
-
-
//**************************************************************************
// Specific signal handling methods
//**************************************************************************
diff --git a/ndb/src/mgmsrv/MgmtSrvrConfig.cpp b/ndb/src/mgmsrv/MgmtSrvrConfig.cpp
index 10316bd2851..44c2aadd1e2 100644
--- a/ndb/src/mgmsrv/MgmtSrvrConfig.cpp
+++ b/ndb/src/mgmsrv/MgmtSrvrConfig.cpp
@@ -288,16 +288,15 @@ MgmtSrvr::readConfig() {
Config *
MgmtSrvr::fetchConfig() {
- ConfigRetriever cr;
+ ConfigRetriever cr(NDB_VERSION, NODE_TYPE_MGM);
cr.setLocalConfigFileName(m_localNdbConfigFilename.c_str());
- struct ndb_mgm_configuration * tmp = cr.getConfig(NDB_VERSION,
- NODE_TYPE_MGM);
+ struct ndb_mgm_configuration * tmp = cr.getConfig();
if(tmp != 0){
Config * conf = new Config();
conf->m_configValues = tmp;
return conf;
}
-
+
return 0;
}
diff --git a/ndb/src/mgmsrv/Services.cpp b/ndb/src/mgmsrv/Services.cpp
index 739eef90c52..7bf408583de 100644
--- a/ndb/src/mgmsrv/Services.cpp
+++ b/ndb/src/mgmsrv/Services.cpp
@@ -14,7 +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 <ctype.h>
#include <uucode.h>
@@ -31,6 +31,8 @@
#include "Services.hpp"
+extern bool g_StopServer;
+
static const unsigned int MAX_READ_TIMEOUT = 1000 ;
static const unsigned int MAX_WRITE_TIMEOUT = 100 ;
@@ -121,6 +123,15 @@ ParserRow<MgmApiSession> commands[] = {
MGM_ARG("version", Int, Mandatory, "Configuration version number"),
MGM_ARG("node", Int, Optional, "Node ID"),
+ MGM_CMD("get nodeid", &MgmApiSession::get_nodeid, ""),
+ MGM_ARG("version", Int, Mandatory, "Configuration version number"),
+ MGM_ARG("nodetype", Int, Mandatory, "Node type"),
+ MGM_ARG("transporter", String, Optional, "Transporter type"),
+ MGM_ARG("nodeid", Int, Optional, "Node ID"),
+ MGM_ARG("user", String, Mandatory, "Password"),
+ MGM_ARG("password", String, Mandatory, "Password"),
+ MGM_ARG("public key", String, Mandatory, "Public key"),
+
MGM_CMD("get version", &MgmApiSession::getVersion, ""),
MGM_CMD("get status", &MgmApiSession::getStatus, ""),
@@ -216,6 +227,16 @@ ParserRow<MgmApiSession> commands[] = {
MGM_ARG("parameter", String, Mandatory, "Parameter"),
MGM_ARG("value", String, Mandatory, "Value"),
+ MGM_CMD("config lock", &MgmApiSession::configLock, ""),
+
+ MGM_CMD("config unlock", &MgmApiSession::configUnlock, ""),
+ MGM_ARG("commit", Int, Mandatory, "Commit changes"),
+
+ MGM_CMD("set parameter", &MgmApiSession::setParameter, ""),
+ MGM_ARG("node", String, Mandatory, "Node"),
+ MGM_ARG("parameter", String, Mandatory, "Parameter"),
+ MGM_ARG("value", String, Mandatory, "Value"),
+
MGM_END()
};
@@ -224,6 +245,19 @@ MgmApiSession::MgmApiSession(class MgmtSrvr & mgm, NDB_SOCKET_TYPE sock)
m_input = new SocketInputStream(sock);
m_output = new SocketOutputStream(sock);
m_parser = new Parser_t(commands, *m_input, true, true, true);
+ m_allocated_resources= new MgmtSrvr::Allocated_resources(m_mgmsrv);
+}
+
+MgmApiSession::~MgmApiSession()
+{
+ if (m_input)
+ delete m_input;
+ if (m_output)
+ delete m_output;
+ if (m_parser)
+ delete m_parser;
+ if (m_allocated_resources)
+ delete m_allocated_resources;
}
void
@@ -333,6 +367,82 @@ backward(const char * base, const Properties* reply){
}
void
+MgmApiSession::get_nodeid(Parser_t::Context &,
+ const class Properties &args)
+{
+ const char *cmd= "get nodeid reply";
+ Uint32 version, nodeid= 0, nodetype= 0xff;
+ const char * transporter;
+ const char * user;
+ const char * password;
+ const char * public_key;
+
+ args.get("version", &version);
+ args.get("nodetype", &nodetype);
+ args.get("transporter", &transporter);
+ args.get("nodeid", &nodeid);
+ args.get("user", &user);
+ args.get("password", &password);
+ args.get("public key", &public_key);
+
+ bool compatible;
+ switch (nodetype) {
+ case NODE_TYPE_MGM:
+ case NODE_TYPE_API:
+ compatible = ndbCompatible_mgmt_api(NDB_VERSION, version);
+ break;
+ case NODE_TYPE_DB:
+ compatible = ndbCompatible_mgmt_ndb(NDB_VERSION, version);
+ break;
+ default:
+ m_output->println(cmd);
+ m_output->println("result: unknown nodetype %d", nodetype);
+ m_output->println("");
+ return;
+ }
+
+ struct sockaddr addr;
+ SOCKET_SIZE_TYPE addrlen= sizeof(addr);
+ int r = getpeername(m_socket, &addr, &addrlen);
+ if (r != 0 ) {
+ m_output->println(cmd);
+ m_output->println("result: getpeername(%d) failed, err= %d", m_socket, r);
+ m_output->println("");
+ return;
+ }
+
+ NodeId tmp= nodeid;
+ if(tmp == 0 || !m_allocated_resources->is_reserved(tmp)){
+ if (!m_mgmsrv.alloc_node_id(&tmp, (enum ndb_mgm_node_type)nodetype,
+ &addr, &addrlen)){
+ m_output->println(cmd);
+ m_output->println("result: no free nodeid %d for nodetype %d",
+ nodeid, nodetype);
+ m_output->println("");
+ return;
+ }
+ }
+
+#if 0
+ if (!compatible){
+ m_output->println(cmd);
+ m_output->println("result: incompatible version mgmt 0x%x and node 0x%x",
+ NDB_VERSION, version);
+ m_output->println("");
+ return;
+ }
+#endif
+
+ m_output->println(cmd);
+ m_output->println("nodeid: %u", tmp);
+ m_output->println("result: Ok");
+ m_output->println("");
+ m_allocated_resources->reserve_node(tmp);
+
+ return;
+}
+
+void
MgmApiSession::getConfig_common(Parser_t::Context &,
const class Properties &args,
bool compat) {
@@ -432,7 +542,6 @@ MgmApiSession::getConfig_common(Parser_t::Context &,
m_output->println("Content-Transfer-Encoding: base64");
m_output->println("");
m_output->println(str.c_str());
- m_output->println("");
return;
}
@@ -905,10 +1014,27 @@ MgmApiSession::stop(Parser<MgmApiSession>::Context &,
nodes.push_back(atoi(p));
}
+ int stop_self= 0;
+
+ for(size_t i=0; i < nodes.size(); i++) {
+ if (nodes[i] == m_mgmsrv.getOwnNodeId()) {
+ stop_self= 1;
+ if (i != nodes.size()-1) {
+ m_output->println("stop reply");
+ m_output->println("result: server must be stopped last");
+ m_output->println("");
+ return;
+ }
+ }
+ }
+
int stopped = 0, result = 0;
for(size_t i=0; i < nodes.size(); i++)
- if((result = m_mgmsrv.stopNode(nodes[i], abort != 0)) == 0)
+ if (nodes[i] != m_mgmsrv.getOwnNodeId()) {
+ if((result = m_mgmsrv.stopNode(nodes[i], abort != 0)) == 0)
+ stopped++;
+ } else
stopped++;
m_output->println("stop reply");
@@ -918,6 +1044,9 @@ MgmApiSession::stop(Parser<MgmApiSession>::Context &,
m_output->println("result: Ok");
m_output->println("stopped: %d", stopped);
m_output->println("");
+
+ if (stop_self)
+ g_StopServer= true;
}
@@ -1119,7 +1248,8 @@ void
MgmStatService::println_statistics(const BaseString &line){
MutexVector<NDB_SOCKET_TYPE> copy(m_sockets.size());
m_sockets.lock();
- for(int i = m_sockets.size() - 1; i >= 0; i--){
+ int i;
+ for(i = m_sockets.size() - 1; i >= 0; i--){
if(println_socket(m_sockets[i], MAX_WRITE_TIMEOUT, line.c_str()) == -1){
copy.push_back(m_sockets[i]);
m_sockets.erase(i, false);
@@ -1127,7 +1257,7 @@ MgmStatService::println_statistics(const BaseString &line){
}
m_sockets.unlock();
- for(int i = copy.size() - 1; i >= 0; i--){
+ for(i = copy.size() - 1; i >= 0; i--){
NDB_CLOSE_SOCKET(copy[i]);
copy.erase(i);
}
@@ -1142,5 +1272,28 @@ MgmStatService::stopSessions(){
NDB_CLOSE_SOCKET(m_sockets[i]);
m_sockets.erase(i);
}
+}
+
+void
+MgmApiSession::setParameter(Parser_t::Context &,
+ Properties const &args) {
+ BaseString node, param, value;
+ args.get("node", node);
+ args.get("parameter", param);
+ args.get("value", value);
+ BaseString result;
+ int ret = m_mgmsrv.setDbParameter(atoi(node.c_str()),
+ atoi(param.c_str()),
+ value.c_str(),
+ result);
+
+ m_output->println("set parameter reply");
+ m_output->println("message: %s", result.c_str());
+ m_output->println("result: %d", ret);
+ m_output->println("");
}
+
+template class MutexVector<int>;
+template class Vector<ParserRow<MgmApiSession> const*>;
+template class Vector<unsigned short>;
diff --git a/ndb/src/mgmsrv/Services.hpp b/ndb/src/mgmsrv/Services.hpp
index 3690f1a5a93..9cf8b59be8f 100644
--- a/ndb/src/mgmsrv/Services.hpp
+++ b/ndb/src/mgmsrv/Services.hpp
@@ -36,6 +36,7 @@ private:
InputStream *m_input;
OutputStream *m_output;
Parser_t *m_parser;
+ MgmtSrvr::Allocated_resources *m_allocated_resources;
void getConfig_common(Parser_t::Context &ctx,
const class Properties &args,
@@ -43,6 +44,7 @@ private:
public:
MgmApiSession(class MgmtSrvr & mgm, NDB_SOCKET_TYPE sock);
+ virtual ~MgmApiSession();
void runSession();
void getStatPort(Parser_t::Context &ctx, const class Properties &args);
@@ -51,6 +53,7 @@ public:
void getConfig_old(Parser_t::Context &ctx);
#endif /* MGM_GET_CONFIG_BACKWARDS_COMPAT */
+ void get_nodeid(Parser_t::Context &ctx, const class Properties &args);
void getVersion(Parser_t::Context &ctx, const class Properties &args);
void getStatus(Parser_t::Context &ctx, const class Properties &args);
void getInfoClusterLog(Parser_t::Context &ctx, const class Properties &args);
@@ -79,6 +82,8 @@ public:
void configUnlock(Parser_t::Context &ctx, const class Properties &args);
void configChange(Parser_t::Context &ctx, const class Properties &args);
+ void setParameter(Parser_t::Context &ctx, const class Properties &args);
+
void repCommand(Parser_t::Context &ctx, const class Properties &args);
};
diff --git a/ndb/src/mgmsrv/main.cpp b/ndb/src/mgmsrv/main.cpp
index d9eb0001c44..719226b51df 100644
--- a/ndb/src/mgmsrv/main.cpp
+++ b/ndb/src/mgmsrv/main.cpp
@@ -16,11 +16,9 @@
#include <ndb_global.h>
-#include <signal.h>
-
#include "MgmtSrvr.hpp"
#include "EventLogger.hpp"
-#include "Config.hpp"
+#include <Config.hpp>
#include "InitConfigFileParser.hpp"
#include <SocketServer.hpp>
#include "Services.hpp"
@@ -37,6 +35,8 @@
#include <mgmapi_config_parameters.h>
#include <getarg.h>
+#include <NdbAutoPtr.hpp>
+
#if defined NDB_OSE || defined NDB_SOFTOSE
#include <efs.h>
#else
@@ -88,7 +88,6 @@ static MgmGlobals glob;
******************************************************************************/
static bool readLocalConfig();
static bool readGlobalConfig();
-static bool setPortNo();
/**
* Global variables
@@ -100,16 +99,16 @@ extern int global_mgmt_server_check;
int _print_version = 0;
struct getargs args[] = {
- { "version", 0, arg_flag, &_print_version,
- "Print versions"},
- { NULL, 'c', arg_string, &glob.config_filename,
- "Running cluster configuration file", "filename" },
- { NULL, 'd', arg_flag, &glob.daemon,
- "Daemon mode" },
+ { "version", 'v', arg_flag, &_print_version,
+ "Print ndb_mgmd version"},
+ { "config-file", 'c', arg_string, &glob.config_filename,
+ "Specify cluster configuration file", "filename" },
+ { "daemon", 'd', arg_flag, &glob.daemon,
+ "Run ndb_mgmd in daemon mode" },
{ NULL, 'l', arg_string, &glob.local_config_filename,
- "Local configuration file (Ndb.cfg)",
+ "Specify configuration file connect string (will default use Ndb.cfg if available)",
"filename" },
- { NULL, 'n', arg_flag, &glob.non_interactive,
+ { "nodaemon", 'n', arg_flag, &glob.non_interactive,
"Don't run as daemon, but don't read from stdin", "non-interactive" }
};
@@ -146,7 +145,9 @@ NDB_MAIN(mgmsrv){
exit(1);
}
glob.socketServer = new SocketServer();
+
MgmApiService * mapi = new MgmApiService();
+
MgmStatService * mstat = new MgmStatService();
/****************************
@@ -157,16 +158,34 @@ NDB_MAIN(mgmsrv){
if (!readGlobalConfig())
goto error_end;
- if (!setPortNo())
+ glob.mgmObject = new MgmtSrvr(glob.localNodeId,
+ BaseString(glob.config_filename),
+ BaseString(glob.local_config_filename == 0 ?
+ "" : glob.local_config_filename),
+ glob.cluster_config);
+
+ glob.cluster_config = 0;
+ glob.localNodeId= glob.mgmObject->getOwnNodeId();
+
+ if (glob.localNodeId == 0) {
goto error_end;
-
+ }
+
+ glob.port= glob.mgmObject->getPort();
+
+ if (glob.port == 0)
+ goto error_end;
+
+ glob.interface_name = 0;
+ glob.use_specific_ip = false;
+
if(!glob.use_specific_ip){
if(!glob.socketServer->tryBind(glob.port, glob.interface_name)){
ndbout_c("Unable to setup port: %s:%d!\n"
"Please check if the port is already used,\n"
"(perhaps a mgmtsrvr is already running),\n"
"and if you are executing on the correct computer",
- glob.interface_name, glob.port);
+ (glob.interface_name ? glob.interface_name : "*"), glob.port);
goto error_end;
}
free(glob.interface_name);
@@ -190,31 +209,25 @@ NDB_MAIN(mgmsrv){
goto error_end;
}
- glob.mgmObject = new MgmtSrvr(glob.localNodeId,
- BaseString(glob.config_filename),
- BaseString(glob.local_config_filename == 0 ? "" : glob.local_config_filename),
- glob.cluster_config);
-
- glob.cluster_config = 0;
-
if(!glob.mgmObject->check_start()){
- ndbout_c("Unable to start management server.");
+ ndbout_c("Unable to check start management server.");
ndbout_c("Probably caused by illegal initial configuration file.");
goto error_end;
}
if (glob.daemon) {
// Become a daemon
- char homePath[255],lockfile[255], logfile[255];
- NdbConfig_HomePath(homePath, 255);
- snprintf(lockfile, 255, "%snode%d.pid", homePath, glob.localNodeId);
- snprintf(logfile, 255, "%snode%d.out", homePath, glob.localNodeId);
+ char *lockfile= NdbConfig_PidFileName(glob.localNodeId);
+ char *logfile= NdbConfig_StdoutFileName(glob.localNodeId);
+ NdbAutoPtr<char> tmp_aptr1(lockfile), tmp_aptr2(logfile);
+
if (NdbDaemon_Make(lockfile, logfile, 0) == -1) {
ndbout << "Cannot become daemon: " << NdbDaemon_ErrorText << endl;
return 1;
}
}
+ signal(SIGPIPE, SIG_IGN);
if(!glob.mgmObject->start()){
ndbout_c("Unable to start management server.");
ndbout_c("Probably caused by illegal initial configuration file.");
@@ -233,8 +246,8 @@ NDB_MAIN(mgmsrv){
ndbout_c(msg);
g_EventLogger.info(msg);
- snprintf(msg, 256, "Command port: %d, Statistics port: %d",
- glob.port, glob.port_stats);
+ snprintf(msg, 256, "Id: %d, Command port: %d, Statistics port: %d",
+ glob.localNodeId, glob.port, glob.port_stats);
ndbout_c(msg);
g_EventLogger.info(msg);
@@ -298,14 +311,11 @@ MgmGlobals::~MgmGlobals(){
static bool
readLocalConfig(){
// Read local config file
- ConfigRetriever cr;
- cr.setLocalConfigFileName(glob.local_config_filename);
- int nodeid = cr.init(true);
- if(nodeid == -1){
+ LocalConfig lc;
+ if(!lc.init(glob.local_config_filename))
return false;
- }
- glob.localNodeId = (NodeId)nodeid;
+ glob.localNodeId = lc._ownNodeId;
return true;
}
@@ -328,123 +338,7 @@ readGlobalConfig() {
InitConfigFileParser parser;
glob.cluster_config = parser.parseConfig(glob.config_filename);
if(glob.cluster_config == 0){
- /**
- * Try to get configuration from other MGM server
- * Note: Only new format
- */
- glob.cluster_config = new Config();
-
- ConfigRetriever cr;
- cr.setLocalConfigFileName(glob.local_config_filename);
- glob.cluster_config->m_configValues = cr.getConfig(NDB_VERSION,
- NODE_TYPE_MGM);
- if (glob.cluster_config->m_configValues == NULL)
- return false;
- }
- return true;
-}
-
-/**
- * @fn setPortNo
- * @param glob : Global variables
- * @return true if success, false otherwise.
- *
- * Port number:
- * 2. Use port number from global configuration file
- * 4. Use port number for statistics from global configuration file
- */
-static bool
-setPortNo(){
- const Properties *mgmProps;
-
- ndb_mgm_configuration_iterator * iter =
- ndb_mgm_create_configuration_iterator(glob.cluster_config->m_configValues,
- CFG_SECTION_NODE);
- if(iter == 0)
- return false;
-
- if(ndb_mgm_find(iter, CFG_NODE_ID, glob.localNodeId) != 0){
- ndbout << "Could not retrieve configuration for Node "
- << glob.localNodeId << " in config file." << endl
- << "Have you set correct NodeId for this node?" << endl;
- ndb_mgm_destroy_iterator(iter);
- return false;
- }
-
- unsigned type;
- if(ndb_mgm_get_int_parameter(iter, CFG_TYPE_OF_SECTION, &type) != 0 ||
- type != NODE_TYPE_MGM){
- ndbout << "Local node id " << glob.localNodeId
- << " is not defined as management server" << endl
- << "Have you set correct NodeId for this node?" << endl;
- return false;
- }
-
- /************
- * Set Port *
- ************/
- Uint32 tmp = 0;
- if(ndb_mgm_get_int_parameter(iter, CFG_MGM_PORT, &tmp) != 0){
- ndbout << "Could not find PortNumber in the configuration file." << endl;
- return false;
- }
- glob.port = tmp;
-
- /*****************
- * Set Stat Port *
- *****************/
-#if 0
- if (!mgmProps->get("PortNumberStats", &tmp)){
- ndbout << "Could not find PortNumberStats in the configuration file."
- << endl;
return false;
}
- glob.port_stats = tmp;
-#endif
-
-#if 0
- const char * host;
- if(ndb_mgm_get_string_parameter(iter, mgmProps->get("ExecuteOnComputer", host)){
- ndbout << "Failed to find \"ExecuteOnComputer\" for my node" << endl;
- ndbout << "Unable to verify own hostname" << endl;
- return false;
- }
-
- const char * hostname;
- {
- const Properties * p;
- char buf[255];
- snprintf(buf, sizeof(buf), "Computer_%s", host.c_str());
- if(!glob.cluster_config->get(buf, &p)){
- ndbout << "Failed to find computer " << host << " in config" << endl;
- ndbout << "Unable to verify own hostname" << endl;
- return false;
- }
- if(!p->get("HostName", &hostname)){
- ndbout << "Failed to find \"HostName\" for computer " << host
- << " in config" << endl;
- ndbout << "Unable to verify own hostname" << endl;
- return false;
- }
- if(NdbHost_GetHostName(buf) != 0){
- ndbout << "Unable to get own hostname" << endl;
- ndbout << "Unable to verify own hostname" << endl;
- return false;
- }
- }
-
- const char * ip_address;
- if(mgmProps->get("IpAddress", &ip_address)){
- glob.use_specific_ip = true;
- glob.interface_name = strdup(ip_address);
- return true;
- }
-
- glob.interface_name = strdup(hostname);
-#endif
-
- glob.interface_name = 0;
- glob.use_specific_ip = false;
-
return true;
}
diff --git a/ndb/src/ndbapi/ClusterMgr.cpp b/ndb/src/ndbapi/ClusterMgr.cpp
index b26d550fe31..b9947fcf0e7 100644
--- a/ndb/src/ndbapi/ClusterMgr.cpp
+++ b/ndb/src/ndbapi/ClusterMgr.cpp
@@ -295,6 +295,7 @@ ClusterMgr::execAPI_REGREQ(const Uint32 * theData){
}
int global_mgmt_server_check = 0; // set to one in mgmtsrvr main;
+
void
ClusterMgr::execAPI_REGCONF(const Uint32 * theData){
const ApiRegConf * const apiRegConf = (ApiRegConf *)&theData[0];
@@ -309,6 +310,7 @@ ClusterMgr::execAPI_REGCONF(const Uint32 * theData){
Node & node = theNodes[nodeId];
assert(node.defined == true);
assert(node.connected == true);
+
if(node.m_info.m_version != apiRegConf->version){
node.m_info.m_version = apiRegConf->version;
if (global_mgmt_server_check == 1)
diff --git a/ndb/src/ndbapi/DictCache.cpp b/ndb/src/ndbapi/DictCache.cpp
index f6f2106f2aa..5f620f77906 100644
--- a/ndb/src/ndbapi/DictCache.cpp
+++ b/ndb/src/ndbapi/DictCache.cpp
@@ -157,6 +157,7 @@ GlobalDictCache::put(const char * name, NdbTableImpl * tab)
void
GlobalDictCache::drop(NdbTableImpl * tab)
{
+ unsigned i;
const Uint32 len = strlen(tab->m_internalName.c_str());
Vector<TableVersion> * vers =
m_tableHash.getData(tab->m_internalName.c_str(), len);
@@ -173,7 +174,7 @@ GlobalDictCache::drop(NdbTableImpl * tab)
abort();
}
- for(unsigned i = 0; i < sz; i++){
+ for(i = 0; i < sz; i++){
TableVersion & ver = (* vers)[i];
if(ver.m_impl == tab){
if(ver.m_refCount == 0 || ver.m_status == RETREIVING ||
@@ -193,7 +194,7 @@ GlobalDictCache::drop(NdbTableImpl * tab)
}
}
- for(unsigned i = 0; i<sz; i++){
+ for(i = 0; i<sz; i++){
TableVersion & ver = (* vers)[i];
ndbout_c("%d: version: %d refCount: %d status: %d impl: %p",
i, ver.m_version, ver.m_refCount, ver.m_status, ver.m_impl);
@@ -204,6 +205,7 @@ GlobalDictCache::drop(NdbTableImpl * tab)
void
GlobalDictCache::release(NdbTableImpl * tab){
+ unsigned i;
const Uint32 len = strlen(tab->m_internalName.c_str());
Vector<TableVersion> * vers =
m_tableHash.getData(tab->m_internalName.c_str(), len);
@@ -220,7 +222,7 @@ GlobalDictCache::release(NdbTableImpl * tab){
abort();
}
- for(unsigned i = 0; i < sz; i++){
+ for(i = 0; i < sz; i++){
TableVersion & ver = (* vers)[i];
if(ver.m_impl == tab){
if(ver.m_refCount == 0 || ver.m_status == RETREIVING ||
@@ -235,7 +237,7 @@ GlobalDictCache::release(NdbTableImpl * tab){
}
}
- for(unsigned i = 0; i<sz; i++){
+ for(i = 0; i<sz; i++){
TableVersion & ver = (* vers)[i];
ndbout_c("%d: version: %d refCount: %d status: %d impl: %p",
i, ver.m_version, ver.m_refCount, ver.m_status, ver.m_impl);
@@ -244,3 +246,4 @@ GlobalDictCache::release(NdbTableImpl * tab){
abort();
}
+template class Vector<GlobalDictCache::TableVersion>;
diff --git a/ndb/src/ndbapi/Makefile.am b/ndb/src/ndbapi/Makefile.am
index 2ec58ab6e85..14badb0c62f 100644
--- a/ndb/src/ndbapi/Makefile.am
+++ b/ndb/src/ndbapi/Makefile.am
@@ -23,9 +23,7 @@ libndbapi_la_SOURCES = \
NdbOperationDefine.cpp \
NdbOperationExec.cpp \
NdbResultSet.cpp \
- NdbCursorOperation.cpp \
- NdbScanReceiver.cpp NdbScanOperation.cpp \
- NdbScanFilter.cpp \
+ NdbScanOperation.cpp NdbScanFilter.cpp \
NdbIndexOperation.cpp \
NdbEventOperation.cpp \
NdbEventOperationImpl.cpp \
diff --git a/ndb/src/ndbapi/Makefile_old b/ndb/src/ndbapi/Makefile_old
index c2bb0189a7f..54de9ba96f4 100644
--- a/ndb/src/ndbapi/Makefile_old
+++ b/ndb/src/ndbapi/Makefile_old
@@ -34,31 +34,24 @@ SOURCES = \
Ndblist.cpp \
Ndbif.cpp \
Ndbinit.cpp \
- Ndberr.cpp \
- ndberror.c \
- NdbErrorOut.cpp \
- NdbConnection.cpp \
+ ndberror.c Ndberr.cpp NdbErrorOut.cpp \
+ NdbConnection.cpp \
NdbConnectionScan.cpp \
NdbOperation.cpp \
NdbOperationSearch.cpp \
- NdbOperationScan.cpp \
NdbOperationInt.cpp \
NdbOperationDefine.cpp \
NdbOperationExec.cpp \
- NdbScanReceiver.cpp \
NdbResultSet.cpp \
- NdbCursorOperation.cpp \
NdbScanOperation.cpp NdbScanFilter.cpp \
NdbIndexOperation.cpp \
NdbEventOperation.cpp \
NdbEventOperationImpl.cpp \
NdbApiSignal.cpp \
NdbRecAttr.cpp \
- NdbSchemaCon.cpp \
- NdbSchemaOp.cpp \
NdbUtil.cpp \
NdbReceiver.cpp \
- NdbDictionary.cpp NdbDictionaryImpl.cpp DictCache.cpp \
+ NdbDictionary.cpp NdbDictionaryImpl.cpp DictCache.cpp
NdbBlob.cpp
include $(NDB_TOP)/Epilogue.mk
diff --git a/ndb/src/ndbapi/Ndb.cpp b/ndb/src/ndbapi/Ndb.cpp
index fe7260c4693..f09a7481d2d 100644
--- a/ndb/src/ndbapi/Ndb.cpp
+++ b/ndb/src/ndbapi/Ndb.cpp
@@ -154,26 +154,22 @@ Ndb::NDB_connect(Uint32 tNode)
tNdbCon->Status(NdbConnection::Connecting); // Set status to connecting
Uint32 nodeSequence;
{ // send and receive signal
- tp->lock_mutex();
+ Guard guard(tp->theMutexPtr);
nodeSequence = tp->getNodeSequence(tNode);
bool node_is_alive = tp->get_node_alive(tNode);
if (node_is_alive) {
tReturnCode = tp->sendSignal(tSignal, tNode);
releaseSignal(tSignal);
- if (tReturnCode == -1) {
- tp->unlock_mutex();
- } else {
+ if (tReturnCode != -1) {
theWaiter.m_node = tNode;
theWaiter.m_state = WAIT_TC_SEIZE;
tReturnCode = receiveResponse();
}//if
} else {
releaseSignal(tSignal);
- tp->unlock_mutex();
tReturnCode = -1;
}//if
}
-
if ((tReturnCode == 0) && (tNdbCon->Status() == NdbConnection::Connected)) {
//************************************************
// Send and receive was successful
@@ -463,9 +459,9 @@ Ndb::closeTransaction(NdbConnection* aConnection)
CHECK_STATUS_MACRO_VOID;
tCon = theTransactionList;
-
+
if (aConnection == tCon) { // Remove the active connection object
- theTransactionList = tCon->next(); // from the transaction list.
+ theTransactionList = tCon->next(); // from the transaction list.
} else {
while (aConnection != tCon) {
if (tCon == NULL) {
@@ -473,44 +469,33 @@ Ndb::closeTransaction(NdbConnection* aConnection)
// closeTransaction called on non-existing transaction
//-----------------------------------------------------
- if(aConnection->theError.code == 4008){
- /**
- * When a SCAN timed-out, returning the NdbConnection leads
- * to reuse. And TC crashes when the API tries to reuse it to
- * something else...
- */
+ if(aConnection->theError.code == 4008){
+ /**
+ * When a SCAN timed-out, returning the NdbConnection leads
+ * to reuse. And TC crashes when the API tries to reuse it to
+ * something else...
+ */
#ifdef VM_TRACE
- printf("Scan timeout:ed NdbConnection-> not returning it-> memory leak\n");
+ printf("Scan timeout:ed NdbConnection-> "
+ "not returning it-> memory leak\n");
#endif
- return;
- }
+ return;
+ }
#ifdef VM_TRACE
- printf("Non-existing transaction into closeTransaction\n");
+ printf("Non-existing transaction into closeTransaction\n");
abort();
#endif
- return;
+ return;
}//if
tPreviousCon = tCon;
tCon = tCon->next();
}//while
tPreviousCon->next(tCon->next());
}//if
-
+
aConnection->release();
-
- if(aConnection->theError.code == 4008){
- /**
- * When a SCAN timed-out, returning the NdbConnection leads
- * to reuse. And TC crashes when the API tries to reuse it to
- * something else...
- */
-#ifdef VM_TRACE
- printf("Scan timeout:ed NdbConnection-> not returning it-> memory leak\n");
-#endif
- return;
- }
-
+
if(aConnection->theError.code == 4008){
/**
* Something timed-out, returning the NdbConnection leads
@@ -522,7 +507,7 @@ Ndb::closeTransaction(NdbConnection* aConnection)
#endif
return;
}
-
+
if (aConnection->theReleaseOnClose == false) {
/**
* Put it back in idle list for that node
@@ -729,9 +714,10 @@ Ndb::getNodeId()
}
/****************************************************************************
-Uint64 getTupleIdFromNdb( Uint32 aTableId );
+Uint64 getTupleIdFromNdb( Uint32 aTableId, Uint32 cacheSize );
Parameters: aTableId : The TableId.
+ cacheSize: Prefetch this many values
Remark: Returns a new TupleId to the application.
The TupleId comes from SYSTAB_0 where SYSKEY_0 = TableId.
It is initialized to (TableId << 48) + 1 in NdbcntrMain.cpp.
@@ -750,8 +736,19 @@ Ndb::getAutoIncrementValue(const char* aTableName, Uint32 cacheSize)
return tupleId;
}
+Uint64
+Ndb::getAutoIncrementValue(NdbDictionary::Table * aTable, Uint32 cacheSize)
+{
+ DEBUG_TRACE("getAutoIncrementValue");
+ if (aTable == 0)
+ return ~0;
+ const NdbTableImpl* table = & NdbTableImpl::getImpl(*aTable);
+ Uint64 tupleId = getTupleIdFromNdb(table->m_tableId, cacheSize);
+ return tupleId;
+}
+
Uint64
-Ndb::getTupleIdFromNdb(const char* aTableName, Uint32 cacheSize )
+Ndb::getTupleIdFromNdb(const char* aTableName, Uint32 cacheSize)
{
const NdbTableImpl* table = theDictionary->getTable(aTableName);
if (table == 0)
@@ -760,7 +757,7 @@ Ndb::getTupleIdFromNdb(const char* aTableName, Uint32 cacheSize )
}
Uint64
-Ndb::getTupleIdFromNdb(Uint32 aTableId, Uint32 cacheSize )
+Ndb::getTupleIdFromNdb(Uint32 aTableId, Uint32 cacheSize)
{
if ( theFirstTupleId[aTableId] != theLastTupleId[aTableId] )
{
@@ -773,31 +770,90 @@ Ndb::getTupleIdFromNdb(Uint32 aTableId, Uint32 cacheSize )
}
}
+Uint64
+Ndb::readAutoIncrementValue(const char* aTableName)
+{
+ DEBUG_TRACE("readtAutoIncrementValue");
+ const NdbTableImpl* table = theDictionary->getTable(aTableName);
+ if (table == 0)
+ return ~0;
+ Uint64 tupleId = readTupleIdFromNdb(table->m_tableId);
+ return tupleId;
+}
+
+Uint64
+Ndb::readAutoIncrementValue(NdbDictionary::Table * aTable)
+{
+ DEBUG_TRACE("readtAutoIncrementValue");
+ if (aTable == 0)
+ return ~0;
+ const NdbTableImpl* table = & NdbTableImpl::getImpl(*aTable);
+ Uint64 tupleId = readTupleIdFromNdb(table->m_tableId);
+ return tupleId;
+}
+
+Uint64
+Ndb::readTupleIdFromNdb(Uint32 aTableId)
+{
+ if ( theFirstTupleId[aTableId] == theLastTupleId[aTableId] )
+ // Cache is empty, check next in database
+ return opTupleIdOnNdb(aTableId, 0, 3);
+
+ return theFirstTupleId[aTableId] + 1;
+}
+
bool
-Ndb::setAutoIncrementValue(const char* aTableName, Uint64 val)
+Ndb::setAutoIncrementValue(const char* aTableName, Uint64 val, bool increase)
{
DEBUG_TRACE("setAutoIncrementValue " << val);
const NdbTableImpl* table = theDictionary->getTable(aTableName);
if (table == 0)
return false;
- return setTupleIdInNdb(table->m_tableId, val);
+ return setTupleIdInNdb(table->m_tableId, val, increase);
+}
+
+bool
+Ndb::setAutoIncrementValue(NdbDictionary::Table * aTable, Uint64 val, bool increase)
+{
+ DEBUG_TRACE("setAutoIncrementValue " << val);
+ if (aTable == 0)
+ return ~0;
+ const NdbTableImpl* table = & NdbTableImpl::getImpl(*aTable);
+ return setTupleIdInNdb(table->m_tableId, val, increase);
}
bool
-Ndb::setTupleIdInNdb(const char* aTableName, Uint64 val )
+Ndb::setTupleIdInNdb(const char* aTableName, Uint64 val, bool increase )
{
DEBUG_TRACE("setTupleIdInNdb");
const NdbTableImpl* table = theDictionary->getTable(aTableName);
if (table == 0)
return false;
- return setTupleIdInNdb(table->m_tableId, val);
+ return setTupleIdInNdb(table->m_tableId, val, increase);
}
bool
-Ndb::setTupleIdInNdb(Uint32 aTableId, Uint64 val )
+Ndb::setTupleIdInNdb(Uint32 aTableId, Uint64 val, bool increase )
{
DEBUG_TRACE("setTupleIdInNdb");
- return (opTupleIdOnNdb(aTableId, val, 1) == val);
+ if (increase)
+ {
+ if (theFirstTupleId[aTableId] != theLastTupleId[aTableId])
+ {
+ // We have a cache sequence
+ if (val <= theFirstTupleId[aTableId]+1)
+ return false;
+ if (val <= theLastTupleId[aTableId])
+ {
+ theFirstTupleId[aTableId] = val - 1;
+ return true;
+ }
+ // else continue;
+ }
+ return (opTupleIdOnNdb(aTableId, val, 2) == val);
+ }
+ else
+ return (opTupleIdOnNdb(aTableId, val, 1) == val);
}
Uint64
@@ -809,7 +865,7 @@ Ndb::opTupleIdOnNdb(Uint32 aTableId, Uint64 opValue, Uint32 op)
NdbOperation* tOperation;
Uint64 tValue;
NdbRecAttr* tRecAttrResult;
-
+ int result;
Uint64 ret;
CHECK_STATUS_MACRO_ZERO;
@@ -835,15 +891,7 @@ Ndb::opTupleIdOnNdb(Uint32 aTableId, Uint64 opValue, Uint32 op)
case 0:
tOperation->interpretedUpdateTuple();
tOperation->equal("SYSKEY_0", aTableId );
- {
-#ifdef WORDS_BIGENDIAN
- Uint64 cacheSize64 = opValue; // XXX interpreter bug on Uint32
- tOperation->incValue("NEXTID", cacheSize64);
-#else
- Uint32 cacheSize32 = opValue; // XXX for little-endian
- tOperation->incValue("NEXTID", cacheSize32);
-#endif
- }
+ tOperation->incValue("NEXTID", opValue);
tRecAttrResult = tOperation->getValue("NEXTID");
if (tConnection->execute( Commit ) == -1 )
@@ -863,10 +911,40 @@ Ndb::opTupleIdOnNdb(Uint32 aTableId, Uint64 opValue, Uint32 op)
if (tConnection->execute( Commit ) == -1 )
goto error_handler;
- theFirstTupleId[aTableId] = ~0;
- theLastTupleId[aTableId] = ~0;
+ theFirstTupleId[aTableId] = ~(Uint64)0;
+ theLastTupleId[aTableId] = ~(Uint64)0;
ret = opValue;
break;
+ case 2:
+ tOperation->interpretedUpdateTuple();
+ tOperation->equal("SYSKEY_0", aTableId );
+ tOperation->load_const_u64(1, opValue);
+ tOperation->read_attr("NEXTID", 2);
+ tOperation->branch_le(2, 1, 0);
+ tOperation->write_attr("NEXTID", 1);
+ tOperation->interpret_exit_ok();
+ tOperation->def_label(0);
+ tOperation->interpret_exit_nok(9999);
+
+ if ( (result = tConnection->execute( Commit )) == -1 )
+ goto error_handler;
+
+ if (result == 9999)
+ ret = ~(Uint64)0;
+ else
+ {
+ theFirstTupleId[aTableId] = theLastTupleId[aTableId] = opValue - 1;
+ ret = opValue;
+ }
+ break;
+ case 3:
+ tOperation->readTuple();
+ tOperation->equal("SYSKEY_0", aTableId );
+ tRecAttrResult = tOperation->getValue("NEXTID");
+ if (tConnection->execute( Commit ) == -1 )
+ goto error_handler;
+ ret = tRecAttrResult->u_64_value();
+ break;
default:
goto error_handler;
}
@@ -973,13 +1051,13 @@ Ndb::StartTransactionNodeSelectionData::init(Uint32 noOfNodes,
*/
{
fragment2PrimaryNodeMap = new Uint32[noOfFragments];
-
- for(Uint32 i = 0; i<noOfNodes; i++){
+ Uint32 i;
+ for(i = 0; i<noOfNodes; i++){
fragment2PrimaryNodeMap[i] = nodeIds[i];
}
// Sort them (bubble sort)
- for(Uint32 i = 0; i<noOfNodes-1; i++)
+ for(i = 0; i<noOfNodes-1; i++)
for(Uint32 j = i+1; j<noOfNodes; j++)
if(fragment2PrimaryNodeMap[i] > fragment2PrimaryNodeMap[j]){
Uint32 tmp = fragment2PrimaryNodeMap[i];
@@ -987,7 +1065,7 @@ Ndb::StartTransactionNodeSelectionData::init(Uint32 noOfNodes,
fragment2PrimaryNodeMap[j] = tmp;
}
- for(Uint32 i = 0; i<noOfNodes; i++){
+ for(i = 0; i<noOfNodes; i++){
fragment2PrimaryNodeMap[i+noOfNodes] = fragment2PrimaryNodeMap[i];
}
}
diff --git a/ndb/src/ndbapi/NdbApiSignal.cpp b/ndb/src/ndbapi/NdbApiSignal.cpp
index a44937cd398..6f5e1e50d2c 100644
--- a/ndb/src/ndbapi/NdbApiSignal.cpp
+++ b/ndb/src/ndbapi/NdbApiSignal.cpp
@@ -15,18 +15,6 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-/******************************************************************************
-Name: NdbApiSignal.C
-Include:
-Link:
-Author: UABMNST Mona Natterkvist UAB/B/SD
-Date: 970829
-Version: 0.1
-Description: Interface between TIS and NDB
-Documentation:
-Adjust: 971114 UABMNST First version.
- 000705 QABANAB Update of Protocol2
-******************************************************************************/
#include "API.hpp"
#include "NdbApiSignal.hpp"
@@ -46,6 +34,7 @@ Adjust: 971114 UABMNST First version.
#include <signaldata/IndxKeyInfo.hpp>
#include <signaldata/IndxAttrInfo.hpp>
#include <signaldata/TcHbRep.hpp>
+#include <signaldata/ScanTab.hpp>
#include <NdbOut.hpp>
@@ -161,7 +150,7 @@ NdbApiSignal::setSignal(int aNdbSignalType)
theTrace = TestOrd::TraceAPI;
theReceiversBlockNumber = DBTC;
theVerId_signalNumber = GSN_TCROLLBACKREQ;
- theLength = 5;
+ theLength = 3;
}
break;
@@ -188,16 +177,7 @@ NdbApiSignal::setSignal(int aNdbSignalType)
theTrace = TestOrd::TraceAPI;
theReceiversBlockNumber = DBTC;
theVerId_signalNumber = GSN_SCAN_TABREQ;
- theLength = 25;
- }
- break;
-
- case GSN_SCAN_TABINFO:
- {
- theTrace = TestOrd::TraceAPI;
- theReceiversBlockNumber = DBTC;
- theVerId_signalNumber = GSN_SCAN_TABINFO;
- theLength = 17;
+ theLength = 9; // ScanTabReq::SignalLength;
}
break;
diff --git a/ndb/src/ndbapi/NdbBlob.cpp b/ndb/src/ndbapi/NdbBlob.cpp
index 8e067f770e8..7939f54d846 100644
--- a/ndb/src/ndbapi/NdbBlob.cpp
+++ b/ndb/src/ndbapi/NdbBlob.cpp
@@ -14,23 +14,25 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-#include "Ndb.hpp"
-#include "NdbDictionaryImpl.hpp"
-#include "NdbConnection.hpp"
-#include "NdbOperation.hpp"
-#include "NdbIndexOperation.hpp"
-#include "NdbRecAttr.hpp"
-#include "NdbBlob.hpp"
+#include <Ndb.hpp>
+#include <NdbDictionaryImpl.hpp>
+#include <NdbConnection.hpp>
+#include <NdbOperation.hpp>
+#include <NdbIndexOperation.hpp>
+#include <NdbRecAttr.hpp>
+#include <NdbBlob.hpp>
+#include <NdbScanOperation.hpp>
#ifdef NDB_BLOB_DEBUG
#define DBG(x) \
do { \
static const char* p = getenv("NDB_BLOB_DEBUG"); \
if (p == 0 || *p == 0 || *p == '0') break; \
- const char* cname = theColumn == NULL ? "BLOB" : theColumn->m_name.c_str(); \
- ndbout << cname << " " << __LINE__ << " " << x << " " << *this << endl; \
+ static char* prefix = "BLOB"; \
+ const char* cname = theColumn == NULL ? "-" : theColumn->m_name.c_str(); \
+ ndbout << prefix << " " << hex << (void*)this << " " << cname; \
+ ndbout << " " << dec << __LINE__ << " " << x << " " << *this << endl; \
} while (0)
-#define EXE() assert(theNdbCon->executeNoBlobs(NoCommit) == 0)
#else
#define DBG(x)
#endif
@@ -48,7 +50,7 @@ ndb_blob_debug(const Uint32* data, unsigned size)
/*
* Reading index table directly (as a table) is faster but there are
- * bugs or limitations. Keep the code but make possible to choose.
+ * bugs or limitations. Keep the code and make possible to choose.
*/
static const bool g_ndb_blob_ok_to_read_index_table = false;
@@ -81,7 +83,7 @@ NdbBlob::getBlobTableName(char* btname, const NdbTableImpl* t, const NdbColumnIm
{
assert(t != 0 && c != 0 && c->getBlobType());
memset(btname, 0, BlobTableNameSize);
- sprintf(btname, "NDB$BLOB_%d_%d_%d", (int)t->m_tableId, (int)t->m_version, (int)c->m_attrId);
+ sprintf(btname, "NDB$BLOB_%d_%d", (int)t->m_tableId, (int)c->m_attrId);
}
void
@@ -115,7 +117,7 @@ NdbBlob::getBlobTable(NdbTableImpl& bt, const NdbTableImpl* t, const NdbColumnIm
case NdbDictionary::Column::Blob:
bc.setType(NdbDictionary::Column::Binary);
break;
- case NdbDictionary::Column::Clob:
+ case NdbDictionary::Column::Text:
bc.setType(NdbDictionary::Column::Char);
break;
default:
@@ -138,12 +140,12 @@ void
NdbBlob::init()
{
theState = Idle;
- theBlobTableName[0] = 0;
theNdb = NULL;
theNdbCon = NULL;
theNdbOp = NULL;
theTable = NULL;
theAccessTable = NULL;
+ theBlobTable = NULL;
theColumn = NULL;
theFillChar = 0;
theInlineSize = 0;
@@ -154,11 +156,13 @@ NdbBlob::init()
theSetFlag = false;
theSetBuf = NULL;
theGetSetBytes = 0;
+ thePendingBlobOps = 0;
+ theActiveHook = NULL;
+ theActiveHookArg = NULL;
theHead = NULL;
theInlineData = NULL;
theHeadInlineRecAttr = NULL;
theHeadInlineUpdateFlag = false;
- theNewPartFlag = false;
theNullFlag = -1;
theLength = 0;
thePos = 0;
@@ -269,7 +273,7 @@ NdbBlob::isScanOp()
inline Uint32
NdbBlob::getPartNumber(Uint64 pos)
{
- assert(pos >= theInlineSize);
+ assert(thePartSize != 0 && pos >= theInlineSize);
return (pos - theInlineSize) / thePartSize;
}
@@ -301,7 +305,7 @@ NdbBlob::getTableKeyValue(NdbOperation* anOp)
assert(c != NULL);
if (c->m_pk) {
unsigned len = c->m_attrSize * c->m_arraySize;
- if (anOp->getValue(c, (char*)&data[pos]) == NULL) {
+ if (anOp->getValue_impl(c, (char*)&data[pos]) == NULL) {
setErrorCode(anOp);
return -1;
}
@@ -321,10 +325,10 @@ int
NdbBlob::setTableKeyValue(NdbOperation* anOp)
{
const Uint32* data = (const Uint32*)theKeyBuf.data;
+ DBG("setTableKeyValue key=" << ndb_blob_debug(data, theTable->m_sizeOfKeysInWords));
+ const unsigned columns = theTable->m_columns.size();
unsigned pos = 0;
- const unsigned size = theTable->m_columns.size();
- DBG("setTableKeyValue key=" << ndb_blob_debug(data, size));
- for (unsigned i = 0; i < size; i++) {
+ for (unsigned i = 0; i < columns; i++) {
NdbColumnImpl* c = theTable->m_columns[i];
assert(c != NULL);
if (c->m_pk) {
@@ -344,10 +348,10 @@ int
NdbBlob::setAccessKeyValue(NdbOperation* anOp)
{
const Uint32* data = (const Uint32*)theAccessKeyBuf.data;
+ DBG("setAccessKeyValue key=" << ndb_blob_debug(data, theAccessTable->m_sizeOfKeysInWords));
+ const unsigned columns = theAccessTable->m_columns.size();
unsigned pos = 0;
- const unsigned size = theAccessTable->m_columns.size();
- DBG("setAccessKeyValue key=" << ndb_blob_debug(data, size));
- for (unsigned i = 0; i < size; i++) {
+ for (unsigned i = 0; i < columns; i++) {
NdbColumnImpl* c = theAccessTable->m_columns[i];
assert(c != NULL);
if (c->m_pk) {
@@ -382,7 +386,7 @@ int
NdbBlob::getHeadInlineValue(NdbOperation* anOp)
{
DBG("getHeadInlineValue");
- theHeadInlineRecAttr = anOp->getValue(theColumn, theHeadInlineBuf.data);
+ theHeadInlineRecAttr = anOp->getValue_impl(theColumn, theHeadInlineBuf.data);
if (theHeadInlineRecAttr == NULL) {
setErrorCode(anOp);
return -1;
@@ -478,11 +482,27 @@ NdbBlob::setValue(const void* data, Uint32 bytes)
return 0;
}
+// activation hook
+
+int
+NdbBlob::setActiveHook(ActiveHook activeHook, void* arg)
+{
+ DBG("setActiveHook hook=" << hex << (void*)activeHook << " arg=" << hex << arg);
+ if (theState != Prepared) {
+ setErrorCode(ErrState);
+ return -1;
+ }
+ theActiveHook = activeHook;
+ theActiveHookArg = arg;
+ return 0;
+}
+
// misc operations
int
NdbBlob::getNull(bool& isNull)
{
+ DBG("getNull");
if (theState == Prepared && theSetFlag) {
isNull = (theSetBuf == NULL);
return 0;
@@ -519,6 +539,7 @@ NdbBlob::setNull()
int
NdbBlob::getLength(Uint64& len)
{
+ DBG("getLength");
if (theState == Prepared && theSetFlag) {
len = theGetSetBytes;
return 0;
@@ -534,17 +555,17 @@ NdbBlob::getLength(Uint64& len)
int
NdbBlob::truncate(Uint64 length)
{
- DBG("truncate kength=" << length);
+ DBG("truncate length=" << length);
if (theNullFlag == -1) {
setErrorCode(ErrState);
return -1;
}
if (theLength > length) {
- if (length >= theInlineSize) {
- Uint32 part1 = getPartNumber(length);
+ if (length > theInlineSize) {
+ Uint32 part1 = getPartNumber(length - 1);
Uint32 part2 = getPartNumber(theLength - 1);
assert(part2 >= part1);
- if (deleteParts(part1, part2 - part1) == -1)
+ if (part2 > part1 && deleteParts(part1 + 1, part2 - part1) == -1)
return -1;
} else {
if (deleteParts(0, getPartCount()) == -1)
@@ -559,6 +580,7 @@ NdbBlob::truncate(Uint64 length)
int
NdbBlob::getPos(Uint64& pos)
{
+ DBG("getPos");
if (theNullFlag == -1) {
setErrorCode(ErrState);
return -1;
@@ -570,6 +592,7 @@ NdbBlob::getPos(Uint64& pos)
int
NdbBlob::setPos(Uint64 pos)
{
+ DBG("setPos pos=" << pos);
if (theNullFlag == -1) {
setErrorCode(ErrState);
return -1;
@@ -628,6 +651,10 @@ NdbBlob::readDataPrivate(Uint64 pos, char* buf, Uint32& bytes)
len -= n;
}
}
+ if (len > 0 && thePartSize == 0) {
+ setErrorCode(ErrSeek);
+ return -1;
+ }
if (len > 0) {
assert(pos >= theInlineSize);
Uint32 off = (pos - theInlineSize) % thePartSize;
@@ -637,11 +664,10 @@ NdbBlob::readDataPrivate(Uint64 pos, char* buf, Uint32& bytes)
Uint32 part = (pos - theInlineSize) / thePartSize;
if (readParts(thePartBuf.data, part, 1) == -1)
return -1;
- DBG("force execute");
- if (theNdbCon->executeNoBlobs(NoCommit) == -1) {
- setErrorCode(theNdbOp);
+ // need result now
+ DBG("execute pending part reads");
+ if (executePendingBlobReads() == -1)
return -1;
- }
Uint32 n = thePartSize - off;
if (n > len)
n = len;
@@ -672,11 +698,10 @@ NdbBlob::readDataPrivate(Uint64 pos, char* buf, Uint32& bytes)
Uint32 part = (pos - theInlineSize) / thePartSize;
if (readParts(thePartBuf.data, part, 1) == -1)
return -1;
- DBG("force execute");
- if (theNdbCon->executeNoBlobs(NoCommit) == -1) {
- setErrorCode(theNdbOp);
+ // need result now
+ DBG("execute pending part reads");
+ if (executePendingBlobReads() == -1)
return -1;
- }
memcpy(buf, thePartBuf.data, len);
Uint32 n = len;
pos += n;
@@ -735,29 +760,27 @@ NdbBlob::writeDataPrivate(Uint64 pos, const char* buf, Uint32 bytes)
len -= n;
}
}
+ if (len > 0 && thePartSize == 0) {
+ setErrorCode(ErrSeek);
+ return -1;
+ }
if (len > 0) {
assert(pos >= theInlineSize);
Uint32 off = (pos - theInlineSize) % thePartSize;
// partial first block
if (off != 0) {
DBG("partial first block pos=" << pos << " len=" << len);
- if (theNewPartFlag) {
- // must flush insert to guarantee read
- DBG("force execute");
- if (theNdbCon->executeNoBlobs(NoCommit) == -1) {
- setErrorCode(theNdbOp);
- return -1;
- }
- theNewPartFlag = false;
- }
+ // flush writes to guarantee correct read
+ DBG("execute pending part writes");
+ if (executePendingBlobWrites() == -1)
+ return -1;
Uint32 part = (pos - theInlineSize) / thePartSize;
if (readParts(thePartBuf.data, part, 1) == -1)
return -1;
- DBG("force execute");
- if (theNdbCon->executeNoBlobs(NoCommit) == -1) {
- setErrorCode(theNdbOp);
+ // need result now
+ DBG("execute pending part reafs");
+ if (executePendingBlobReads() == -1)
return -1;
- }
Uint32 n = thePartSize - off;
if (n > len) {
memset(thePartBuf.data + off + len, theFillChar, n - len);
@@ -798,22 +821,16 @@ NdbBlob::writeDataPrivate(Uint64 pos, const char* buf, Uint32 bytes)
assert((pos - theInlineSize) % thePartSize == 0 && len < thePartSize);
Uint32 part = (pos - theInlineSize) / thePartSize;
if (theLength > pos + len) {
- if (theNewPartFlag) {
- // must flush insert to guarantee read
- DBG("force execute");
- if (theNdbCon->executeNoBlobs(NoCommit) == -1) {
- setErrorCode(theNdbOp);
- return -1;
- }
- theNewPartFlag = false;
- }
+ // flush writes to guarantee correct read
+ DBG("execute pending part writes");
+ if (executePendingBlobWrites() == -1)
+ return -1;
if (readParts(thePartBuf.data, part, 1) == -1)
return -1;
- DBG("force execute");
- if (theNdbCon->executeNoBlobs(NoCommit) == -1) {
- setErrorCode(theNdbOp);
+ // need result now
+ DBG("execute pending part reads");
+ if (executePendingBlobReads() == -1)
return -1;
- }
memcpy(thePartBuf.data, buf, len);
if (updateParts(thePartBuf.data, part, 1) == -1)
return -1;
@@ -848,7 +865,7 @@ NdbBlob::readParts(char* buf, Uint32 part, Uint32 count)
DBG("readParts part=" << part << " count=" << count);
Uint32 n = 0;
while (n < count) {
- NdbOperation* tOp = theNdbCon->getNdbOperation(theBlobTableName);
+ NdbOperation* tOp = theNdbCon->getNdbOperation(theBlobTable);
if (tOp == NULL ||
tOp->readTuple() == -1 ||
setPartKeyValue(tOp, part + n) == -1 ||
@@ -858,6 +875,8 @@ NdbBlob::readParts(char* buf, Uint32 part, Uint32 count)
}
buf += thePartSize;
n++;
+ thePendingBlobOps |= (1 << NdbOperation::ReadRequest);
+ theNdbCon->thePendingBlobOps |= (1 << NdbOperation::ReadRequest);
}
return 0;
}
@@ -868,7 +887,7 @@ NdbBlob::insertParts(const char* buf, Uint32 part, Uint32 count)
DBG("insertParts part=" << part << " count=" << count);
Uint32 n = 0;
while (n < count) {
- NdbOperation* tOp = theNdbCon->getNdbOperation(theBlobTableName);
+ NdbOperation* tOp = theNdbCon->getNdbOperation(theBlobTable);
if (tOp == NULL ||
tOp->insertTuple() == -1 ||
setPartKeyValue(tOp, part + n) == -1 ||
@@ -878,7 +897,8 @@ NdbBlob::insertParts(const char* buf, Uint32 part, Uint32 count)
}
buf += thePartSize;
n++;
- theNewPartFlag = true;
+ thePendingBlobOps |= (1 << NdbOperation::InsertRequest);
+ theNdbCon->thePendingBlobOps |= (1 << NdbOperation::InsertRequest);
}
return 0;
}
@@ -889,7 +909,7 @@ NdbBlob::updateParts(const char* buf, Uint32 part, Uint32 count)
DBG("updateParts part=" << part << " count=" << count);
Uint32 n = 0;
while (n < count) {
- NdbOperation* tOp = theNdbCon->getNdbOperation(theBlobTableName);
+ NdbOperation* tOp = theNdbCon->getNdbOperation(theBlobTable);
if (tOp == NULL ||
tOp->updateTuple() == -1 ||
setPartKeyValue(tOp, part + n) == -1 ||
@@ -899,7 +919,8 @@ NdbBlob::updateParts(const char* buf, Uint32 part, Uint32 count)
}
buf += thePartSize;
n++;
- theNewPartFlag = true;
+ thePendingBlobOps |= (1 << NdbOperation::UpdateRequest);
+ theNdbCon->thePendingBlobOps |= (1 << NdbOperation::UpdateRequest);
}
return 0;
}
@@ -910,7 +931,7 @@ NdbBlob::deleteParts(Uint32 part, Uint32 count)
DBG("deleteParts part=" << part << " count=" << count);
Uint32 n = 0;
while (n < count) {
- NdbOperation* tOp = theNdbCon->getNdbOperation(theBlobTableName);
+ NdbOperation* tOp = theNdbCon->getNdbOperation(theBlobTable);
if (tOp == NULL ||
tOp->deleteTuple() == -1 ||
setPartKeyValue(tOp, part + n) == -1) {
@@ -918,6 +939,52 @@ NdbBlob::deleteParts(Uint32 part, Uint32 count)
return -1;
}
n++;
+ thePendingBlobOps |= (1 << NdbOperation::DeleteRequest);
+ theNdbCon->thePendingBlobOps |= (1 << NdbOperation::DeleteRequest);
+ }
+ return 0;
+}
+
+// pending ops
+
+int
+NdbBlob::executePendingBlobReads()
+{
+ Uint8 flags = (1 << NdbOperation::ReadRequest);
+ if (thePendingBlobOps & flags) {
+ if (theNdbCon->executeNoBlobs(NoCommit) == -1)
+ return -1;
+ thePendingBlobOps = 0;
+ theNdbCon->thePendingBlobOps = 0;
+ }
+ return 0;
+}
+
+int
+NdbBlob::executePendingBlobWrites()
+{
+ Uint8 flags = 0xFF & ~(1 << NdbOperation::ReadRequest);
+ if (thePendingBlobOps & flags) {
+ if (theNdbCon->executeNoBlobs(NoCommit) == -1)
+ return -1;
+ thePendingBlobOps = 0;
+ theNdbCon->thePendingBlobOps = 0;
+ }
+ return 0;
+}
+
+// callbacks
+
+int
+NdbBlob::invokeActiveHook()
+{
+ DBG("invokeActiveHook");
+ assert(theState == Active && theActiveHook != NULL);
+ int ret = (*theActiveHook)(this, theActiveHookArg);
+ DBG("invokeActiveHook ret=" << ret);
+ if (ret != 0) {
+ // no error is set on blob level
+ return -1;
}
return 0;
}
@@ -947,7 +1014,7 @@ NdbBlob::atPrepare(NdbConnection* aCon, NdbOperation* anOp, const NdbColumnImpl*
partType = NdbDictionary::Column::Binary;
theFillChar = 0x0;
break;
- case NdbDictionary::Column::Clob:
+ case NdbDictionary::Column::Text:
partType = NdbDictionary::Column::Char;
theFillChar = 0x20;
break;
@@ -959,22 +1026,21 @@ NdbBlob::atPrepare(NdbConnection* aCon, NdbOperation* anOp, const NdbColumnImpl*
theInlineSize = theColumn->getInlineSize();
thePartSize = theColumn->getPartSize();
theStripeSize = theColumn->getStripeSize();
- // blob table sanity check
+ // sanity check
assert((NDB_BLOB_HEAD_SIZE << 2) == sizeof(Head));
assert(theColumn->m_attrSize * theColumn->m_arraySize == sizeof(Head) + theInlineSize);
- getBlobTableName(theBlobTableName, theTable, theColumn);
- const NdbDictionary::Table* bt;
- const NdbDictionary::Column* bc;
- if (theInlineSize >= (1 << 16) ||
- thePartSize == 0 ||
- thePartSize >= (1 << 16) ||
- theStripeSize == 0 ||
- (bt = theNdb->theDictionary->getTable(theBlobTableName)) == NULL ||
- (bc = bt->getColumn("DATA")) == NULL ||
- bc->getType() != partType ||
- bc->getLength() != (int)thePartSize) {
- setErrorCode(ErrTable);
- return -1;
+ if (thePartSize > 0) {
+ const NdbDictionary::Table* bt = NULL;
+ const NdbDictionary::Column* bc = NULL;
+ if (theStripeSize == 0 ||
+ (bt = theColumn->getBlobTable()) == NULL ||
+ (bc = bt->getColumn("DATA")) == NULL ||
+ bc->getType() != partType ||
+ bc->getLength() != (int)thePartSize) {
+ setErrorCode(ErrTable);
+ return -1;
+ }
+ theBlobTable = &NdbTableImpl::getImpl(*bt);
}
// buffers
theKeyBuf.alloc(theTable->m_sizeOfKeysInWords << 2);
@@ -1060,7 +1126,7 @@ NdbBlob::preExecute(ExecType anExecType, bool& batch)
Uint32 bytes = theGetSetBytes - theInlineSize;
if (writeDataPrivate(pos, buf, bytes) == -1)
return -1;
- if (anExecType == Commit && theHeadInlineUpdateFlag) {
+ if (theHeadInlineUpdateFlag) {
// add an operation to update head+inline
NdbOperation* tOp = theNdbCon->getNdbOperation(theTable);
if (tOp == NULL ||
@@ -1128,6 +1194,10 @@ NdbBlob::preExecute(ExecType anExecType, bool& batch)
batch = true;
}
}
+ if (theActiveHook != NULL) {
+ // need blob head for callback
+ batch = true;
+ }
DBG("preExecute out batch=" << batch);
return 0;
}
@@ -1144,8 +1214,11 @@ NdbBlob::postExecute(ExecType anExecType)
DBG("postExecute type=" << anExecType);
if (theState == Invalid)
return -1;
- if (theState == Active)
+ if (theState == Active) {
+ setState(anExecType == NoCommit ? Active : Closed);
+ DBG("postExecute skip");
return 0;
+ }
assert(theState == Prepared);
assert(isKeyOp());
if (isIndexOp()) {
@@ -1199,8 +1272,12 @@ NdbBlob::postExecute(ExecType anExecType)
if (deleteParts(0, getPartCount()) == -1)
return -1;
}
- theNewPartFlag = false;
setState(anExecType == NoCommit ? Active : Closed);
+ // activation callback
+ if (theActiveHook != NULL) {
+ if (invokeActiveHook() == -1)
+ return -1;
+ }
DBG("postExecute out");
return 0;
}
@@ -1250,7 +1327,7 @@ NdbBlob::atNextResult()
// get primary key
{ Uint32* data = (Uint32*)theKeyBuf.data;
unsigned size = theTable->m_sizeOfKeysInWords;
- if (theNdbOp->getKeyFromKEYINFO20(data, size) == -1) {
+ if (((NdbScanOperation*)theNdbOp)->getKeyFromKEYINFO20(data, size) == -1) {
setErrorCode(ErrUsage);
return -1;
}
@@ -1274,20 +1351,18 @@ NdbBlob::atNextResult()
Uint32 bytes = theGetSetBytes - theInlineSize;
if (readDataPrivate(pos, buf, bytes) == -1)
return -1;
- // must also execute them
- DBG("force execute");
- if (theNdbCon->executeNoBlobs(NoCommit) == -1) {
- setErrorCode((NdbOperation*)0);
- return -1;
- }
}
}
setState(Active);
+ // activation callback
+ if (theActiveHook != NULL) {
+ if (invokeActiveHook() == -1)
+ return -1;
+ }
DBG("atNextResult out");
return 0;
}
-
// misc
const NdbDictionary::Column*
@@ -1303,6 +1378,9 @@ NdbBlob::setErrorCode(int anErrorCode, bool invalidFlag)
{
DBG("setErrorCode code=" << anErrorCode);
theError.code = anErrorCode;
+ // conditionally copy error to operation level
+ if (theNdbOp != NULL && theNdbOp->theError.code == 0)
+ theNdbOp->setErrorCode(theError.code);
if (invalidFlag)
setState(Invalid);
}
@@ -1335,11 +1413,34 @@ NdbBlob::setErrorCode(NdbConnection* aCon, bool invalidFlag)
setErrorCode(code, invalidFlag);
}
+// info about all blobs in this operation
+
+NdbBlob*
+NdbBlob::blobsFirstBlob()
+{
+ return theNdbOp->theBlobList;
+}
+
+NdbBlob*
+NdbBlob::blobsNextBlob()
+{
+ return theNext;
+}
+
+// debug
+
#ifdef VM_TRACE
+inline int
+NdbBlob::getOperationType() const
+{
+ return theNdbOp != NULL ? theNdbOp->theOperationType : -1;
+}
+
NdbOut&
operator<<(NdbOut& out, const NdbBlob& blob)
{
- ndbout << dec << "s=" << blob.theState;
+ ndbout << dec << "o=" << blob.getOperationType();
+ ndbout << dec << " s=" << blob.theState;
ndbout << dec << " n=" << blob.theNullFlag;;
ndbout << dec << " l=" << blob.theLength;
ndbout << dec << " p=" << blob.thePos;
diff --git a/ndb/src/ndbapi/NdbConnection.cpp b/ndb/src/ndbapi/NdbConnection.cpp
index ad415b8acbf..9a2995a957e 100644
--- a/ndb/src/ndbapi/NdbConnection.cpp
+++ b/ndb/src/ndbapi/NdbConnection.cpp
@@ -27,11 +27,12 @@ Description: Interface between TIS and NDB
Documentation:
Adjust: 971022 UABMNST First version.
*****************************************************************************/
-#include "NdbOut.hpp"
-#include "NdbConnection.hpp"
-#include "NdbOperation.hpp"
-#include "NdbScanOperation.hpp"
-#include "NdbIndexOperation.hpp"
+#include <NdbOut.hpp>
+#include <NdbConnection.hpp>
+#include <NdbOperation.hpp>
+#include <NdbScanOperation.hpp>
+#include <NdbIndexScanOperation.hpp>
+#include <NdbIndexOperation.hpp>
#include "NdbApiSignal.hpp"
#include "TransporterFacade.hpp"
#include "API.hpp"
@@ -80,18 +81,16 @@ NdbConnection::NdbConnection( Ndb* aNdb ) :
theTransactionIsStarted(false),
theDBnode(0),
theReleaseOnClose(false),
- // Cursor operations
+ // Scan operations
m_waitForReply(true),
- m_theFirstCursorOperation(NULL),
- m_theLastCursorOperation(NULL),
- m_firstExecutedCursorOp(NULL),
+ m_theFirstScanOperation(NULL),
+ m_theLastScanOperation(NULL),
+ m_firstExecutedScanOp(NULL),
// Scan operations
- theScanFinished(0),
- theCurrentScanRec(NULL),
- thePreviousScanRec(NULL),
theScanningOp(NULL),
theBuddyConPtr(0xFFFFFFFF),
- theBlobFlag(false)
+ theBlobFlag(false),
+ thePendingBlobOps(0)
{
theListState = NotInList;
theError.code = 0;
@@ -119,7 +118,6 @@ NdbConnection::init()
theListState = NotInList;
theInUseState = true;
theTransactionIsStarted = false;
- theScanFinished = 0;
theNext = NULL;
theFirstOpInList = NULL;
@@ -130,9 +128,6 @@ NdbConnection::init()
theFirstExecOpInList = NULL;
theLastExecOpInList = NULL;
- theCurrentScanRec = NULL;
- thePreviousScanRec = NULL;
-
theCompletedFirstOp = NULL;
theGlobalCheckpointId = 0;
@@ -148,14 +143,15 @@ NdbConnection::init()
theSimpleState = true;
theSendStatus = InitState;
theMagicNumber = 0x37412619;
- // Cursor operations
+ // Scan operations
m_waitForReply = true;
- m_theFirstCursorOperation = NULL;
- m_theLastCursorOperation = NULL;
- m_firstExecutedCursorOp = 0;
+ m_theFirstScanOperation = NULL;
+ m_theLastScanOperation = NULL;
+ m_firstExecutedScanOp = 0;
theBuddyConPtr = 0xFFFFFFFF;
//
theBlobFlag = false;
+ thePendingBlobOps = 0;
}//NdbConnection::init()
/*****************************************************************************
@@ -203,6 +199,23 @@ NdbConnection::setErrorCode(int anErrorCode)
theError.code = anErrorCode;
}//NdbConnection::setErrorCode()
+int
+NdbConnection::restart(){
+ if(theCompletionStatus == CompletedSuccess){
+ releaseCompletedOperations();
+ Uint64 tTransid = theNdb->theFirstTransId;
+ theTransactionId = tTransid;
+ if ((tTransid & 0xFFFFFFFF) == 0xFFFFFFFF) {
+ theNdb->theFirstTransId = (tTransid >> 32) << 32;
+ } else {
+ theNdb->theFirstTransId = tTransid + 1;
+ }
+ theCompletionStatus = NotCompleted;
+ return 0;
+ }
+ return -1;
+}
+
/*****************************************************************************
void handleExecuteCompletion(void);
@@ -258,26 +271,34 @@ NdbConnection::execute(ExecType aTypeOfExec,
if (! theBlobFlag)
return executeNoBlobs(aTypeOfExec, abortOption, forceSend);
- // execute prepared ops in batches, as requested by blobs
+ /*
+ * execute prepared ops in batches, as requested by blobs
+ * - blob error does not terminate execution
+ * - blob error sets error on operation
+ * - if error on operation skip blob calls
+ */
ExecType tExecType;
NdbOperation* tPrepOp;
+ int ret = 0;
do {
tExecType = aTypeOfExec;
tPrepOp = theFirstOpInList;
while (tPrepOp != NULL) {
- bool batch = false;
- NdbBlob* tBlob = tPrepOp->theBlobList;
- while (tBlob != NULL) {
- if (tBlob->preExecute(tExecType, batch) == -1)
- return -1;
- tBlob = tBlob->theNext;
- }
- if (batch) {
- // blob asked to execute all up to here now
- tExecType = NoCommit;
- break;
+ if (tPrepOp->theError.code == 0) {
+ bool batch = false;
+ NdbBlob* tBlob = tPrepOp->theBlobList;
+ while (tBlob != NULL) {
+ if (tBlob->preExecute(tExecType, batch) == -1)
+ ret = -1;
+ tBlob = tBlob->theNext;
+ }
+ if (batch) {
+ // blob asked to execute all up to here now
+ tExecType = NoCommit;
+ break;
+ }
}
tPrepOp = tPrepOp->next();
}
@@ -293,26 +314,30 @@ NdbConnection::execute(ExecType aTypeOfExec,
if (tExecType == Commit) {
NdbOperation* tOp = theCompletedFirstOp;
while (tOp != NULL) {
- NdbBlob* tBlob = tOp->theBlobList;
- while (tBlob != NULL) {
- if (tBlob->preCommit() == -1)
- return -1;
- tBlob = tBlob->theNext;
+ if (tOp->theError.code == 0) {
+ NdbBlob* tBlob = tOp->theBlobList;
+ while (tBlob != NULL) {
+ if (tBlob->preCommit() == -1)
+ ret = -1;
+ tBlob = tBlob->theNext;
+ }
}
tOp = tOp->next();
}
}
if (executeNoBlobs(tExecType, abortOption, forceSend) == -1)
- return -1;
+ ret = -1;
{
NdbOperation* tOp = theCompletedFirstOp;
while (tOp != NULL) {
- NdbBlob* tBlob = tOp->theBlobList;
- while (tBlob != NULL) {
- // may add new operations if batch
- if (tBlob->postExecute(tExecType) == -1)
- return -1;
- tBlob = tBlob->theNext;
+ if (tOp->theError.code == 0) {
+ NdbBlob* tBlob = tOp->theBlobList;
+ while (tBlob != NULL) {
+ // may add new operations if batch
+ if (tBlob->postExecute(tExecType) == -1)
+ ret = -1;
+ tBlob = tBlob->theNext;
+ }
}
tOp = tOp->next();
}
@@ -327,7 +352,7 @@ NdbConnection::execute(ExecType aTypeOfExec,
}
} while (theFirstOpInList != NULL || tExecType != aTypeOfExec);
- return 0;
+ return ret;
}
int
@@ -386,6 +411,7 @@ NdbConnection::executeNoBlobs(ExecType aTypeOfExec,
break;
}
}
+ thePendingBlobOps = 0;
return 0;
}//NdbConnection::execute()
@@ -414,7 +440,7 @@ NdbConnection::executeAsynchPrepare( ExecType aTypeOfExec,
* Reset error.code on execute
*/
theError.code = 0;
- NdbCursorOperation* tcOp = m_theFirstCursorOperation;
+ NdbScanOperation* tcOp = m_theFirstScanOperation;
if (tcOp != 0){
// Execute any cursor operations
while (tcOp != NULL) {
@@ -423,14 +449,14 @@ NdbConnection::executeAsynchPrepare( ExecType aTypeOfExec,
if (tReturnCode == -1) {
return;
}//if
- tcOp = (NdbCursorOperation*)tcOp->next();
+ tcOp = (NdbScanOperation*)tcOp->next();
} // while
- m_theLastCursorOperation->next(m_firstExecutedCursorOp);
- m_firstExecutedCursorOp = m_theFirstCursorOperation;
+ m_theLastScanOperation->next(m_firstExecutedScanOp);
+ m_firstExecutedScanOp = m_theFirstScanOperation;
// Discard cursor operations, since these are also
// in the complete operations list we do not need
// to release them.
- m_theFirstCursorOperation = m_theLastCursorOperation = NULL;
+ m_theFirstScanOperation = m_theLastScanOperation = NULL;
}
bool tTransactionIsStarted = theTransactionIsStarted;
@@ -797,17 +823,14 @@ Remark: Release all operations.
******************************************************************************/
void
NdbConnection::release(){
- if (theTransactionIsStarted == true && theScanningOp != NULL )
- stopScan();
-
releaseOperations();
if ( (theTransactionIsStarted == true) &&
- ((theCommitStatus != Committed) &&
- (theCommitStatus != Aborted))) {
-/****************************************************************************
- * The user did not perform any rollback but simply closed the
- * transaction. We must rollback Ndb since Ndb have been contacted.
-******************************************************************************/
+ ((theCommitStatus != Committed) &&
+ (theCommitStatus != Aborted))) {
+ /************************************************************************
+ * The user did not perform any rollback but simply closed the
+ * transaction. We must rollback Ndb since Ndb have been contacted.
+ ************************************************************************/
execute(Rollback);
}//if
theMagicNumber = 0xFE11DC;
@@ -839,8 +862,8 @@ void
NdbConnection::releaseOperations()
{
// Release any open scans
- releaseCursorOperations(m_theFirstCursorOperation);
- releaseCursorOperations(m_firstExecutedCursorOp);
+ releaseScanOperations(m_theFirstScanOperation);
+ releaseScanOperations(m_firstExecutedScanOp);
releaseOps(theCompletedFirstOp);
releaseOps(theFirstOpInList);
@@ -852,9 +875,9 @@ NdbConnection::releaseOperations()
theLastOpInList = NULL;
theLastExecOpInList = NULL;
theScanningOp = NULL;
- m_theFirstCursorOperation = NULL;
- m_theLastCursorOperation = NULL;
- m_firstExecutedCursorOp = NULL;
+ m_theFirstScanOperation = NULL;
+ m_theLastScanOperation = NULL;
+ m_firstExecutedScanOp = NULL;
}//NdbConnection::releaseOperations()
void
@@ -865,24 +888,21 @@ NdbConnection::releaseCompletedOperations()
}//NdbConnection::releaseOperations()
/******************************************************************************
-void releaseCursorOperations();
+void releaseScanOperations();
Remark: Release all cursor operations.
(NdbScanOperation and NdbIndexOperation)
******************************************************************************/
void
-NdbConnection::releaseCursorOperations(NdbCursorOperation* cursorOp)
+NdbConnection::releaseScanOperations(NdbIndexScanOperation* cursorOp)
{
while(cursorOp != 0){
- NdbCursorOperation* next = (NdbCursorOperation*)cursorOp->next();
+ NdbIndexScanOperation* next = (NdbIndexScanOperation*)cursorOp->next();
cursorOp->release();
- if (cursorOp->cursorType() == NdbCursorOperation::ScanCursor)
- theNdb->releaseScanOperation((NdbScanOperation*)cursorOp);
- else
- theNdb->releaseOperation(cursorOp);
+ theNdb->releaseScanOperation(cursorOp);
cursorOp = next;
}
-}//NdbConnection::releaseCursorOperations()
+}//NdbConnection::releaseScanOperations()
/*****************************************************************************
NdbOperation* getNdbOperation(const char* aTableName);
@@ -916,45 +936,6 @@ NdbConnection::getNdbOperation(const char* aTableName)
}//NdbConnection::getNdbOperation()
/*****************************************************************************
-NdbOperation* getNdbOperation(const char* anIndexName, const char* aTableName);
-
-Return Value Return a pointer to a NdbOperation object if getNdbOperation
- was succesful.
- Return NULL : In all other case.
-Parameters: anIndexName : Name of the index to use.
- aTableName : Name of the database table.
-Remark: Get an operation from NdbOperation idlelist and get the
- NdbConnection object
- who was fetch by startTransaction pointing to this operation
- getOperation will set the theTableId in the NdbOperation object.
- synchronous
-******************************************************************************/
-NdbOperation*
-NdbConnection::getNdbOperation(const char* anIndexName, const char* aTableName)
-{
- if ((theError.code == 0) &&
- (theCommitStatus == Started)){
- NdbIndexImpl* index =
- theNdb->theDictionary->getIndex(anIndexName, aTableName);
- NdbTableImpl* table = theNdb->theDictionary->getTable(aTableName);
- NdbTableImpl* indexTable =
- theNdb->theDictionary->getIndexTable(index, table);
- if (indexTable != 0){
- return getNdbOperation(indexTable);
- } else {
- setErrorCode(theNdb->theDictionary->getNdbError().code);
- return NULL;
- }//if
- } else {
- if (theError.code == 0) {
- setOperationErrorCodeAbort(4114);
- }//if
-
- return NULL;
- }//if
-}//NdbConnection::getNdbOperation()
-
-/*****************************************************************************
NdbOperation* getNdbOperation(int aTableId);
Return Value Return a pointer to a NdbOperation object if getNdbOperation
@@ -1014,6 +995,14 @@ NdbConnection::getNdbOperation(NdbTableImpl * tab, NdbOperation* aNextOp)
return NULL;
}//NdbConnection::getNdbOperation()
+NdbOperation* NdbConnection::getNdbOperation(NdbDictionary::Table * table)
+{
+ if (table)
+ return getNdbOperation(& NdbTableImpl::getImpl(*table));
+ else
+ return NULL;
+}//NdbConnection::getNdbOperation()
+
// NdbScanOperation
/*****************************************************************************
NdbScanOperation* getNdbScanOperation(const char* aTableName);
@@ -1033,7 +1022,7 @@ NdbConnection::getNdbScanOperation(const char* aTableName)
if (tab != 0){
return getNdbScanOperation(tab);
} else {
- setOperationErrorCodeAbort(theNdb->theError.code);
+ setOperationErrorCodeAbort(theNdb->theDictionary->m_error.code);
return NULL;
}//if
}
@@ -1053,17 +1042,29 @@ Remark: Get an operation from NdbScanOperation idlelist and get the NdbC
who was fetch by startTransaction pointing to this operation
getOperation will set the theTableId in the NdbOperation object.synchronous
******************************************************************************/
-NdbScanOperation*
-NdbConnection::getNdbScanOperation(const char* anIndexName, const char* aTableName)
+NdbIndexScanOperation*
+NdbConnection::getNdbIndexScanOperation(const char* anIndexName,
+ const char* aTableName)
+{
+ NdbIndexImpl* index =
+ theNdb->theDictionary->getIndex(anIndexName, aTableName);
+ NdbTableImpl* table = theNdb->theDictionary->getTable(aTableName);
+
+ return getNdbIndexScanOperation(index, table);
+}
+
+NdbIndexScanOperation*
+NdbConnection::getNdbIndexScanOperation(NdbIndexImpl* index,
+ NdbTableImpl* table)
{
if (theCommitStatus == Started){
- NdbIndexImpl* index =
- theNdb->theDictionary->getIndex(anIndexName, aTableName);
- NdbTableImpl* table = theNdb->theDictionary->getTable(aTableName);
- NdbTableImpl* indexTable =
- theNdb->theDictionary->getIndexTable(index, table);
+ const NdbTableImpl * indexTable = index->getIndexTable();
if (indexTable != 0){
- return getNdbScanOperation(indexTable);
+ NdbIndexScanOperation* tOp =
+ getNdbScanOperation((NdbTableImpl *) indexTable);
+ tOp->m_currentTable = table;
+ if(tOp) tOp->m_cursor_type = NdbScanOperation::IndexCursor;
+ return tOp;
} else {
setOperationErrorCodeAbort(theNdb->theError.code);
return NULL;
@@ -1072,7 +1073,18 @@ NdbConnection::getNdbScanOperation(const char* anIndexName, const char* aTableNa
setOperationErrorCodeAbort(4114);
return NULL;
-}//NdbConnection::getNdbScanOperation()
+}//NdbConnection::getNdbIndexScanOperation()
+
+NdbIndexScanOperation*
+NdbConnection::getNdbIndexScanOperation(NdbDictionary::Index * index,
+ NdbDictionary::Table * table)
+{
+ if (index && table)
+ return getNdbIndexScanOperation(& NdbIndexImpl::getImpl(*index),
+ & NdbTableImpl::getImpl(*table));
+ else
+ return NULL;
+}//NdbConnection::getNdbIndexScanOperation()
/*****************************************************************************
NdbScanOperation* getNdbScanOperation(int aTableId);
@@ -1084,21 +1096,21 @@ Remark: Get an operation from NdbScanOperation object idlelist and get t
object who was fetch by startTransaction pointing to this operation
getOperation will set the theTableId in the NdbOperation object, synchronous.
*****************************************************************************/
-NdbScanOperation*
+NdbIndexScanOperation*
NdbConnection::getNdbScanOperation(NdbTableImpl * tab)
{
- NdbScanOperation* tOp;
+ NdbIndexScanOperation* tOp;
tOp = theNdb->getScanOperation();
if (tOp == NULL)
goto getNdbOp_error1;
// Link scan operation into list of cursor operations
- if (m_theLastCursorOperation == NULL)
- m_theFirstCursorOperation = m_theLastCursorOperation = tOp;
+ if (m_theLastScanOperation == NULL)
+ m_theFirstScanOperation = m_theLastScanOperation = tOp;
else {
- m_theLastCursorOperation->next(tOp);
- m_theLastCursorOperation = tOp;
+ m_theLastScanOperation->next(tOp);
+ m_theLastScanOperation = tOp;
}
tOp->next(NULL);
if (tOp->init(tab, this) != -1) {
@@ -1113,6 +1125,14 @@ getNdbOp_error1:
return NULL;
}//NdbConnection::getNdbScanOperation()
+NdbScanOperation*
+NdbConnection::getNdbScanOperation(NdbDictionary::Table * table)
+{
+ if (table)
+ return getNdbScanOperation(& NdbTableImpl::getImpl(*table));
+ else
+ return NULL;
+}//NdbConnection::getNdbScanOperation()
// IndexOperation
@@ -1207,6 +1227,18 @@ NdbConnection::getNdbIndexOperation(NdbIndexImpl * anIndex,
return NULL;
}//NdbConnection::getNdbIndexOperation()
+NdbIndexOperation*
+NdbConnection::getNdbIndexOperation(NdbDictionary::Index * index,
+ NdbDictionary::Table * table)
+{
+ if (index && table)
+ return getNdbIndexOperation(& NdbIndexImpl::getImpl(*index),
+ & NdbTableImpl::getImpl(*table));
+ else
+ return NULL;
+}//NdbConnection::getNdbIndexOperation()
+
+
/*******************************************************************************
int receiveDIHNDBTAMPER(NdbApiSignal* aSignal)
@@ -1323,12 +1355,16 @@ Remark:
int
NdbConnection::receiveTC_COMMITCONF(const TcCommitConf * commitConf)
{
- if(theStatus != Connected){
- return -1;
+ if(checkState_TransId(&commitConf->transId1)){
+ theCommitStatus = Committed;
+ theCompletionStatus = CompletedSuccess;
+ return 0;
+ } else {
+#ifdef NDB_NO_DROPPED_SIGNAL
+ abort();
+#endif
}
- theCommitStatus = Committed;
- theCompletionStatus = CompletedSuccess;
- return 0;
+ return -1;
}//NdbConnection::receiveTC_COMMITCONF()
/******************************************************************************
@@ -1342,33 +1378,43 @@ Remark:
int
NdbConnection::receiveTC_COMMITREF(NdbApiSignal* aSignal)
{
- if(theStatus != Connected){
- return -1;
+ const TcCommitRef * ref = CAST_CONSTPTR(TcCommitRef, aSignal->getDataPtr());
+ if(checkState_TransId(&ref->transId1)){
+ setOperationErrorCodeAbort(ref->errorCode);
+ theCommitStatus = Aborted;
+ theCompletionStatus = CompletedFailure;
+ return 0;
+ } else {
+#ifdef NDB_NO_DROPPED_SIGNAL
+ abort();
+#endif
}
- const TcCommitRef * const ref = CAST_CONSTPTR(TcCommitRef, aSignal->getDataPtr());
- setOperationErrorCodeAbort(ref->errorCode);
- theCommitStatus = Aborted;
- theCompletionStatus = CompletedFailure;
- return 0;
+
+ return -1;
}//NdbConnection::receiveTC_COMMITREF()
-/*******************************************************************************
+/******************************************************************************
int receiveTCROLLBACKCONF(NdbApiSignal* aSignal);
Return Value: Return 0 : receiveTCROLLBACKCONF was successful.
Return -1: In all other case.
Parameters: aSignal: The signal object pointer.
Remark:
-*******************************************************************************/
+******************************************************************************/
int
NdbConnection::receiveTCROLLBACKCONF(NdbApiSignal* aSignal)
{
- if(theStatus != Connected){
- return -1;
+ if(checkState_TransId(aSignal->getDataPtr() + 1)){
+ theCommitStatus = Aborted;
+ theCompletionStatus = CompletedSuccess;
+ return 0;
+ } else {
+#ifdef NDB_NO_DROPPED_SIGNAL
+ abort();
+#endif
}
- theCommitStatus = Aborted;
- theCompletionStatus = CompletedSuccess;
- return 0;
+
+ return -1;
}//NdbConnection::receiveTCROLLBACKCONF()
/*******************************************************************************
@@ -1382,13 +1428,18 @@ Remark:
int
NdbConnection::receiveTCROLLBACKREF(NdbApiSignal* aSignal)
{
- if(theStatus != Connected){
- return -1;
+ if(checkState_TransId(aSignal->getDataPtr() + 1)){
+ setOperationErrorCodeAbort(aSignal->readData(4));
+ theCommitStatus = Aborted;
+ theCompletionStatus = CompletedFailure;
+ return 0;
+ } else {
+#ifdef NDB_NO_DROPPED_SIGNAL
+ abort();
+#endif
}
- setOperationErrorCodeAbort(aSignal->readData(2));
- theCommitStatus = Aborted;
- theCompletionStatus = CompletedFailure;
- return 0;
+
+ return -1;
}//NdbConnection::receiveTCROLLBACKREF()
/*****************************************************************************
@@ -1403,36 +1454,31 @@ Remark: Handles the reception of the ROLLBACKREP signal.
int
NdbConnection::receiveTCROLLBACKREP( NdbApiSignal* aSignal)
{
- Uint64 tRecTransId, tCurrTransId;
- Uint32 tTmp1, tTmp2;
-
- if (theStatus != Connected) {
- return -1;
- }//if
-/*****************************************************************************
+ /****************************************************************************
Check that we are expecting signals from this transaction and that it doesn't
belong to a transaction already completed. Simply ignore messages from other
transactions.
-******************************************************************************/
- tTmp1 = aSignal->readData(2);
- tTmp2 = aSignal->readData(3);
- tRecTransId = (Uint64)tTmp1 + ((Uint64)tTmp2 << 32);
- tCurrTransId = this->getTransactionId();
- if (tCurrTransId != tRecTransId) {
- return -1;
- }//if
- theError.code = aSignal->readData(4); // Override any previous errors
+ ****************************************************************************/
+ if(checkState_TransId(aSignal->getDataPtr() + 1)){
+ theError.code = aSignal->readData(4);// Override any previous errors
+
+ /**********************************************************************/
+ /* A serious error has occured. This could be due to deadlock or */
+ /* lack of resources or simply a programming error in NDB. This */
+ /* transaction will be aborted. Actually it has already been */
+ /* and we only need to report completion and return with the */
+ /* error code to the application. */
+ /**********************************************************************/
+ theCompletionStatus = CompletedFailure;
+ theCommitStatus = Aborted;
+ return 0;
+ } else {
+#ifdef NDB_NO_DROPPED_SIGNAL
+ abort();
+#endif
+ }
-/**********************************************************************/
-/* A serious error has occured. This could be due to deadlock or */
-/* lack of resources or simply a programming error in NDB. This */
-/* transaction will be aborted. Actually it has already been */
-/* and we only need to report completion and return with the */
-/* error code to the application. */
-/**********************************************************************/
- theCompletionStatus = CompletedFailure;
- theCommitStatus = Aborted;
- return 0;
+ return -1;
}//NdbConnection::receiveTCROLLBACKREP()
/*******************************************************************************
@@ -1446,49 +1492,50 @@ Remark:
int
NdbConnection::receiveTCKEYCONF(const TcKeyConf * keyConf, Uint32 aDataLength)
{
- Uint64 tRecTransId;
- NdbOperation* tOp;
- Uint32 tConditionFlag;
-
+ NdbReceiver* tOp;
const Uint32 tTemp = keyConf->confInfo;
- const Uint32 tTmp1 = keyConf->transId1;
- const Uint32 tTmp2 = keyConf->transId2;
-/******************************************************************************
+ /***************************************************************************
Check that we are expecting signals from this transaction and that it
doesn't belong to a transaction already completed. Simply ignore messages
from other transactions.
-******************************************************************************/
- tRecTransId = (Uint64)tTmp1 + ((Uint64)tTmp2 << 32);
+ ***************************************************************************/
+ if(checkState_TransId(&keyConf->transId1)){
- const Uint32 tNoOfOperations = TcKeyConf::getNoOfOperations(tTemp);
- const Uint32 tCommitFlag = TcKeyConf::getCommitFlag(tTemp);
- tConditionFlag = (Uint32)(((aDataLength - 5) >> 1) - tNoOfOperations);
- tConditionFlag |= (Uint32)(tNoOfOperations > 10);
- tConditionFlag |= (Uint32)(tNoOfOperations <= 0);
- tConditionFlag |= (Uint32)(theTransactionId - tRecTransId);
- tConditionFlag |= (Uint32)(theStatus - Connected);
+ const Uint32 tNoOfOperations = TcKeyConf::getNoOfOperations(tTemp);
+ const Uint32 tCommitFlag = TcKeyConf::getCommitFlag(tTemp);
- if (tConditionFlag == 0) {
const Uint32* tPtr = (Uint32 *)&keyConf->operations[0];
+ Uint32 tNoComp = theNoOfOpCompleted;
for (Uint32 i = 0; i < tNoOfOperations ; i++) {
- tOp = theNdb->void2rec_op(theNdb->int2void(*tPtr));
+ tOp = theNdb->void2rec(theNdb->int2void(*tPtr));
tPtr++;
const Uint32 tAttrInfoLen = *tPtr;
tPtr++;
- if (tOp && tOp->checkMagicNumber() != -1) {
- tOp->TCOPCONF(tAttrInfoLen);
+ if (tOp && tOp->checkMagicNumber()) {
+ tNoComp += tOp->execTCOPCONF(tAttrInfoLen);
} else {
return -1;
}//if
}//for
- Uint32 tNoComp = theNoOfOpCompleted;
Uint32 tNoSent = theNoOfOpSent;
+ theNoOfOpCompleted = tNoComp;
Uint32 tGCI = keyConf->gci;
if (tCommitFlag == 1) {
theCommitStatus = Committed;
theGlobalCheckpointId = tGCI;
} else if ((tNoComp >= tNoSent) &&
(theLastExecOpInList->theCommitIndicator == 1)){
+
+
+ if (m_abortOption == IgnoreError && theError.code != 0){
+ /**
+ * There's always a TCKEYCONF when using IgnoreError
+ */
+#ifdef VM_TRACE
+ ndbout_c("Not completing transaction 2");
+#endif
+ return -1;
+ }
/**********************************************************************/
// We sent the transaction with Commit flag set and received a CONF with
// no Commit flag set. This is clearly an anomaly.
@@ -1502,7 +1549,12 @@ from other transactions.
return 0; // No more operations to wait for
}//if
// Not completed the reception yet.
- }//if
+ } else {
+#ifdef NDB_NO_DROPPED_SIGNAL
+ abort();
+#endif
+ }
+
return -1;
}//NdbConnection::receiveTCKEYCONF()
@@ -1518,50 +1570,50 @@ Remark: Handles the reception of the TCKEY_FAILCONF signal.
int
NdbConnection::receiveTCKEY_FAILCONF(const TcKeyFailConf * failConf)
{
- Uint64 tRecTransId, tCurrTransId;
- Uint32 tTmp1, tTmp2;
NdbOperation* tOp;
- if (theStatus != Connected) {
- return -1;
- }//if
/*
- Check that we are expecting signals from this transaction and that it
- doesn't belong to a transaction already completed. Simply ignore
- messages from other transactions.
+ Check that we are expecting signals from this transaction and that it
+ doesn't belong to a transaction already completed. Simply ignore
+ messages from other transactions.
*/
- tTmp1 = failConf->transId1;
- tTmp2 = failConf->transId2;
- tRecTransId = (Uint64)tTmp1 + ((Uint64)tTmp2 << 32);
- tCurrTransId = this->getTransactionId();
- if (tCurrTransId != tRecTransId) {
- return -1;
- }//if
- /*
- A node failure of the TC node occured. The transaction has
- been committed.
- */
- theCommitStatus = Committed;
- tOp = theFirstExecOpInList;
- while (tOp != NULL) {
+ if(checkState_TransId(&failConf->transId1)){
/*
- Check if the transaction expected read values...
- If it did some of them might have gotten lost even if we succeeded
- in committing the transaction.
+ A node failure of the TC node occured. The transaction has
+ been committed.
*/
- if (tOp->theAI_ElementLen != 0) {
- theCompletionStatus = CompletedFailure;
- setOperationErrorCodeAbort(4115);
- break;
- }//if
- if (tOp->theCurrentRecAttr != NULL) {
- theCompletionStatus = CompletedFailure;
- setOperationErrorCodeAbort(4115);
- break;
- }//if
- tOp = tOp->next();
- }//while
- theReleaseOnClose = true;
- return 0;
+ theCommitStatus = Committed;
+ tOp = theFirstExecOpInList;
+ while (tOp != NULL) {
+ /*
+ * Check if the transaction expected read values...
+ * If it did some of them might have gotten lost even if we succeeded
+ * in committing the transaction.
+ */
+ switch(tOp->theOperationType){
+ case NdbOperation::UpdateRequest:
+ case NdbOperation::InsertRequest:
+ case NdbOperation::DeleteRequest:
+ case NdbOperation::WriteRequest:
+ tOp = tOp->next();
+ break;
+ case NdbOperation::ReadRequest:
+ case NdbOperation::ReadExclusive:
+ case NdbOperation::OpenScanRequest:
+ case NdbOperation::OpenRangeScanRequest:
+ theCompletionStatus = CompletedFailure;
+ setOperationErrorCodeAbort(4115);
+ tOp = NULL;
+ break;
+ }//if
+ }//while
+ theReleaseOnClose = true;
+ return 0;
+ } else {
+#ifdef VM_TRACE
+ ndbout_c("Recevied TCKEY_FAILCONF wo/ operation");
+#endif
+ }
+ return -1;
}//NdbConnection::receiveTCKEY_FAILCONF()
/*************************************************************************
@@ -1576,111 +1628,94 @@ Remark: Handles the reception of the TCKEY_FAILREF signal.
int
NdbConnection::receiveTCKEY_FAILREF(NdbApiSignal* aSignal)
{
- Uint64 tRecTransId, tCurrTransId;
- Uint32 tTmp1, tTmp2;
-
- if (theStatus != Connected) {
- return -1;
- }//if
- /*
- Check that we are expecting signals from this transaction and
- that it doesn't belong to a transaction already
- completed. Simply ignore messages from other transactions.
- */
- tTmp1 = aSignal->readData(2);
- tTmp2 = aSignal->readData(3);
- tRecTransId = (Uint64)tTmp1 + ((Uint64)tTmp2 << 32);
- tCurrTransId = this->getTransactionId();
- if (tCurrTransId != tRecTransId) {
- return -1;
- }//if
/*
- We received an indication of that this transaction was aborted due to a
- node failure.
+ Check that we are expecting signals from this transaction and
+ that it doesn't belong to a transaction already
+ completed. Simply ignore messages from other transactions.
*/
- if (theSendStatus == sendTC_ROLLBACK) {
+ if(checkState_TransId(aSignal->getDataPtr()+1)){
/*
- We were in the process of sending a rollback anyways. We will
- report it as a success.
+ We received an indication of that this transaction was aborted due to a
+ node failure.
*/
- theCompletionStatus = CompletedSuccess;
+ if (theSendStatus == NdbConnection::sendTC_ROLLBACK) {
+ /*
+ We were in the process of sending a rollback anyways. We will
+ report it as a success.
+ */
+ theCompletionStatus = NdbConnection::CompletedSuccess;
+ } else {
+ theCompletionStatus = NdbConnection::CompletedFailure;
+ theError.code = 4031;
+ }//if
+ theReleaseOnClose = true;
+ theCommitStatus = NdbConnection::Aborted;
+ return 0;
} else {
- theCompletionStatus = CompletedFailure;
- theError.code = 4031;
- }//if
- theReleaseOnClose = true;
- theCommitStatus = Aborted;
- return 0;
+#ifdef VM_TRACE
+ ndbout_c("Recevied TCKEY_FAILREF wo/ operation");
+#endif
+ }
+ return -1;
}//NdbConnection::receiveTCKEY_FAILREF()
-/*******************************************************************************
+/******************************************************************************
int receiveTCINDXCONF(NdbApiSignal* aSignal, Uint32 long_short_ind);
Return Value: Return 0 : receiveTCINDXCONF was successful.
Return -1: In all other case.
Parameters: aSignal: The signal object pointer.
Remark:
-*******************************************************************************/
+******************************************************************************/
int
-NdbConnection::receiveTCINDXCONF(const TcIndxConf * indxConf, Uint32 aDataLength)
+NdbConnection::receiveTCINDXCONF(const TcIndxConf * indxConf,
+ Uint32 aDataLength)
{
- Uint64 tRecTransId;
- Uint32 tConditionFlag;
-
- const Uint32 tTemp = indxConf->confInfo;
- const Uint32 tTmp1 = indxConf->transId1;
- const Uint32 tTmp2 = indxConf->transId2;
-/******************************************************************************
-Check that we are expecting signals from this transaction and that it
-doesn't belong to a transaction already completed. Simply ignore messages
-from other transactions.
-******************************************************************************/
- tRecTransId = (Uint64)tTmp1 + ((Uint64)tTmp2 << 32);
-
- const Uint32 tNoOfOperations = TcIndxConf::getNoOfOperations(tTemp);
- const Uint32 tCommitFlag = TcKeyConf::getCommitFlag(tTemp);
-
- tConditionFlag = (Uint32)(((aDataLength - 5) >> 1) - tNoOfOperations);
- tConditionFlag |= (Uint32)(tNoOfOperations > 10);
- tConditionFlag |= (Uint32)(tNoOfOperations <= 0);
- tConditionFlag |= (Uint32)(theTransactionId - tRecTransId);
- tConditionFlag |= (Uint32)(theStatus - Connected);
-
- if (tConditionFlag == 0) {
+ if(checkState_TransId(&indxConf->transId1)){
+ const Uint32 tTemp = indxConf->confInfo;
+ const Uint32 tNoOfOperations = TcIndxConf::getNoOfOperations(tTemp);
+ const Uint32 tCommitFlag = TcKeyConf::getCommitFlag(tTemp);
+
const Uint32* tPtr = (Uint32 *)&indxConf->operations[0];
+ Uint32 tNoComp = theNoOfOpCompleted;
for (Uint32 i = 0; i < tNoOfOperations ; i++) {
- NdbIndexOperation* tOp = theNdb->void2rec_iop(theNdb->int2void(*tPtr));
+ NdbReceiver* tOp = theNdb->void2rec(theNdb->int2void(*tPtr));
tPtr++;
const Uint32 tAttrInfoLen = *tPtr;
tPtr++;
- if (tOp && tOp->checkMagicNumber() != -1) {
- tOp->TCOPCONF(tAttrInfoLen);
+ if (tOp && tOp->checkMagicNumber()) {
+ tNoComp += tOp->execTCOPCONF(tAttrInfoLen);
} else {
return -1;
}//if
}//for
- Uint32 tNoComp = theNoOfOpCompleted;
Uint32 tNoSent = theNoOfOpSent;
Uint32 tGCI = indxConf->gci;
+ theNoOfOpCompleted = tNoComp;
if (tCommitFlag == 1) {
theCommitStatus = Committed;
theGlobalCheckpointId = tGCI;
} else if ((tNoComp >= tNoSent) &&
(theLastExecOpInList->theCommitIndicator == 1)){
-/**********************************************************************/
-// We sent the transaction with Commit flag set and received a CONF with
-// no Commit flag set. This is clearly an anomaly.
-/**********************************************************************/
+ /**********************************************************************/
+ // We sent the transaction with Commit flag set and received a CONF with
+ // no Commit flag set. This is clearly an anomaly.
+ /**********************************************************************/
theError.code = 4011;
- theCompletionStatus = CompletedFailure;
- theCommitStatus = Aborted;
+ theCompletionStatus = NdbConnection::CompletedFailure;
+ theCommitStatus = NdbConnection::Aborted;
return 0;
}//if
if (tNoComp >= tNoSent) {
return 0; // No more operations to wait for
}//if
// Not completed the reception yet.
- }//if
+ } else {
+#ifdef NDB_NO_DROPPED_SIGNAL
+ abort();
+#endif
+ }
+
return -1;
}//NdbConnection::receiveTCINDXCONF()
@@ -1696,36 +1731,26 @@ Remark: Handles the reception of the TCINDXREF signal.
int
NdbConnection::receiveTCINDXREF( NdbApiSignal* aSignal)
{
- Uint64 tRecTransId, tCurrTransId;
- Uint32 tTmp1, tTmp2;
-
- if (theStatus != Connected) {
- return -1;
- }//if
-/*****************************************************************************
-Check that we are expecting signals from this transaction and that it doesn't
-belong to a transaction already completed. Simply ignore messages from other
-transactions.
-******************************************************************************/
- tTmp1 = aSignal->readData(2);
- tTmp2 = aSignal->readData(3);
- tRecTransId = (Uint64)tTmp1 + ((Uint64)tTmp2 << 32);
- tCurrTransId = this->getTransactionId();
- if (tCurrTransId != tRecTransId) {
- return -1;
- }//if
- theError.code = aSignal->readData(4); // Override any previous errors
+ if(checkState_TransId(aSignal->getDataPtr()+1)){
+ theError.code = aSignal->readData(4); // Override any previous errors
+
+ /**********************************************************************/
+ /* A serious error has occured. This could be due to deadlock or */
+ /* lack of resources or simply a programming error in NDB. This */
+ /* transaction will be aborted. Actually it has already been */
+ /* and we only need to report completion and return with the */
+ /* error code to the application. */
+ /**********************************************************************/
+ theCompletionStatus = NdbConnection::CompletedFailure;
+ theCommitStatus = NdbConnection::Aborted;
+ return 0;
+ } else {
+#ifdef NDB_NO_DROPPED_SIGNAL
+ abort();
+#endif
+ }
-/**********************************************************************/
-/* A serious error has occured. This could be due to deadlock or */
-/* lack of resources or simply a programming error in NDB. This */
-/* transaction will be aborted. Actually it has already been */
-/* and we only need to report completion and return with the */
-/* error code to the application. */
-/**********************************************************************/
- theCompletionStatus = CompletedFailure;
- theCommitStatus = Aborted;
- return 0;
+ return -1;
}//NdbConnection::receiveTCINDXREF()
/*******************************************************************************
@@ -1741,7 +1766,7 @@ NdbConnection::OpCompleteFailure()
{
Uint32 tNoComp = theNoOfOpCompleted;
Uint32 tNoSent = theNoOfOpSent;
- theCompletionStatus = CompletedFailure;
+ theCompletionStatus = NdbConnection::CompletedFailure;
tNoComp++;
theNoOfOpCompleted = tNoComp;
if (tNoComp == tNoSent) {
@@ -1752,8 +1777,18 @@ NdbConnection::OpCompleteFailure()
//operation is not really part of that transaction.
//------------------------------------------------------------------------
if (theSimpleState == 1) {
- theCommitStatus = Aborted;
+ theCommitStatus = NdbConnection::Aborted;
}//if
+ if (m_abortOption == IgnoreError){
+ /**
+ * There's always a TCKEYCONF when using IgnoreError
+ */
+#ifdef VM_TRACE
+ ndbout_c("Not completing transaction");
+#endif
+ return -1;
+ }
+
return 0; // Last operation received
} else if (tNoComp > tNoSent) {
setOperationErrorCodeAbort(4113); // Too many operations,
@@ -1780,7 +1815,7 @@ NdbConnection::OpCompleteSuccess()
theNoOfOpCompleted = tNoComp;
if (tNoComp == tNoSent) { // Last operation completed
if (theSimpleState == 1) {
- theCommitStatus = Committed;
+ theCommitStatus = NdbConnection::Committed;
}//if
return 0;
} else if (tNoComp < tNoSent) {
@@ -1788,7 +1823,7 @@ NdbConnection::OpCompleteSuccess()
} else {
setOperationErrorCodeAbort(4113); // Too many operations,
// stop waiting for more
- theCompletionStatus = CompletedFailure;
+ theCompletionStatus = NdbConnection::CompletedFailure;
return 0;
}//if
}//NdbConnection::OpCompleteSuccess()
@@ -1801,7 +1836,7 @@ Remark: Get global checkpoint identity of the transaction
int
NdbConnection::getGCI()
{
- if (theCommitStatus == Committed) {
+ if (theCommitStatus == NdbConnection::Committed) {
return theGlobalCheckpointId;
}//if
return 0;
diff --git a/ndb/src/ndbapi/NdbConnectionScan.cpp b/ndb/src/ndbapi/NdbConnectionScan.cpp
index 962acc0bdac..0c4490015ff 100644
--- a/ndb/src/ndbapi/NdbConnectionScan.cpp
+++ b/ndb/src/ndbapi/NdbConnectionScan.cpp
@@ -33,7 +33,6 @@
#include <NdbConnection.hpp>
#include <NdbOperation.hpp>
#include <NdbScanOperation.hpp>
-#include "NdbScanReceiver.hpp"
#include "NdbApiSignal.hpp"
#include "TransporterFacade.hpp"
#include "NdbUtil.hpp"
@@ -44,304 +43,6 @@
#include <NdbOut.hpp>
-// time out for next scan result (-1 is infinite)
-// XXX should change default only if non-trivial interpreted program is used
-#define WAITFOR_SCAN_TIMEOUT 120000
-
-
-/*****************************************************************************
- * int executeScan();
- *
- * 1. Check that the transaction is started and other important preconditions
- * 2. Tell the kernel to start scanning by sending one SCAN_TABREQ, if
- * parallelism is greater than 16 also send one SCAN_TABINFO for each
- * additional 16
- * Define which attributes to scan in ATTRINFO, this signal also holds the
- * interpreted program
- * 3. Wait for the answer of the SCAN_TABREQ. This is either a SCAN_TABCONF if
- * the scan was correctly defined and a SCAN_TABREF if the scan couldn't
- * be started.
- * 4. Check the result, if scan was not started return -1
- *
- ****************************************************************************/
-int
-NdbConnection::executeScan(){
- if (theTransactionIsStarted == true){ // Transaction already started.
- setErrorCode(4600);
- return -1;
- }
- if (theStatus != Connected) { // Lost connection
- setErrorCode(4601);
- return -1;
- }
- if (theScanningOp == NULL){
- setErrorCode(4602); // getNdbOperation must be called before executeScan
- return -1;
- }
- TransporterFacade* tp = TransporterFacade::instance();
- theNoOfOpCompleted = 0;
- theNoOfSCANTABCONFRecv = 0;
- tp->lock_mutex();
- if (tp->get_node_alive(theDBnode) &&
- (tp->getNodeSequence(theDBnode) == theNodeSequence)) {
- if (tp->check_send_size(theDBnode, get_send_size())) {
- theTransactionIsStarted = true;
- if (sendScanStart() == -1){
- tp->unlock_mutex();
- return -1;
- }//if
- theNdb->theWaiter.m_node = theDBnode;
- theNdb->theWaiter.m_state = WAIT_SCAN;
- int res = theNdb->receiveResponse(WAITFOR_SCAN_TIMEOUT);
- if (res == 0) {
- return 0;
- } else {
- if (res == -1) {
- setErrorCode(4008);
- } else if (res == -2) {
- theTransactionIsStarted = false;
- theReleaseOnClose = true;
- setErrorCode(4028);
- } else {
- ndbout << "Impossible return from receiveResponse in executeScan";
- ndbout << endl;
- abort();
- }//if
- theCommitStatus = Aborted;
- return -1;
- }//if
- } else {
- TRACE_DEBUG("Start a scan with send buffer full attempted");
- setErrorCode(4022);
- theCommitStatus = Aborted;
- }//if
- } else {
- if (!(tp->get_node_stopping(theDBnode) &&
- (tp->getNodeSequence(theDBnode) == theNodeSequence))) {
- TRACE_DEBUG("The node is hard dead when attempting to start a scan");
- setErrorCode(4029);
- theReleaseOnClose = true;
- } else {
- TRACE_DEBUG("The node is stopping when attempting to start a scan");
- setErrorCode(4030);
- }//if
- theCommitStatus = Aborted;
- }//if
- tp->unlock_mutex();
- return -1;
-}
-
-/******************************************************************************
- * int nextScanResult();
- * Remark:
- * This method is used to distribute data received to the application.
- * Iterate through the list and search for operations that haven't
- * been distributed yet (status != Finished).
- * If there are no more operations/records still waiting to be exececuted
- * we have to send SCAN_NEXTREQ to fetch next set of records.
- *
- * TODO - This function should be able to return a value indicating if
- * there are any more records already fetched from memory or if it has to
- * ask the db for more. This would mean we could get better performance when
- * takeOver is used wince we can take over all ops already fetched, put them
- * in another trans and send them of to the db when there are no more records
- * already fetched. Maybe use a new argument to the function for this
-******************************************************************************/
-int
-NdbConnection::nextScanResult(bool fetchAllowed){
-
- if (theTransactionIsStarted != true){ // Transaction not started.
- setErrorCode(4601);
- return -1;
- }
- // Scan has finished ok but no operations recived = empty recordset.
- if(theScanFinished == true){
- return 1; // No more records
- }
- if (theStatus != Connected){// Lost connection
- setErrorCode(4601);
- return -1;
- }
- // Something went wrong, probably we got a SCAN_TABREF earlier.
- if (theCompletionStatus == CompletedFailure) {
- return -1;
- }
- if (theNoOfOpCompleted == theNoOfOpFetched) {
- // There are no more records cached in NdbApi
- if (fetchAllowed == true){
- // Get some more records from db
-
- if (fetchNextScanResult() == -1){
- return -1;
- }
- if (theScanFinished == true) { // The scan has finished.
- return 1; // 1 = No more records
- }
- if (theCompletionStatus == CompletedFailure) {
- return -1; // Something went wrong, probably we got a SCAN_TABREF.
- }
- } else {
- // There where no more cached records in NdbApi
- // and we where not allowed to go to db and ask for
- // more
- return 2;
- }
- }
-
- // It's not allowed to come here without any cached records
- if (theCurrentScanRec == NULL){
-#ifdef VM_TRACE
- ndbout << "nextScanResult("<<fetchAllowed<<")"<<endl
- << " theTransactionIsStarted = " << theTransactionIsStarted << endl
- << " theScanFinished = " << theScanFinished << endl
- << " theCommitStatus = " << theCommitStatus << endl
- << " theStatus = " << theStatus << endl
- << " theCompletionStatus = " << theCompletionStatus << endl
- << " theNoOfOpCompleted = " << theNoOfOpCompleted << endl
- << " theNoOfOpFetched = " << theNoOfOpFetched << endl
- << " theScanningOp = " << theScanningOp << endl
- << " theNoOfSCANTABCONFRecv = "<< theNoOfSCANTABCONFRecv << endl
- << " theNdb->theWaiter.m_node = " <<theNdb->theWaiter.m_node<<endl
- << " theNdb->theWaiter.m_state = " << theNdb->theWaiter.m_state << endl;
- abort();
-#endif
- return -1;
- }
-
- // Execute the saved signals for this operation.
- NdbScanReceiver* tScanRec = theCurrentScanRec;
- theScanningOp->theCurrRecAI_Len = 0;
- theScanningOp->theCurrentRecAttr = theScanningOp->theFirstRecAttr;
- if(tScanRec->executeSavedSignals() != 0)
- return -1;
- theNoOfOpCompleted++;
- // Remember for next iteration and takeOverScanOp
- thePreviousScanRec = tScanRec;
- theCurrentScanRec = tScanRec->next();
- return 0; // 0 = There are more rows to be fetched.
-}
-
-/******************************************************************************
- * int stopScan()
- * Remark: By sending SCAN_NEXTREQ with data word 2 set to TRUE we
- * abort the scan process.
- *****************************************************************************/
-int
-NdbConnection::stopScan()
-{
- if(theScanFinished == true){
- return 0;
- }
- if (theCompletionStatus == CompletedFailure){
- return 0;
- }
-
- if (theScanningOp == 0){
- return 0;
- }
-
- theNoOfOpCompleted = 0;
- theNoOfSCANTABCONFRecv = 0;
- theScanningOp->prepareNextScanResult();
- return sendScanNext(1);
-}
-
-
-/********************************************************************
- * int sendScanStart()
- *
- * Send the signals reuired to define and start the scan
- * 1. Send SCAN_TABREQ
- * 2. Send SCAN_TABINFO(if any, parallelism must be > 16)
- * 3. Send ATTRINFO signals
- *
- * Returns -1 if an error occurs otherwise 0.
- *
- ********************************************************************/
-int
-NdbConnection::sendScanStart(){
-
- /***** 0. Prepare signals ******************/
- // This might modify variables and signals
- if(theScanningOp->prepareSendScan(theTCConPtr,
- theTransactionId) == -1)
- return -1;
-
- /***** 1. Send SCAN_TABREQ **************/
- /***** 2. Send SCAN_TABINFO *************/
- /***** 3. Send ATTRINFO signals *********/
- if (theScanningOp->doSendScan(theDBnode) == -1)
- return -1;
- return 0;
-}
-
-
-int
-NdbConnection::fetchNextScanResult(){
- theNoOfOpCompleted = 0;
- theNoOfSCANTABCONFRecv = 0;
- theScanningOp->prepareNextScanResult();
- return sendScanNext(0);
-}
-
-
-
-/***********************************************************
- * int sendScanNext(int stopScanFlag)
- *
- * ************************************************************/
-int NdbConnection::sendScanNext(bool stopScanFlag){
- NdbApiSignal tSignal(theNdb->theMyRef);
- Uint32 tTransId1, tTransId2;
- tSignal.setSignal(GSN_SCAN_NEXTREQ);
- tSignal.setData(theTCConPtr, 1);
- // Set the stop flag in word 2(1 = stop)
- Uint32 tStopValue;
- tStopValue = stopScanFlag == true ? 1 : 0;
- tSignal.setData(tStopValue, 2);
- tTransId1 = (Uint32) theTransactionId;
- tTransId2 = (Uint32) (theTransactionId >> 32);
- tSignal.setData(tTransId1, 3);
- tSignal.setData(tTransId2, 4);
- tSignal.setLength(4);
- Uint32 conn_seq = theNodeSequence;
- int return_code = theNdb->sendRecSignal(theDBnode,
- WAIT_SCAN,
- &tSignal,
- conn_seq);
- if (return_code == 0) {
- return 0;
- } else if (return_code == -1) { // Time-out
- TRACE_DEBUG("Time-out when sending sendScanNext");
- setErrorCode(4024);
- theTransactionIsStarted = false;
- theReleaseOnClose = true;
- theCommitStatus = Aborted;
- } else if (return_code == -2) { // Node failed
- TRACE_DEBUG("Node failed when sendScanNext");
- setErrorCode(4027);
- theTransactionIsStarted = false;
- theReleaseOnClose = true;
- theCommitStatus = Aborted;
- } else if (return_code == -3) {
- TRACE_DEBUG("Send failed when sendScanNext");
- setErrorCode(4033);
- theTransactionIsStarted = false;
- theReleaseOnClose = true;
- theCommitStatus = Aborted;
- } else if (return_code == -4) {
- TRACE_DEBUG("Send buffer full when sendScanNext");
- setErrorCode(4032);
- } else if (return_code == -5) {
- TRACE_DEBUG("Node stopping when sendScanNext");
- setErrorCode(4034);
- } else {
- ndbout << "Impossible return from sendRecSignal" << endl;
- abort();
- }//if
- return -1;
-}
-
/***************************************************************************
* int receiveSCAN_TABREF(NdbApiSignal* aSignal)
@@ -352,39 +53,24 @@ int NdbConnection::sendScanNext(bool stopScanFlag){
****************************************************************************/
int
NdbConnection::receiveSCAN_TABREF(NdbApiSignal* aSignal){
- const ScanTabRef * const scanTabRef = CAST_CONSTPTR(ScanTabRef, aSignal->getDataPtr());
- if (theStatus != Connected){
-#ifdef VM_TRACE
- ndbout << "SCAN_TABREF dropped, theStatus = " << theStatus << endl;
-#endif
- return -1;
- }
- if (aSignal->getLength() != ScanTabRef::SignalLength){
-#ifdef VM_TRACE
- ndbout << "SCAN_TABREF dropped, signal length " << aSignal->getLength() << endl;
-#endif
- return -1;
- }
- const Uint64 tCurrTransId = this->getTransactionId();
- const Uint64 tRecTransId = (Uint64)scanTabRef->transId1 +
- ((Uint64)scanTabRef->transId2 << 32);
- if ((tRecTransId - tCurrTransId) != (Uint64)0){
-#ifdef VM_TRACE
- ndbout << "SCAN_TABREF dropped, wrong transid" << endl;
+ const ScanTabRef * ref = CAST_CONSTPTR(ScanTabRef, aSignal->getDataPtr());
+
+ if(checkState_TransId(&ref->transId1)){
+ theScanningOp->theError.code = ref->errorCode;
+ if(!ref->closeNeeded){
+ theScanningOp->execCLOSE_SCAN_REP();
+ return 0;
+ }
+ assert(theScanningOp->m_sent_receivers_count);
+ theScanningOp->m_conf_receivers_count++;
+ return 0;
+ } else {
+#ifdef NDB_NO_DROPPED_SIGNAL
+ abort();
#endif
- return -1;
}
-#if 0
- ndbout << "SCAN_TABREF, "
- <<"transid=("<<hex<<scanTabRef->transId1<<", "<<hex<<scanTabRef->transId2<<")"
- <<", err="<<dec<<scanTabRef->errorCode << endl;
-#endif
- setErrorCode(scanTabRef->errorCode);
- theCompletionStatus = CompletedFailure;
- theCommitStatus = Aborted; // Indicate that this "transaction" was aborted
- theTransactionIsStarted = false;
- theScanningOp->releaseSignals();
- return 0;
+
+ return -1;
}
/*****************************************************************************
@@ -401,173 +87,44 @@ NdbConnection::receiveSCAN_TABREF(NdbApiSignal* aSignal){
*
*****************************************************************************/
int
-NdbConnection::receiveSCAN_TABCONF(NdbApiSignal* aSignal)
+NdbConnection::receiveSCAN_TABCONF(NdbApiSignal* aSignal,
+ const Uint32 * ops, Uint32 len)
{
- const ScanTabConf * const conf = CAST_CONSTPTR(ScanTabConf, aSignal->getDataPtr());
- if (theStatus != Connected){
-#ifdef VM_TRACE
- ndbout << "Dropping SCAN_TABCONF, theStatus = "<< theStatus << endl;
-#endif
- return -1;
- }
- if(aSignal->getLength() != ScanTabConf::SignalLength){
-#ifdef VM_TRACE
- ndbout << "Dropping SCAN_TABCONF, getLength = "<< aSignal->getLength() << endl;
-#endif
- return -1;
- }
- const Uint64 tCurrTransId = this->getTransactionId();
- const Uint64 tRecTransId =
- (Uint64)conf->transId1 + ((Uint64)conf->transId2 << 32);
- if ((tRecTransId - tCurrTransId) != (Uint64)0){
-#ifdef VM_TRACE
- ndbout << "Dropping SCAN_TABCONF, wrong transid" << endl;
-#endif
- return -1;
- }
-
- const Uint8 scanStatus =
- ScanTabConf::getScanStatus(conf->requestInfo);
-
- if (scanStatus != 0) {
- theCompletionStatus = CompletedSuccess;
- theCommitStatus = Committed;
- theScanFinished = true;
- return 0;
- }
-
- // There can only be one SCANTABCONF
- assert(theNoOfSCANTABCONFRecv == 0);
- theNoOfSCANTABCONFRecv++;
-
- // Save a copy of the signal
- NdbApiSignal * tCopy = new NdbApiSignal(0);//getSignal();
- if (tCopy == NULL){
- setErrorCode(4000);
- return 2; // theWaiter.m_state = NO_WAIT
- }
- tCopy->copyFrom(aSignal);
- tCopy->next(NULL);
- theScanningOp->theSCAN_TABCONF_Recv = tCopy;
-
- return checkNextScanResultComplete();
-
-}
-
-/*****************************************************************************
- * int receiveSCAN_TABINFO(NdbApiSignal* aSignal)
- *
- * Receive SCAN_TABINFO
- *
- *****************************************************************************/
-int
-NdbConnection::receiveSCAN_TABINFO(NdbApiSignal* aSignal)
-{
- if (theStatus != Connected){
- //ndbout << "SCAN_TABINFO dropped, theStatus = " << theStatus << endl;
- return -1;
- }
- if (aSignal->getLength() != ScanTabInfo::SignalLength){
- //ndbout << "SCAN_TABINFO dropped, length = " << aSignal->getLength() << endl;
- return -1;
- }
-
- NdbApiSignal * tCopy = new NdbApiSignal(0);//getSignal();
- if (tCopy == NULL){
- setErrorCode(4000);
- return 2; // theWaiter.m_state = NO_WAIT
- }
- tCopy->copyFrom(aSignal);
- tCopy->next(NULL);
-
- // Put the signal last in list
- if (theScanningOp->theFirstSCAN_TABINFO_Recv == NULL)
- theScanningOp->theFirstSCAN_TABINFO_Recv = tCopy;
- else
- theScanningOp->theLastSCAN_TABINFO_Recv->next(tCopy);
- theScanningOp->theLastSCAN_TABINFO_Recv = tCopy;
-
- return checkNextScanResultComplete();
-}
-
-/******************************************************************************
- * int checkNextScanResultComplete(NdbApiSignal* aSignal)
- *
- * Remark Traverses all the lists that are associated with
- * this resultset and checks if all signals are there.
- * If all required signal are received return 0
- *
- *
- *****************************************************************************/
-int
-NdbConnection::checkNextScanResultComplete(){
-
- if (theNoOfSCANTABCONFRecv != 1) {
- return -1;
- }
-
- Uint32 tNoOfOpFetched = 0;
- theCurrentScanRec = NULL;
- thePreviousScanRec = NULL;
-
- const ScanTabConf * const conf =
- CAST_CONSTPTR(ScanTabConf, theScanningOp->theSCAN_TABCONF_Recv->getDataPtr());
- const Uint32 numOperations = ScanTabConf::getOperations(conf->requestInfo);
- Uint32 sigIndex = 0;
- NdbApiSignal* tSignal = theScanningOp->theFirstSCAN_TABINFO_Recv;
- while(tSignal != NULL){
- const ScanTabInfo * const info = CAST_CONSTPTR(ScanTabInfo, tSignal->getDataPtr());
- // Loop through the operations for this SCAN_TABINFO
- // tOpAndLength is allowed to be zero, this means no
- // TRANSID_AI signals where sent for this record
- // I.e getValue was called 0 times when defining scan
-
- // The max number of operations in each signal is 16
- Uint32 numOpsInSig = numOperations - sigIndex*16;
- if (numOpsInSig > 16)
- numOpsInSig = 16;
- for(Uint32 i = 0; i < numOpsInSig; i++){
- const Uint32 tOpAndLength = info->operLenAndIdx[i];
- const Uint32 tOpIndex = ScanTabInfo::getIdx(tOpAndLength);
- const Uint32 tOpLen = ScanTabInfo::getLen(tOpAndLength);
-
- assert(tOpIndex < 256);
- NdbScanReceiver* tScanRec =
- theScanningOp->theScanReceiversArray[tOpIndex];
- assert(tScanRec != NULL);
- if(tScanRec->isCompleted(tOpLen))
- tScanRec->setCompleted();
- else{
- return -1; // At least one receiver was not ready
- }
-
- // Build list of scan receivers
- if (theCurrentScanRec == NULL) {
- theCurrentScanRec = tScanRec;
- thePreviousScanRec = tScanRec;
- } else {
- thePreviousScanRec->next(tScanRec);
- thePreviousScanRec = tScanRec;
+ const ScanTabConf * conf = CAST_CONSTPTR(ScanTabConf, aSignal->getDataPtr());
+ if(checkState_TransId(&conf->transId1)){
+
+ if (conf->requestInfo == ScanTabConf::EndOfData) {
+ theScanningOp->execCLOSE_SCAN_REP();
+ return 0;
+ }
+
+ for(Uint32 i = 0; i<len; i += 3){
+ Uint32 ptrI = * ops++;
+ Uint32 tcPtrI = * ops++;
+ Uint32 info = * ops++;
+ Uint32 opCount = ScanTabConf::getRows(info);
+ Uint32 totalLen = ScanTabConf::getLength(info);
+
+ void * tPtr = theNdb->int2void(ptrI);
+ assert(tPtr); // For now
+ NdbReceiver* tOp = theNdb->void2rec(tPtr);
+ if (tOp && tOp->checkMagicNumber()){
+ if(tOp->execSCANOPCONF(tcPtrI, totalLen, opCount)){
+ /**
+ *
+ */
+ theScanningOp->receiver_delivered(tOp);
+ } else if(info == ScanTabConf::EndOfData){
+ theScanningOp->receiver_completed(tOp);
+ }
}
- tNoOfOpFetched++;
}
- tSignal = tSignal->next();
- sigIndex++;
- }
-
- // Check number of operations fetched against value in SCANTAB_CONF
- if (tNoOfOpFetched != numOperations) {
- setErrorCode(4113);
- return 2; // theWaiter.m_state = NO_WAIT
+ return 0;
+ } else {
+#ifdef NDB_NO_DROPPED_SIGNAL
+ abort();
+#endif
}
- // All signals for this resultset recieved
- // release SCAN_TAB signals
- theNoOfSCANTABCONFRecv = 0;
- theScanningOp->releaseSignals();
-
- // We have received all operations with correct lengths.
- thePreviousScanRec = NULL;
- theNoOfOpFetched = tNoOfOpFetched;
- return 0;
+ return -1;
}
diff --git a/ndb/src/ndbapi/NdbCursorOperation.cpp b/ndb/src/ndbapi/NdbCursorOperation.cpp
index e4dd600c57f..a9f84c4c110 100644
--- a/ndb/src/ndbapi/NdbCursorOperation.cpp
+++ b/ndb/src/ndbapi/NdbCursorOperation.cpp
@@ -30,8 +30,6 @@
#include <NdbResultSet.hpp>
NdbCursorOperation::NdbCursorOperation(Ndb* aNdb) :
- NdbOperation(aNdb),
- m_resultSet(0)
{
}
@@ -48,10 +46,6 @@ void NdbCursorOperation::cursInit()
NdbResultSet* NdbCursorOperation::getResultSet()
{
- if (!m_resultSet)
- m_resultSet = new NdbResultSet(this);
-
- return m_resultSet;
}
diff --git a/ndb/src/ndbapi/NdbDictionary.cpp b/ndb/src/ndbapi/NdbDictionary.cpp
index 413ad0745db..4b30f41b51d 100644
--- a/ndb/src/ndbapi/NdbDictionary.cpp
+++ b/ndb/src/ndbapi/NdbDictionary.cpp
@@ -174,6 +174,14 @@ NdbDictionary::Column::getIndexOnlyStorage() const {
return m_impl.m_indexOnly;
}
+const NdbDictionary::Table *
+NdbDictionary::Column::getBlobTable() const {
+ NdbTableImpl * t = m_impl.m_blobTable;
+ if (t)
+ return t->m_facade;
+ return 0;
+}
+
void
NdbDictionary::Column::setAutoIncrement(bool val){
m_impl.m_autoIncrement = val;
@@ -806,73 +814,90 @@ NdbDictionary::Dictionary::getNdbError() const {
return m_impl.getNdbError();
}
-NdbOut& operator <<(NdbOut& ndbout, const NdbDictionary::Column::Type type)
+// printers
+
+NdbOut&
+operator<<(NdbOut& out, const NdbDictionary::Column& col)
{
- switch(type){
- case NdbDictionary::Column::Bigunsigned:
- ndbout << "Bigunsigned";
+ out << col.getName() << " ";
+ switch (col.getType()) {
+ case NdbDictionary::Column::Tinyint:
+ out << "Tinyint";
break;
- case NdbDictionary::Column::Unsigned:
- ndbout << "Unsigned";
+ case NdbDictionary::Column::Tinyunsigned:
+ out << "Tinyunsigned";
+ break;
+ case NdbDictionary::Column::Smallint:
+ out << "Smallint";
break;
case NdbDictionary::Column::Smallunsigned:
- ndbout << "Smallunsigned";
+ out << "Smallunsigned";
break;
- case NdbDictionary::Column::Tinyunsigned:
- ndbout << "Tinyunsigned";
+ case NdbDictionary::Column::Mediumint:
+ out << "Mediumint";
break;
- case NdbDictionary::Column::Bigint:
- ndbout << "Bigint";
+ case NdbDictionary::Column::Mediumunsigned:
+ out << "Mediumunsigned";
break;
case NdbDictionary::Column::Int:
- ndbout << "Int";
- break;
- case NdbDictionary::Column::Smallint:
- ndbout << "Smallint";
+ out << "Int";
break;
- case NdbDictionary::Column::Tinyint:
- ndbout << "Tinyint";
+ case NdbDictionary::Column::Unsigned:
+ out << "Unsigned";
break;
- case NdbDictionary::Column::Char:
- ndbout << "Char";
+ case NdbDictionary::Column::Bigint:
+ out << "Bigint";
break;
- case NdbDictionary::Column::Varchar:
- ndbout << "Varchar";
+ case NdbDictionary::Column::Bigunsigned:
+ out << "Bigunsigned";
break;
case NdbDictionary::Column::Float:
- ndbout << "Float";
+ out << "Float";
break;
case NdbDictionary::Column::Double:
- ndbout << "Double";
+ out << "Double";
break;
- case NdbDictionary::Column::Mediumint:
- ndbout << "Mediumint";
+ case NdbDictionary::Column::Decimal:
+ out << "Decimal(" << col.getScale() << "," << col.getPrecision() << ")";
break;
- case NdbDictionary::Column::Mediumunsigned:
- ndbout << "Mediumunsigend";
+ case NdbDictionary::Column::Char:
+ out << "Char(" << col.getLength() << ")";
+ break;
+ case NdbDictionary::Column::Varchar:
+ out << "Varchar(" << col.getLength() << ")";
break;
case NdbDictionary::Column::Binary:
- ndbout << "Binary";
+ out << "Binary(" << col.getLength() << ")";
break;
case NdbDictionary::Column::Varbinary:
- ndbout << "Varbinary";
+ out << "Varbinary(" << col.getLength() << ")";
break;
- case NdbDictionary::Column::Decimal:
- ndbout << "Decimal";
+ case NdbDictionary::Column::Datetime:
+ out << "Datetime";
break;
case NdbDictionary::Column::Timespec:
- ndbout << "Timespec";
+ out << "Timespec";
break;
case NdbDictionary::Column::Blob:
- ndbout << "Blob";
+ out << "Blob(" << col.getInlineSize() << "," << col.getPartSize()
+ << ";" << col.getStripeSize() << ")";
+ break;
+ case NdbDictionary::Column::Text:
+ out << "Text(" << col.getInlineSize() << "," << col.getPartSize()
+ << ";" << col.getStripeSize() << ")";
break;
case NdbDictionary::Column::Undefined:
- ndbout << "Undefined";
+ out << "Undefined";
break;
default:
- ndbout << "Unknown type=" << (Uint32)type;
+ out << "Type" << (Uint32)col.getType();
break;
}
-
- return ndbout;
+ if (col.getPrimaryKey())
+ out << " PRIMARY KEY";
+ else if (! col.getNullable())
+ out << " NOT NULL";
+ else
+ out << " NULL";
+ return out;
}
diff --git a/ndb/src/ndbapi/NdbDictionaryImpl.cpp b/ndb/src/ndbapi/NdbDictionaryImpl.cpp
index 348f6db36e4..cb5e3b3c821 100644
--- a/ndb/src/ndbapi/NdbDictionaryImpl.cpp
+++ b/ndb/src/ndbapi/NdbDictionaryImpl.cpp
@@ -79,6 +79,7 @@ NdbColumnImpl::operator=(const NdbColumnImpl& col)
m_attrSize = col.m_attrSize;
m_arraySize = col.m_arraySize;
m_keyInfoPos = col.m_keyInfoPos;
+ m_blobTable = col.m_blobTable;
// Do not copy m_facade !!
return *this;
@@ -104,6 +105,7 @@ NdbColumnImpl::init()
m_arraySize = 1,
m_autoIncrement = false;
m_autoIncrementInitialValue = 1;
+ m_blobTable = NULL;
}
NdbColumnImpl::~NdbColumnImpl()
@@ -181,7 +183,7 @@ NdbColumnImpl::equal(const NdbColumnImpl& col) const
case NdbDictionary::Column::Timespec:
break;
case NdbDictionary::Column::Blob:
- case NdbDictionary::Column::Clob:
+ case NdbDictionary::Column::Text:
if (m_precision != col.m_precision ||
m_scale != col.m_scale ||
m_length != col.m_length) {
@@ -230,10 +232,6 @@ NdbColumnImpl::assign(const NdbColumnImpl& org)
NdbTableImpl::NdbTableImpl()
: NdbDictionary::Table(* this), m_facade(this)
{
- m_noOfKeys = 0;
- m_sizeOfKeysInWords = 0;
- m_noOfBlobs = 0;
- m_index = 0;
init();
}
@@ -267,6 +265,7 @@ NdbTableImpl::init(){
m_indexType = NdbDictionary::Index::Undefined;
m_noOfKeys = 0;
+ m_fragmentCount = 0;
m_sizeOfKeysInWords = 0;
m_noOfBlobs = 0;
}
@@ -287,11 +286,9 @@ NdbTableImpl::equal(const NdbTableImpl& obj) const
if(strcmp(m_internalName.c_str(), obj.m_internalName.c_str()) != 0){
return false;
}
-
if(m_fragmentType != obj.m_fragmentType){
return false;
}
-
if(m_columns.size() != obj.m_columns.size()){
return false;
}
@@ -330,6 +327,7 @@ NdbTableImpl::assign(const NdbTableImpl& org)
m_newExternalName.assign(org.m_newExternalName);
m_frm.assign(org.m_frm.get_data(), org.m_frm.length());
m_fragmentType = org.m_fragmentType;
+ m_fragmentCount = org.m_fragmentCount;
for(unsigned i = 0; i<org.m_columns.size(); i++){
NdbColumnImpl * col = new NdbColumnImpl();
@@ -387,7 +385,8 @@ void
NdbTableImpl::buildColumnHash(){
const Uint32 size = m_columns.size();
- for(size_t i = 31; i >= 0; i--){
+ size_t i;
+ for(i = 31; i >= 0; i--){
if(((1 << i) & size) != 0){
m_columnHashMask = (1 << (i + 1)) - 1;
break;
@@ -396,7 +395,7 @@ NdbTableImpl::buildColumnHash(){
Vector<Uint32> hashValues;
Vector<Vector<Uint32> > chains; chains.fill(size, hashValues);
- for(size_t i = 0; i<size; i++){
+ for(i = 0; i<size; i++){
Uint32 hv = Hash(m_columns[i]->getName()) & 0xFFFE;
Uint32 bucket = hv & m_columnHashMask;
bucket = (bucket < size ? bucket : bucket - size);
@@ -410,7 +409,7 @@ NdbTableImpl::buildColumnHash(){
m_columnHash.fill((unsigned)size-1, tmp); // Default no chaining
Uint32 pos = 0; // In overflow vector
- for(size_t i = 0; i<size; i++){
+ for(i = 0; i<size; i++){
Uint32 sz = chains[i].size();
if(sz == 1){
Uint32 col = chains[i][0];
@@ -495,6 +494,12 @@ NdbIndexImpl::getTable() const
return m_tableName.c_str();
}
+const NdbTableImpl *
+NdbIndexImpl::getIndexTable() const
+{
+ return m_table;
+}
+
/**
* NdbEventImpl
*/
@@ -840,6 +845,7 @@ NdbDictInterface::dictSignal(NdbApiSignal* signal,
m_waiter.m_state = wst;
m_waiter.wait(theWait);
+ m_transporter->unlock_mutex();
// End of Protected area
if(m_waiter.m_state == NO_WAIT && m_error.code == 0){
@@ -1091,7 +1097,7 @@ columnTypeMapping[] = {
{ DictTabInfo::ExtDatetime, NdbDictionary::Column::Datetime },
{ DictTabInfo::ExtTimespec, NdbDictionary::Column::Timespec },
{ DictTabInfo::ExtBlob, NdbDictionary::Column::Blob },
- { DictTabInfo::ExtClob, NdbDictionary::Column::Clob },
+ { DictTabInfo::ExtText, NdbDictionary::Column::Text },
{ -1, -1 }
};
@@ -1132,6 +1138,7 @@ NdbDictInterface::parseTableInfo(NdbTableImpl ** ret,
impl->m_kvalue = tableDesc.TableKValue;
impl->m_minLoadFactor = tableDesc.MinLoadFactor;
impl->m_maxLoadFactor = tableDesc.MaxLoadFactor;
+ impl->m_fragmentCount = tableDesc.FragmentCount;
impl->m_indexType = (NdbDictionary::Index::Type)
getApiConstant(tableDesc.TableType,
@@ -1147,7 +1154,7 @@ NdbDictInterface::parseTableInfo(NdbTableImpl ** ret,
Uint32 keyInfoPos = 0;
Uint32 keyCount = 0;
- Uint32 blobCount;
+ Uint32 blobCount = 0;
for(Uint32 i = 0; i < tableDesc.NoOfAttributes; i++) {
DictTabInfo::Attribute attrDesc; attrDesc.init();
@@ -1206,7 +1213,6 @@ NdbDictInterface::parseTableInfo(NdbTableImpl ** ret,
}
if (col->getBlobType())
blobCount++;
-
NdbColumnImpl * null = 0;
impl->m_columns.fill(attrDesc.AttributeId, null);
if(impl->m_columns[attrDesc.AttributeId] != 0){
@@ -1218,6 +1224,7 @@ NdbDictInterface::parseTableInfo(NdbTableImpl ** ret,
it.next();
}
impl->m_noOfKeys = keyCount;
+ impl->m_keyLenInWords = keyInfoPos;
impl->m_sizeOfKeysInWords = keyInfoPos;
impl->m_noOfBlobs = blobCount;
* ret = impl;
@@ -1254,13 +1261,34 @@ NdbDictionaryImpl::createBlobTables(NdbTableImpl &t)
{
for (unsigned i = 0; i < t.m_columns.size(); i++) {
NdbColumnImpl & c = *t.m_columns[i];
- if (! c.getBlobType())
+ if (! c.getBlobType() || c.getPartSize() == 0)
continue;
NdbTableImpl bt;
NdbBlob::getBlobTable(bt, &t, &c);
if (createTable(bt) != 0)
return -1;
+ // Save BLOB table handle
+ NdbTableImpl * cachedBlobTable = getTable(bt.m_externalName.c_str());
+ c.m_blobTable = cachedBlobTable;
}
+
+ return 0;
+}
+
+int
+NdbDictionaryImpl::addBlobTables(NdbTableImpl &t)
+{
+ for (unsigned i = 0; i < t.m_columns.size(); i++) {
+ NdbColumnImpl & c = *t.m_columns[i];
+ if (! c.getBlobType() || c.getPartSize() == 0)
+ continue;
+ char btname[NdbBlob::BlobTableNameSize];
+ NdbBlob::getBlobTableName(btname, &t, &c);
+ // Save BLOB table handle
+ NdbTableImpl * cachedBlobTable = getTable(btname);;
+ c.m_blobTable = cachedBlobTable;
+ }
+
return 0;
}
@@ -1315,6 +1343,7 @@ NdbDictInterface::createOrAlterTable(Ndb & ndb,
NdbTableImpl & impl,
bool alter)
{
+ unsigned i;
if((unsigned)impl.getNoOfPrimaryKeys() > NDB_MAX_NO_OF_ATTRIBUTES_IN_KEY){
m_error.code = 4317;
return -1;
@@ -1340,7 +1369,7 @@ NdbDictInterface::createOrAlterTable(Ndb & ndb,
bool haveAutoIncrement = false;
Uint64 autoIncrementValue;
- for(unsigned i = 0; i<sz; i++){
+ for(i = 0; i<sz; i++){
const NdbColumnImpl * col = impl.m_columns[i];
if(col == 0)
continue;
@@ -1384,7 +1413,7 @@ NdbDictInterface::createOrAlterTable(Ndb & ndb,
abort();
}
- for(unsigned i = 0; i<sz; i++){
+ for(i = 0; i<sz; i++){
const NdbColumnImpl * col = impl.m_columns[i];
if(col == 0)
continue;
@@ -1453,7 +1482,7 @@ NdbDictInterface::createOrAlterTable(Ndb & ndb,
alterTable(&tSignal, ptr)
: createTable(&tSignal, ptr);
- if (haveAutoIncrement) {
+ if (!alter && haveAutoIncrement) {
// if (!ndb.setAutoIncrementValue(impl.m_internalName.c_str(), autoIncrementValue)) {
if (!ndb.setAutoIncrementValue(impl.m_externalName.c_str(), autoIncrementValue)) {
m_error.code = 4336;
@@ -1623,7 +1652,7 @@ NdbDictionaryImpl::dropBlobTables(NdbTableImpl & t)
{
for (unsigned i = 0; i < t.m_columns.size(); i++) {
NdbColumnImpl & c = *t.m_columns[i];
- if (! c.getBlobType())
+ if (! c.getBlobType() || c.getPartSize() == 0)
continue;
char btname[NdbBlob::BlobTableNameSize];
NdbBlob::getBlobTableName(btname, &t, &c);
@@ -1734,8 +1763,8 @@ NdbDictionaryImpl::getIndexImpl(const char * externalName,
return 0;
}
- NdbTableImpl* primTab = getTable(tab->m_primaryTable.c_str());
- if(primTab == 0){
+ NdbTableImpl* prim = getTable(tab->m_primaryTable.c_str());
+ if(prim == 0){
m_error.code = 4243;
return 0;
}
@@ -1749,7 +1778,7 @@ NdbDictionaryImpl::getIndexImpl(const char * externalName,
idx->m_indexId = tab->m_tableId;
idx->m_internalName.assign(internalName);
idx->m_externalName.assign(externalName);
- idx->m_tableName.assign(primTab->m_externalName);
+ idx->m_tableName.assign(prim->m_externalName);
idx->m_type = tab->m_indexType;
// skip last attribute (NDB$PK or NDB$TNODE)
for(unsigned i = 0; i+1<tab->m_columns.size(); i++){
@@ -1757,6 +1786,14 @@ NdbDictionaryImpl::getIndexImpl(const char * externalName,
// Copy column definition
*col = *tab->m_columns[i];
idx->m_columns.push_back(col);
+ /**
+ * reverse map
+ */
+ int key_id = prim->getColumn(col->getName())->getColumnNo();
+ int fill = -1;
+ idx->m_key_ids.fill(key_id, fill);
+ idx->m_key_ids[key_id] = i;
+ col->m_keyInfoPos = key_id;
}
idx->m_table = tab;
@@ -1788,7 +1825,7 @@ NdbDictInterface::createIndex(Ndb & ndb,
{
//validate();
//aggregate();
-
+ unsigned i;
UtilBufferWriter w(m_buffer);
const size_t len = strlen(impl.m_externalName.c_str()) + 1;
if(len > MAX_TAB_NAME_SIZE) {
@@ -1828,7 +1865,7 @@ NdbDictInterface::createIndex(Ndb & ndb,
req->setOnline(true);
AttributeList attributeList;
attributeList.sz = impl.m_columns.size();
- for(unsigned i = 0; i<attributeList.sz; i++){
+ for(i = 0; i<attributeList.sz; i++){
const NdbColumnImpl* col =
table.getColumn(impl.m_columns[i]->m_name.c_str());
if(col == 0){
@@ -1842,18 +1879,11 @@ NdbDictInterface::createIndex(Ndb & ndb,
m_error.code = 4245;
return -1;
}
-
- if (it == DictTabInfo::UniqueHashIndex &&
- (col->m_nullable) && (attributeList.sz > 1)) {
- // We only support one NULL attribute
- m_error.code = 4246;
- return -1;
- }
attributeList.id[i] = col->m_attrId;
}
if (it == DictTabInfo::UniqueHashIndex) {
// Sort index attributes according to primary table (using insertion sort)
- for(unsigned i = 1; i < attributeList.sz; i++) {
+ for(i = 1; i < attributeList.sz; i++) {
unsigned int temp = attributeList.id[i];
unsigned int j = i;
while((j > 0) && (attributeList.id[j - 1] > temp)) {
@@ -1863,7 +1893,7 @@ NdbDictInterface::createIndex(Ndb & ndb,
attributeList.id[j] = temp;
}
// Check for illegal duplicate attributes
- for(unsigned i = 0; i<attributeList.sz; i++) {
+ for(i = 0; i<attributeList.sz; i++) {
if ((i != (attributeList.sz - 1)) &&
(attributeList.id[i] == attributeList.id[i+1])) {
m_error.code = 4258;
@@ -2043,6 +2073,7 @@ NdbDictInterface::execDROP_INDX_REF(NdbApiSignal * signal,
int
NdbDictionaryImpl::createEvent(NdbEventImpl & evnt)
{
+ int i;
NdbTableImpl* tab = getTable(evnt.getTable());
if(tab == 0){
@@ -2065,7 +2096,7 @@ NdbDictionaryImpl::createEvent(NdbEventImpl & evnt)
int attributeList_sz = evnt.m_attrIds.size();
- for (int i = 0; i < attributeList_sz; i++) {
+ for (i = 0; i < attributeList_sz; i++) {
NdbColumnImpl *col_impl = table.getColumn(evnt.m_attrIds[i]);
if (col_impl) {
evnt.m_facade->addColumn(*(col_impl->m_facade));
@@ -2086,7 +2117,7 @@ NdbDictionaryImpl::createEvent(NdbEventImpl & evnt)
int pk_count = 0;
evnt.m_attrListBitmask.clear();
- for(int i = 0; i<attributeList_sz; i++){
+ for(i = 0; i<attributeList_sz; i++){
const NdbColumnImpl* col =
table.getColumn(evnt.m_columns[i]->m_name.c_str());
if(col == 0){
@@ -2104,7 +2135,7 @@ NdbDictionaryImpl::createEvent(NdbEventImpl & evnt)
}
// Sort index attributes according to primary table (using insertion sort)
- for(int i = 1; i < attributeList_sz; i++) {
+ for(i = 1; i < attributeList_sz; i++) {
NdbColumnImpl* temp = evnt.m_columns[i];
unsigned int j = i;
while((j > 0) && (evnt.m_columns[j - 1]->m_attrId > temp->m_attrId)) {
@@ -2114,7 +2145,7 @@ NdbDictionaryImpl::createEvent(NdbEventImpl & evnt)
evnt.m_columns[j] = temp;
}
// Check for illegal duplicate attributes
- for(int i = 1; i<attributeList_sz; i++) {
+ for(i = 1; i<attributeList_sz; i++) {
if (evnt.m_columns[i-1]->m_attrId == evnt.m_columns[i]->m_attrId) {
m_error.code = 4258;
return -1;
@@ -2788,6 +2819,7 @@ NdbDictInterface::listObjects(NdbApiSignal* signal)
m_waiter.m_node = aNodeId;
m_waiter.m_state = WAIT_LIST_TABLES_CONF;
m_waiter.wait(WAITFOR_RESPONSE_TIMEOUT);
+ m_transporter->unlock_mutex();
// end protected
if (m_waiter.m_state == NO_WAIT && m_error.code == 0)
return 0;
@@ -2810,3 +2842,10 @@ NdbDictInterface::execLIST_TABLES_CONF(NdbApiSignal* signal,
m_waiter.signal(NO_WAIT);
}
}
+
+template class Vector<int>;
+template class Vector<Uint32>;
+template class Vector<Vector<Uint32> >;
+template class Vector<NdbTableImpl*>;
+template class Vector<NdbColumnImpl*>;
+
diff --git a/ndb/src/ndbapi/NdbDictionaryImpl.hpp b/ndb/src/ndbapi/NdbDictionaryImpl.hpp
index bf59838c198..9a890f02575 100644
--- a/ndb/src/ndbapi/NdbDictionaryImpl.hpp
+++ b/ndb/src/ndbapi/NdbDictionaryImpl.hpp
@@ -71,6 +71,7 @@ public:
bool m_autoIncrement;
Uint64 m_autoIncrementInitialValue;
BaseString m_defaultValue;
+ NdbTableImpl * m_blobTable;
/**
* Internal types and sizes, and aggregates
@@ -124,7 +125,9 @@ public:
int m_kvalue;
int m_minLoadFactor;
int m_maxLoadFactor;
-
+ int m_keyLenInWords;
+ int m_fragmentCount;
+
NdbDictionaryImpl * m_dictionary;
NdbIndexImpl * m_index;
NdbColumnImpl * getColumn(unsigned attrId);
@@ -168,12 +171,14 @@ public:
const char * getName() const;
void setTable(const char * table);
const char * getTable() const;
+ const NdbTableImpl * getIndexTable() const;
Uint32 m_indexId;
BaseString m_internalName;
BaseString m_externalName;
BaseString m_tableName;
Vector<NdbColumnImpl *> m_columns;
+ Vector<int> m_key_ids;
NdbDictionary::Index::Type m_type;
bool m_logging;
@@ -358,6 +363,7 @@ public:
int createTable(NdbTableImpl &t);
int createBlobTables(NdbTableImpl &);
+ int addBlobTables(NdbTableImpl &);
int alterTable(NdbTableImpl &t);
int dropTable(const char * name);
int dropTable(NdbTableImpl &);
@@ -438,7 +444,7 @@ inline
bool
NdbColumnImpl::getBlobType() const {
return (m_type == NdbDictionary::Column::Blob ||
- m_type == NdbDictionary::Column::Clob);
+ m_type == NdbDictionary::Column::Text);
}
inline
@@ -612,7 +618,6 @@ NdbDictionaryImpl::getTableImpl(const char * internalTableName)
if (ret == 0){
ret = m_receiver.getTable(internalTableName, m_ndb.usingFullyQualifiedNames());
-
m_globalHash->lock();
m_globalHash->put(internalTableName, ret);
m_globalHash->unlock();
@@ -625,6 +630,8 @@ NdbDictionaryImpl::getTableImpl(const char * internalTableName)
m_ndb.theFirstTupleId[ret->getTableId()] = ~0;
m_ndb.theLastTupleId[ret->getTableId()] = ~0;
+
+ addBlobTables(*ret);
return ret;
}
diff --git a/ndb/src/ndbapi/NdbEventOperation.cpp b/ndb/src/ndbapi/NdbEventOperation.cpp
index ebdebaffd61..506a6c8d86d 100644
--- a/ndb/src/ndbapi/NdbEventOperation.cpp
+++ b/ndb/src/ndbapi/NdbEventOperation.cpp
@@ -37,7 +37,7 @@
NdbEventOperation::NdbEventOperation(Ndb *theNdb,
const char* eventName,
- const int bufferLength)
+ int bufferLength)
: m_impl(* new NdbEventOperationImpl(*this,theNdb,
eventName,
bufferLength))
diff --git a/ndb/src/ndbapi/NdbEventOperationImpl.cpp b/ndb/src/ndbapi/NdbEventOperationImpl.cpp
index b73a58d97c4..f5e683b1c29 100644
--- a/ndb/src/ndbapi/NdbEventOperationImpl.cpp
+++ b/ndb/src/ndbapi/NdbEventOperationImpl.cpp
@@ -93,11 +93,12 @@ NdbEventOperationImpl::NdbEventOperationImpl(NdbEventOperation &N,
NdbEventOperationImpl::~NdbEventOperationImpl()
{
+ int i;
if (sdata) NdbMem_Free(sdata);
- for (int i=0 ; i<3; i++) {
+ for (i=0 ; i<3; i++) {
if (ptr[i].p) NdbMem_Free(ptr[i].p);
}
- for (int i=0 ; i<2; i++) {
+ for (i=0 ; i<2; i++) {
NdbRecAttr *p = theFirstRecAttrs[i];
while (p) {
NdbRecAttr *p_next = p->next();
@@ -166,7 +167,7 @@ NdbEventOperationImpl::getValue(const NdbColumnImpl *tAttrInfo, char *aValue, in
}
//theErrorLine++;
- tRecAttr->setUNDEFINED();
+ tRecAttr->setNULL();
// We want to keep the list sorted to make data insertion easier later
if (theFirstRecAttr == NULL) {
@@ -387,7 +388,7 @@ NdbEventOperationImpl::next(int *pOverrun)
while (tAttrId > tRecAttrId) {
//printf("[%u] %u %u [%u]\n", tAttrId, tDataSz, *aDataPtr, tRecAttrId);
- tWorkingRecAttr->setUNDEFINED();
+ tWorkingRecAttr->setNULL();
tWorkingRecAttr = tWorkingRecAttr->next();
if (tWorkingRecAttr == NULL)
break;
@@ -399,19 +400,16 @@ NdbEventOperationImpl::next(int *pOverrun)
//printf("[%u] %u %u [%u]\n", tAttrId, tDataSz, *aDataPtr, tRecAttrId);
if (tAttrId == tRecAttrId) {
- tWorkingRecAttr->setNotNULL();
if (!m_eventImpl->m_tableImpl->getColumn(tRecAttrId)->getPrimaryKey())
hasSomeData++;
//printf("set!\n");
- Uint32 *theRef = (Uint32*)tWorkingRecAttr->aRef();
- Uint32 *theEndRef = theRef + tDataSz;
- while (theRef < theEndRef)
- *theRef++ = *aDataPtr++;
+ tWorkingRecAttr->receive_data(aDataPtr, tDataSz);
// move forward, data has already moved forward
aAttrPtr++;
+ aDataPtr += tDataSz;
tWorkingRecAttr = tWorkingRecAttr->next();
} else {
// move only attr forward
@@ -423,7 +421,7 @@ NdbEventOperationImpl::next(int *pOverrun)
while (tWorkingRecAttr != NULL) {
tRecAttrId = tWorkingRecAttr->attrId();
//printf("set undefined [%u] %u %u [%u]\n", tAttrId, tDataSz, *aDataPtr, tRecAttrId);
- tWorkingRecAttr->setUNDEFINED();
+ tWorkingRecAttr->setNULL();
tWorkingRecAttr = tWorkingRecAttr->next();
}
@@ -436,7 +434,7 @@ NdbEventOperationImpl::next(int *pOverrun)
tDataSz = AttributeHeader(*aDataPtr).getDataSize();
aDataPtr++;
while (tAttrId > tRecAttrId) {
- tWorkingRecAttr->setUNDEFINED();
+ tWorkingRecAttr->setNULL();
tWorkingRecAttr = tWorkingRecAttr->next();
if (tWorkingRecAttr == NULL)
break;
@@ -445,16 +443,11 @@ NdbEventOperationImpl::next(int *pOverrun)
if (tWorkingRecAttr == NULL)
break;
if (tAttrId == tRecAttrId) {
- tWorkingRecAttr->setNotNULL();
-
if (!m_eventImpl->m_tableImpl->getColumn(tRecAttrId)->getPrimaryKey())
hasSomeData++;
- Uint32 *theRef = (Uint32*)tWorkingRecAttr->aRef();
- Uint32 *theEndRef = theRef + tDataSz;
- while (theRef < theEndRef)
- *theRef++ = *aDataPtr++;
-
+ tWorkingRecAttr->receive_data(aDataPtr, tDataSz);
+ aDataPtr += tDataSz;
// move forward, data+attr has already moved forward
tWorkingRecAttr = tWorkingRecAttr->next();
} else {
@@ -463,7 +456,7 @@ NdbEventOperationImpl::next(int *pOverrun)
}
}
while (tWorkingRecAttr != NULL) {
- tWorkingRecAttr->setUNDEFINED();
+ tWorkingRecAttr->setNULL();
tWorkingRecAttr = tWorkingRecAttr->next();
}
@@ -1233,8 +1226,9 @@ NdbGlobalEventBuffer::real_wait(NdbGlobalEventBufferHandle *h,
int aMillisecondNumber)
{
// check if there are anything in any of the buffers
+ int i;
int n = 0;
- for (int i = 0; i < h->m_nids; i++)
+ for (i = 0; i < h->m_nids; i++)
n += hasData(h->m_bufferIds[i]);
if (n) return n;
@@ -1243,7 +1237,9 @@ NdbGlobalEventBuffer::real_wait(NdbGlobalEventBufferHandle *h,
return -1;
n = 0;
- for (int i = 0; i < h->m_nids; i++)
+ for (i = 0; i < h->m_nids; i++)
n += hasData(h->m_bufferIds[i]);
return n;
}
+
+template class Vector<NdbGlobalEventBufferHandle*>;
diff --git a/ndb/src/ndbapi/NdbImpl.hpp b/ndb/src/ndbapi/NdbImpl.hpp
index cd05335b337..1fb1969b589 100644
--- a/ndb/src/ndbapi/NdbImpl.hpp
+++ b/ndb/src/ndbapi/NdbImpl.hpp
@@ -35,6 +35,7 @@ public:
#include <NdbError.hpp>
#include <NdbCondition.h>
#include <NdbReceiver.hpp>
+#include <NdbOperation.hpp>
#include <NdbTick.h>
@@ -83,12 +84,13 @@ Ndb::void2rec_iop(void* val){
return (NdbIndexOperation*)(void2rec(val)->getOwner());
}
-inline
-NdbScanReceiver*
-Ndb::void2rec_srec(void* val){
- return (NdbScanReceiver*)(void2rec(val)->getOwner());
+inline
+NdbConnection *
+NdbReceiver::getTransaction(){
+ return ((NdbOperation*)m_owner)->theNdbCon;
}
+
inline
int
Ndb::checkInitState()
@@ -151,7 +153,6 @@ NdbWaiter::wait(int waitTime)
waitTime = maxTime - NdbTick_CurrentMillisecond();
}
}
- NdbMutex_Unlock((NdbMutex*)m_mutex);
}
inline
diff --git a/ndb/src/ndbapi/NdbIndexOperation.cpp b/ndb/src/ndbapi/NdbIndexOperation.cpp
index 631c09e2e6d..7bea3b9f3d2 100644
--- a/ndb/src/ndbapi/NdbIndexOperation.cpp
+++ b/ndb/src/ndbapi/NdbIndexOperation.cpp
@@ -14,18 +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 */
-/*****************************************************************************
- * Name: NdbIndexOperation.cpp
- * Include:
- * Link:
- * Author: UABMASD Martin Sköld INN/V Alzato
- * Date: 2002-04-01
- * Version: 0.1
- * Description: Secondary index support
- * Documentation:
- * Adjust: 2002-04-01 UABMASD First version.
- ****************************************************************************/
-
+#include <ndb_global.h>
#include <NdbIndexOperation.hpp>
#include <NdbResultSet.hpp>
#include <Ndb.hpp>
@@ -37,8 +26,6 @@
#include <signaldata/IndxKeyInfo.hpp>
#include <signaldata/IndxAttrInfo.hpp>
-#define CHECK_NULL(v) assert(v == NULL); v = NULL;
-
NdbIndexOperation::NdbIndexOperation(Ndb* aNdb) :
NdbOperation(aNdb),
m_theIndex(NULL),
@@ -675,10 +662,8 @@ NdbIndexOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64 aTransactionId)
tSignal = tnextSignal;
} while (tSignal != NULL);
}//if
- NdbRecAttr* tRecAttrObject = theFirstRecAttr;
theStatus = WaitResponse;
- theCurrentRecAttr = tRecAttrObject;
-
+ theReceiver.prepareSend();
return 0;
}
diff --git a/ndb/src/ndbapi/NdbLinHash.hpp b/ndb/src/ndbapi/NdbLinHash.hpp
index f67d4e60200..5d0d52a31d8 100644
--- a/ndb/src/ndbapi/NdbLinHash.hpp
+++ b/ndb/src/ndbapi/NdbLinHash.hpp
@@ -165,13 +165,14 @@ NdbLinHash<C>::createHashTable() {
max = SEGMENTSIZE - 1;
slack = SEGMENTSIZE * MAXLOADFCTR;
directory[0] = new Segment_t();
-
+ int i;
+
/* The first segment cleared before used */
- for(int i = 0; i < SEGMENTSIZE; i++ )
+ for(i = 0; i < SEGMENTSIZE; i++ )
directory[0]->elements[i] = 0;
/* clear the rest of the directory */
- for( int i = 1; i < DIRECTORYSIZE; i++)
+ for(i = 1; i < DIRECTORYSIZE; i++)
directory[i] = 0;
}
@@ -203,7 +204,8 @@ NdbLinHash<C>::insertKey( const char* str, Uint32 len, Uint32 lkey1, C* data )
* chain=chainp will copy the contents of HASH_T into chain
*/
NdbElement_t<C> * oldChain = 0;
- for(NdbElement_t<C> * chain = *chainp; chain != 0; chain = chain->next){
+ NdbElement_t<C> * chain;
+ for(chain = *chainp; chain != 0; chain = chain->next){
if(chain->len == len && !memcmp(chain->str, str, len))
return -1; /* Element already exists */
else
@@ -211,7 +213,7 @@ NdbLinHash<C>::insertKey( const char* str, Uint32 len, Uint32 lkey1, C* data )
}
/* New entry */
- NdbElement_t<C> * chain = new NdbElement_t<C>();
+ chain = new NdbElement_t<C>();
chain->len = len;
chain->hash = hash;
chain->localkey1 = lkey1;
diff --git a/ndb/src/ndbapi/NdbOperation.cpp b/ndb/src/ndbapi/NdbOperation.cpp
index e6031a58c5f..18a7d1d1c80 100644
--- a/ndb/src/ndbapi/NdbOperation.cpp
+++ b/ndb/src/ndbapi/NdbOperation.cpp
@@ -14,20 +14,9 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/*****************************************************************************
- * Name: NdbOperation.C
- * Include:
- * Link:
- * Author: UABMNST Mona Natterkvist UAB/B/SD
- * Date: 970829
- * Version: 0.1
- * Description: Interface between TIS and NDB
- * Documentation:
- * Adjust: 971022 UABMNST First version.
- ****************************************************************************/
-#include "NdbConnection.hpp"
-#include "NdbOperation.hpp"
+#include <ndb_global.h>
+#include <NdbConnection.hpp>
+#include <NdbOperation.hpp>
#include "NdbApiSignal.hpp"
#include "NdbRecAttr.hpp"
#include "NdbUtil.hpp"
@@ -55,7 +44,6 @@ NdbOperation::NdbOperation(Ndb* aNdb) :
//theTable(aTable),
theNdbCon(NULL),
theNext(NULL),
- theNextScanOp(NULL),
theTCREQ(NULL),
theFirstATTRINFO(NULL),
theCurrentATTRINFO(NULL),
@@ -63,8 +51,6 @@ NdbOperation::NdbOperation(Ndb* aNdb) :
theAI_LenInCurrAI(0),
theFirstKEYINFO(NULL),
theLastKEYINFO(NULL),
- theFirstRecAttr(NULL),
- theCurrentRecAttr(NULL),
theFirstLabel(NULL),
theLastLabel(NULL),
@@ -77,10 +63,6 @@ NdbOperation::NdbOperation(Ndb* aNdb) :
theNoOfLabels(0),
theNoOfSubroutines(0),
- theTotalRecAI_Len(0),
- theCurrRecAI_Len(0),
- theAI_ElementLen(0),
- theCurrElemPtr(NULL),
m_currentTable(NULL), //theTableId(0xFFFF),
m_accessTable(NULL), //theAccessTableId(0xFFFF),
//theSchemaVersion(0),
@@ -96,14 +78,6 @@ NdbOperation::NdbOperation(Ndb* aNdb) :
m_tcReqGSN(GSN_TCKEYREQ),
m_keyInfoGSN(GSN_KEYINFO),
m_attrInfoGSN(GSN_ATTRINFO),
- theParallelism(0),
- theScanReceiversArray(NULL),
- theSCAN_TABREQ(NULL),
- theFirstSCAN_TABINFO_Send(NULL),
- theLastSCAN_TABINFO_Send(NULL),
- theFirstSCAN_TABINFO_Recv(NULL),
- theLastSCAN_TABINFO_Recv(NULL),
- theSCAN_TABCONF_Recv(NULL),
theBoundATTRINFO(NULL),
theBlobList(NULL)
{
@@ -167,7 +141,7 @@ NdbOperation::init(NdbTableImpl* tab, NdbConnection* myConnection){
theNdbCon = myConnection;
for (Uint32 i=0; i<NDB_MAX_NO_OF_ATTRIBUTES_IN_KEY; i++)
for (int j=0; j<3; j++)
- theTupleKeyDefined[i][j] = false;
+ theTupleKeyDefined[i][j] = 0;
theFirstATTRINFO = NULL;
theCurrentATTRINFO = NULL;
@@ -177,13 +151,11 @@ NdbOperation::init(NdbTableImpl* tab, NdbConnection* myConnection){
theTupKeyLen = 0;
theNoOfTupKeyDefined = 0;
- theTotalCurrAI_Len = 0;
- theAI_LenInCurrAI = 0;
- theTotalRecAI_Len = 0;
theDistrKeySize = 0;
theDistributionGroup = 0;
- theCurrRecAI_Len = 0;
- theAI_ElementLen = 0;
+
+ theTotalCurrAI_Len = 0;
+ theAI_LenInCurrAI = 0;
theStartIndicator = 0;
theCommitIndicator = 0;
theSimpleIndicator = 0;
@@ -193,9 +165,6 @@ NdbOperation::init(NdbTableImpl* tab, NdbConnection* myConnection){
theDistrGroupType = 0;
theDistrKeyIndicator = 0;
theScanInfo = 0;
- theFirstRecAttr = NULL;
- theCurrentRecAttr = NULL;
- theCurrElemPtr = NULL;
theTotalNrOfKeyWordInSignal = 8;
theMagicNumber = 0xABCDEF01;
theBoundATTRINFO = NULL;
@@ -215,6 +184,7 @@ NdbOperation::init(NdbTableImpl* tab, NdbConnection* myConnection){
tcKeyReq->scanInfo = 0;
theKEYINFOptr = &tcKeyReq->keyInfo[0];
theATTRINFOptr = &tcKeyReq->attrInfo[0];
+ theReceiver.init(NdbReceiver::NDB_OPERATION, this);
return 0;
}
@@ -229,8 +199,6 @@ NdbOperation::release()
{
NdbApiSignal* tSignal;
NdbApiSignal* tSaveSignal;
- NdbRecAttr* tRecAttr;
- NdbRecAttr* tSaveRecAttr;
NdbBranch* tBranch;
NdbBranch* tSaveBranch;
NdbLabel* tLabel;
@@ -265,15 +233,6 @@ NdbOperation::release()
}
theFirstKEYINFO = NULL;
theLastKEYINFO = NULL;
- tRecAttr = theFirstRecAttr;
- while (tRecAttr != NULL)
- {
- tSaveRecAttr = tRecAttr;
- tRecAttr = tRecAttr->next();
- theNdb->releaseRecAttr(tSaveRecAttr);
- }
- theFirstRecAttr = NULL;
- theCurrentRecAttr = NULL;
if (theInterpretIndicator == 1)
{
tBranch = theFirstBranch;
@@ -321,19 +280,19 @@ NdbOperation::release()
theNdb->releaseNdbBlob(tSaveBlob);
}
theBlobList = NULL;
- releaseScan();
+ theReceiver.release();
}
NdbRecAttr*
NdbOperation::getValue(const char* anAttrName, char* aValue)
{
- return getValue(m_currentTable->getColumn(anAttrName), aValue);
+ return getValue_impl(m_currentTable->getColumn(anAttrName), aValue);
}
NdbRecAttr*
NdbOperation::getValue(Uint32 anAttrId, char* aValue)
{
- return getValue(m_currentTable->getColumn(anAttrId), aValue);
+ return getValue_impl(m_currentTable->getColumn(anAttrId), aValue);
}
int
@@ -441,18 +400,6 @@ NdbOperation::write_attr(Uint32 anAttrId, Uint32 RegDest)
return write_attr(m_currentTable->getColumn(anAttrId), RegDest);
}
-int
-NdbOperation::setBound(const char* anAttrName, int type, const void* aValue, Uint32 len)
-{
- return setBound(m_accessTable->getColumn(anAttrName), type, aValue, len);
-}
-
-int
-NdbOperation::setBound(Uint32 anAttrId, int type, const void* aValue, Uint32 len)
-{
- return setBound(m_accessTable->getColumn(anAttrId), type, aValue, len);
-}
-
const char*
NdbOperation::getTableName() const
{
diff --git a/ndb/src/ndbapi/NdbOperationDefine.cpp b/ndb/src/ndbapi/NdbOperationDefine.cpp
index 69a6602fe65..08ed6e84271 100644
--- a/ndb/src/ndbapi/NdbOperationDefine.cpp
+++ b/ndb/src/ndbapi/NdbOperationDefine.cpp
@@ -34,6 +34,7 @@
#include "NdbUtil.hpp"
#include "NdbOut.hpp"
#include "NdbImpl.hpp"
+#include <NdbIndexScanOperation.hpp>
#include "NdbBlob.hpp"
#include <Interpreter.hpp>
@@ -262,30 +263,10 @@ NdbOperation::interpretedUpdateTuple()
theStatus = OperationDefined;
tNdbCon->theSimpleState = 0;
theOperationType = UpdateRequest;
- theInterpretIndicator = 1;
theAI_LenInCurrAI = 25;
theErrorLine = tErrorLine++;
- theTotalCurrAI_Len = 5;
- theSubroutineSize = 0;
- theInitialReadSize = 0;
- theInterpretedSize = 0;
- theFinalUpdateSize = 0;
- theFinalReadSize = 0;
-
- theFirstLabel = NULL;
- theLastLabel = NULL;
- theFirstBranch = NULL;
- theLastBranch = NULL;
-
- theFirstCall = NULL;
- theLastCall = NULL;
- theFirstSubroutine = NULL;
- theLastSubroutine = NULL;
-
- theNoOfLabels = 0;
- theNoOfSubroutines = 0;
-
+ initInterpreter();
return 0;
} else {
setErrorCode(4200);
@@ -305,30 +286,11 @@ NdbOperation::interpretedDeleteTuple()
theStatus = OperationDefined;
tNdbCon->theSimpleState = 0;
theOperationType = DeleteRequest;
- theInterpretIndicator = 1;
theErrorLine = tErrorLine++;
theAI_LenInCurrAI = 25;
- theTotalCurrAI_Len = 5;
- theSubroutineSize = 0;
- theInitialReadSize = 0;
- theInterpretedSize = 0;
- theFinalUpdateSize = 0;
- theFinalReadSize = 0;
-
- theFirstLabel = NULL;
- theLastLabel = NULL;
- theFirstBranch = NULL;
- theLastBranch = NULL;
-
- theFirstCall = NULL;
- theLastCall = NULL;
- theFirstSubroutine = NULL;
- theLastSubroutine = NULL;
-
- theNoOfLabels = 0;
- theNoOfSubroutines = 0;
+ initInterpreter();
return 0;
} else {
setErrorCode(4200);
@@ -348,14 +310,14 @@ NdbOperation::interpretedDeleteTuple()
* Remark: Define an attribute to retrieve in query.
*****************************************************************************/
NdbRecAttr*
-NdbOperation::getValue(const NdbColumnImpl* tAttrInfo, char* aValue)
+NdbOperation::getValue_impl(const NdbColumnImpl* tAttrInfo, char* aValue)
{
NdbRecAttr* tRecAttr;
if ((tAttrInfo != NULL) &&
(!tAttrInfo->m_indexOnly) &&
(theStatus != Init)){
if (theStatus == SetBound) {
- saveBoundATTRINFO();
+ ((NdbIndexScanOperation*)this)->saveBoundATTRINFO();
theStatus = GetValue;
}
if (theStatus != GetValue) {
@@ -387,33 +349,15 @@ NdbOperation::getValue(const NdbColumnImpl* tAttrInfo, char* aValue)
// Insert Attribute Id into ATTRINFO part.
/************************************************************************
- * Get a Receive Attribute object and link it into the operation object.
- ************************************************************************/
- tRecAttr = theNdb->getRecAttr();
- if (tRecAttr != NULL) {
- if (theFirstRecAttr == NULL)
- theFirstRecAttr = tRecAttr;
- else
- theCurrentRecAttr->next(tRecAttr);
- theCurrentRecAttr = tRecAttr;
- tRecAttr->next(NULL);
-
- /**********************************************************************
- * Now set the attribute identity and the pointer to the data in
- * the RecAttr object
- * Also set attribute size, array size and attribute type
- ********************************************************************/
- if (tRecAttr->setup(tAttrInfo, aValue) == 0) {
- theErrorLine++;
- return tRecAttr;
- } else {
- setErrorCodeAbort(4000);
- return NULL;
- }
- } else {
+ * Get a Receive Attribute object and link it into the operation object.
+ ***********************************************************************/
+ if((tRecAttr = theReceiver.getValue(tAttrInfo, aValue)) != 0){
+ theErrorLine++;
+ return tRecAttr;
+ } else {
setErrorCodeAbort(4000);
return NULL;
- }//if getRecAttr failure
+ }
} else {
return NULL;
}//if insertATTRINFO failure
@@ -632,47 +576,6 @@ NdbOperation::getBlobHandle(NdbConnection* aCon, const NdbColumnImpl* tAttrInfo)
return tBlob;
}
-/*
- * Define bound on index column in range scan.
- */
-int
-NdbOperation::setBound(const NdbColumnImpl* tAttrInfo, int type, const void* aValue, Uint32 len)
-{
- if (theOperationType == OpenRangeScanRequest &&
- theStatus == SetBound &&
- (0 <= type && type <= 4) &&
- aValue != NULL &&
- len <= 8000) {
- // bound type
- insertATTRINFO(type);
- // attribute header
- Uint32 sizeInBytes = tAttrInfo->m_attrSize * tAttrInfo->m_arraySize;
- if (len != sizeInBytes && (len != 0)) {
- setErrorCodeAbort(4209);
- return -1;
- }
- len = sizeInBytes;
- Uint32 tIndexAttrId = tAttrInfo->m_attrId;
- Uint32 sizeInWords = (len + 3) / 4;
- AttributeHeader ah(tIndexAttrId, sizeInWords);
- insertATTRINFO(ah.m_value);
- // attribute data
- if ((UintPtr(aValue) & 0x3) == 0 && (len & 0x3) == 0)
- insertATTRINFOloop((const Uint32*)aValue, sizeInWords);
- else {
- Uint32 temp[2000];
- memcpy(temp, aValue, len);
- while ((len & 0x3) != 0)
- ((char*)temp)[len++] = 0;
- insertATTRINFOloop(temp, sizeInWords);
- }
- return 0;
- } else {
- setErrorCodeAbort(4228); // XXX wrong code
- return -1;
- }
-}
-
/****************************************************************************
* int insertATTRINFO( Uint32 aData );
*
diff --git a/ndb/src/ndbapi/NdbOperationExec.cpp b/ndb/src/ndbapi/NdbOperationExec.cpp
index d00c527550d..7ee76bf2f3e 100644
--- a/ndb/src/ndbapi/NdbOperationExec.cpp
+++ b/ndb/src/ndbapi/NdbOperationExec.cpp
@@ -14,18 +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 */
-
-/***************************************************************************
-Name: NdbOperationExec.C
-Include:
-Link:
-Author: UABRONM Mikael Ronström UAB/M/MT Jonas Kamf UAB/M/MT
-Date: 2001-10-16
-Version: 1.2
-Description:
-Documentation:
-***************************************************************************/
-
+#include <ndb_global.h>
#include <NdbOperation.hpp>
#include <NdbConnection.hpp>
#include "NdbApiSignal.hpp"
@@ -46,83 +35,6 @@ Documentation:
#include <NdbOut.hpp>
-/******************************************************************************
-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
-NdbOperation::doSendScan(int aProcessorId)
-{
- Uint32 tSignalCount = 0;
- NdbApiSignal* tSignal;
-
- if (theInterpretIndicator != 1 ||
- (theOperationType != OpenScanRequest &&
- theOperationType != OpenRangeScanRequest)) {
- setErrorCodeAbort(4005);
- return -1;
- }
-
- assert(theSCAN_TABREQ != NULL);
- tSignal = theSCAN_TABREQ;
- if (tSignal->setSignal(GSN_SCAN_TABREQ) == -1) {
- setErrorCode(4001);
- return -1;
- }
- // 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 scanTabReq = CAST_PTR(ScanTabReq, tSignal->getDataPtrSend());
- scanTabReq->attrLen = theTotalCurrAI_Len;
- if (theOperationType == OpenRangeScanRequest)
- scanTabReq->attrLen += theTotalBoundAI_Len;
- TransporterFacade *tp = TransporterFacade::instance();
- if (tp->sendSignal(tSignal, aProcessorId) == -1) {
- setErrorCode(4002);
- return -1;
- }
- tSignalCount++;
-
- tSignal = theFirstSCAN_TABINFO_Send;
- while (tSignal != NULL){
- if (tp->sendSignal(tSignal, aProcessorId)) {
- setErrorCode(4002);
- return -1;
- }
- tSignalCount++;
- tSignal = tSignal->next();
- }
-
- if (theOperationType == OpenRangeScanRequest) {
- // must have at least one signal since it contains attrLen for bounds
- assert(theBoundATTRINFO != NULL);
- tSignal = theBoundATTRINFO;
- while (tSignal != NULL) {
- if (tp->sendSignal(tSignal,aProcessorId) == -1){
- setErrorCode(4002);
- return -1;
- }
- tSignalCount++;
- tSignal = tSignal->next();
- }
- }
-
- tSignal = theFirstATTRINFO;
- while (tSignal != NULL) {
- if (tp->sendSignal(tSignal,aProcessorId) == -1){
- setErrorCode(4002);
- return -1;
- }
- tSignalCount++;
- tSignal = tSignal->next();
- }
- theStatus = WaitResponse;
- return tSignalCount;
-}//NdbOperation::doSendScan()
void
NdbOperation::setLastFlag(NdbApiSignal* signal, Uint32 lastFlag)
@@ -178,62 +90,6 @@ NdbOperation::doSend(int aNodeId, Uint32 lastFlag)
}//NdbOperation::doSend()
/***************************************************************************
-int prepareSendScan(Uint32 aTC_ConnectPtr,
- Uint64 aTransactionId)
-
-Return Value: Return 0 : preparation of send was succesful.
- Return -1: In all other case.
-Parameters: aTC_ConnectPtr: the Connect pointer to TC.
- aTransactionId: the Transaction identity of the transaction.
-Remark: Puts the the final data into ATTRINFO signal(s) after this
- we know the how many signal to send and their sizes
-***************************************************************************/
-int NdbOperation::prepareSendScan(Uint32 aTC_ConnectPtr,
- Uint64 aTransactionId){
-
- if (theInterpretIndicator != 1 ||
- (theOperationType != OpenScanRequest &&
- theOperationType != OpenRangeScanRequest)) {
- setErrorCodeAbort(4005);
- return -1;
- }
-
- if (theStatus == SetBound) {
- saveBoundATTRINFO();
- theStatus = GetValue;
- }
-
- theErrorLine = 0;
-
- // In preapareSendInterpreted we set the sizes (word 4-8) in the
- // first ATTRINFO signal.
- if (prepareSendInterpreted() == -1)
- return -1;
-
- 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);
- return 0;
-}
-
-/***************************************************************************
int prepareSend(Uint32 aTC_ConnectPtr,
Uint64 aTransactionId)
@@ -457,6 +313,7 @@ NdbOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64 aTransId)
theTCREQ->setLength(tcKeyReq->getAIInTcKeyReq(tReqInfo) +
tAttrInfoIndex + TcKeyReq::StaticLength);
+
tAIDataPtr[0] = Tdata1;
tAIDataPtr[1] = Tdata2;
tAIDataPtr[2] = Tdata3;
@@ -479,9 +336,8 @@ NdbOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64 aTransId)
tSignal = tnextSignal;
} while (tSignal != NULL);
}//if
- NdbRecAttr* tRecAttrObject = theFirstRecAttr;
theStatus = WaitResponse;
- theCurrentRecAttr = tRecAttrObject;
+ theReceiver.prepareSend();
return 0;
}//NdbOperation::prepareSend()
@@ -648,71 +504,10 @@ NdbOperation::prepareSendInterpreted()
theFirstATTRINFO->setData(tFinalReadSize, 7);
theFirstATTRINFO->setData(tSubroutineSize, 8);
}//if
+ theReceiver.prepareSend();
return 0;
}//NdbOperation::prepareSendInterpreted()
-/***************************************************************************
-int TCOPCONF(int anAttrInfoLen)
-
-Return Value: Return 0 : send was succesful.
- Return -1: In all other case.
-Parameters: anAttrInfoLen: The length of the attribute information from TC.
-Remark: Handles the reception of the TC[KEY/INDX]CONF signal.
-***************************************************************************/
-void
-NdbOperation::TCOPCONF(Uint32 anAttrInfoLen)
-{
- Uint32 tCurrRecLen = theCurrRecAI_Len;
- if (theStatus == WaitResponse) {
- theTotalRecAI_Len = anAttrInfoLen;
- if (anAttrInfoLen == tCurrRecLen) {
- Uint32 tAI_ElemLen = theAI_ElementLen;
- NdbRecAttr* tCurrRecAttr = theCurrentRecAttr;
- theStatus = Finished;
-
- if ((tAI_ElemLen == 0) &&
- (tCurrRecAttr == NULL)) {
- NdbRecAttr* tRecAttr = theFirstRecAttr;
- while (tRecAttr != NULL) {
- if (tRecAttr->copyoutRequired()) // copy to application buffer
- tRecAttr->copyout();
- tRecAttr = tRecAttr->next();
- }
- theNdbCon->OpCompleteSuccess();
- return;
- } else if (tAI_ElemLen != 0) {
- setErrorCode(4213);
- theNdbCon->OpCompleteFailure();
- return;
- } else {
- setErrorCode(4214);
- theNdbCon->OpCompleteFailure();
- return;
- }//if
- } else if (anAttrInfoLen > tCurrRecLen) {
- return;
- } else {
- theStatus = Finished;
-
- if (theAI_ElementLen != 0) {
- setErrorCode(4213);
- theNdbCon->OpCompleteFailure();
- return;
- }//if
- if (theCurrentRecAttr != NULL) {
- setErrorCode(4214);
- theNdbCon->OpCompleteFailure();
- return;
- }//if
- theNdbCon->OpCompleteFailure();
- return;
- }//if
- } else {
- setErrorCode(4004);
- }//if
- return;
-}//NdbOperation::TCKEYOPCONF()
-
int
NdbOperation::checkState_TransId(NdbApiSignal* aSignal)
{
@@ -777,188 +572,13 @@ NdbOperation::receiveTCKEYREF( NdbApiSignal* aSignal)
}//NdbOperation::receiveTCKEYREF()
-/***************************************************************************
-int receiveREAD_CONF( NdbApiSignal* aSignal)
-
-Return Value: Return 0 : send was succesful.
- Return -1: In all other case.
-Parameters: aSignal: the signal object that contains the READCONF signal from TUP.
-Remark: Handles the reception of the READCONF signal.
-***************************************************************************/
-int
-NdbOperation::receiveREAD_CONF(const Uint32* aDataPtr, Uint32 aDataLength)
-{
- Uint64 tRecTransId, tCurrTransId;
- Uint32 tCondFlag = (Uint32)(theStatus - WaitResponse);
- Uint32 tTotLen = aDataPtr[3];
-
- tRecTransId = (Uint64)aDataPtr[1] + ((Uint64)aDataPtr[2] << 32);
- tCurrTransId = theNdbCon->getTransactionId();
- tCondFlag |= (Uint32)((tRecTransId - tCurrTransId) != (Uint64)0);
- tCondFlag |= (Uint32)(aDataLength < 4);
-
- if (tCondFlag == 0) {
- theTotalRecAI_Len = tTotLen;
- int tRetValue = receiveREAD_AI((Uint32*)&aDataPtr[4], (aDataLength - 4));
- if (theStatus == Finished) {
- return tRetValue;
- } else {
- theStatus = Finished;
- return theNdbCon->OpCompleteFailure();
- }//if
- }//if
-#ifdef NDB_NO_DROPPED_SIGNAL
- abort();
-#endif
- return -1;
-}//NdbOperation::receiveREAD_CONF()
-
-/***************************************************************************
-int receiveTRANSID_AI( NdbApiSignal* aSignal)
-
-Return Value: Return 0 : send was succesful.
- Return -1: In all other case.
-Parameters: aSignal: the signal object that contains the TRANSID_AI signal.
-Remark: Handles the reception of the TRANSID_AI signal.
-***************************************************************************/
-int
-NdbOperation::receiveTRANSID_AI(const Uint32* aDataPtr, Uint32 aDataLength)
-{
- Uint64 tRecTransId, tCurrTransId;
- Uint32 tCondFlag = (Uint32)(theStatus - WaitResponse);
-
- tRecTransId = (Uint64)aDataPtr[1] + ((Uint64)aDataPtr[2] << 32);
- tCurrTransId = theNdbCon->getTransactionId();
- tCondFlag |= (Uint32)((tRecTransId - tCurrTransId) != (Uint64)0);
- tCondFlag |= (Uint32)(aDataLength < 3);
-
- if (tCondFlag == 0) {
- return receiveREAD_AI((Uint32*)&aDataPtr[3], (aDataLength - 3));
- }//if
-#ifdef NDB_NO_DROPPED_SIGNAL
- abort();
-#endif
- return -1;
-}//NdbOperation::receiveTRANSID_AI()
-
-/***************************************************************************
-int receiveREAD_AI( NdbApiSignal* aSignal, int aLength, int aStartPos)
-
-Return Value: Return 0 : send was succesoccurredful.
- Return -1: In all other case.
-Parameters: aSignal: the signal object that contains the LEN_ATTRINFO11 signal.
- aLength:
- aStartPos:
-Remark: Handles the reception of the LEN_ATTRINFO11 signal.
-***************************************************************************/
-int
-NdbOperation::receiveREAD_AI(Uint32* aDataPtr, Uint32 aLength)
-{
-
- register Uint32 tAI_ElementLen = theAI_ElementLen;
- register Uint32* tCurrElemPtr = theCurrElemPtr;
- if (theError.code == 0) {
- // If inconsistency error occurred we will still continue
- // receiving signals since we need to know whether commit
- // has occurred.
-
- register Uint32 tData;
- for (register Uint32 i = 0; i < aLength ; i++, aDataPtr++)
- {
- // Code to receive Attribute Information
- tData = *aDataPtr;
- if (tAI_ElementLen != 0) {
- tAI_ElementLen--;
- *tCurrElemPtr = tData;
- tCurrElemPtr++;
- continue;
- } else {
- // Waiting for a new attribute element
- NdbRecAttr* tWorkingRecAttr;
-
- tWorkingRecAttr = theCurrentRecAttr;
- AttributeHeader ah(tData);
- const Uint32 tAttrId = ah.getAttributeId();
- const Uint32 tAttrSize = ah.getDataSize();
- if ((tWorkingRecAttr != NULL) &&
- (tWorkingRecAttr->attrId() == tAttrId)) {
- ;
- } else {
- setErrorCode(4211);
- break;
- }//if
- theCurrentRecAttr = tWorkingRecAttr->next();
- NdbColumnImpl * col = m_currentTable->getColumn(tAttrId);
- if (ah.isNULL()) {
- // Return a Null value from the NDB to the attribute.
- if(col != 0 && col->m_nullable) {
- tWorkingRecAttr->setNULL();
- tAI_ElementLen = 0;
- } else {
- setErrorCode(4212);
- break;
- }//if
- } else {
- // Return a value from the NDB to the attribute.
- tWorkingRecAttr->setNotNULL();
- const Uint32 sizeInBytes = col->m_attrSize * col->m_arraySize;
- const Uint32 sizeInWords = (sizeInBytes + 3) / 4;
- tAI_ElementLen = tAttrSize;
- tCurrElemPtr = (Uint32*)tWorkingRecAttr->aRef();
- if (sizeInWords == tAttrSize){
- continue;
- } else {
- setErrorCode(4201);
- break;
- }//if
- }//if
- }//if
- }//for
- }//if
- Uint32 tCurrRecLen = theCurrRecAI_Len;
- Uint32 tTotRecLen = theTotalRecAI_Len;
- theAI_ElementLen = tAI_ElementLen;
- theCurrElemPtr = tCurrElemPtr;
- tCurrRecLen = tCurrRecLen + aLength;
- theCurrRecAI_Len = tCurrRecLen; // Update Current Received AI Length
- if (tTotRecLen == tCurrRecLen){ // Operation completed
- NdbRecAttr* tCurrRecAttr = theCurrentRecAttr;
- theStatus = Finished;
-
- NdbConnection* tNdbCon = theNdbCon;
- if ((tAI_ElementLen == 0) &&
- (tCurrRecAttr == NULL)) {
- NdbRecAttr* tRecAttr = theFirstRecAttr;
- while (tRecAttr != NULL) {
- if (tRecAttr->copyoutRequired()) // copy to application buffer
- tRecAttr->copyout();
- tRecAttr = tRecAttr->next();
- }
- return tNdbCon->OpCompleteSuccess();
- } else if (tAI_ElementLen != 0) {
- setErrorCode(4213);
- return tNdbCon->OpCompleteFailure();
- } else {
- setErrorCode(4214);
- return tNdbCon->OpCompleteFailure();
- }//if
- }
- else if ((tCurrRecLen > tTotRecLen) &&
- (tTotRecLen > 0)) { /* == 0 if TCKEYCONF not yet received */
- setErrorCode(4215);
- theStatus = Finished;
-
- return theNdbCon->OpCompleteFailure();
- }//if
- return -1; // Continue waiting for more signals of this operation
-}//NdbOperation::receiveREAD_AI()
void
NdbOperation::handleFailedAI_ElemLen()
{
- NdbRecAttr* tRecAttr = theFirstRecAttr;
+ NdbRecAttr* tRecAttr = theReceiver.theFirstRecAttr;
while (tRecAttr != NULL) {
- tRecAttr->setUNDEFINED();
+ tRecAttr->setNULL();
tRecAttr = tRecAttr->next();
}//while
}//NdbOperation::handleFailedAI_ElemLen()
diff --git a/ndb/src/ndbapi/NdbOperationInt.cpp b/ndb/src/ndbapi/NdbOperationInt.cpp
index e61fc5b05d7..3a7e0dda85e 100644
--- a/ndb/src/ndbapi/NdbOperationInt.cpp
+++ b/ndb/src/ndbapi/NdbOperationInt.cpp
@@ -33,6 +33,7 @@ Adjust: 991029 UABRONM First version.
#include "NdbRecAttr.hpp"
#include "NdbUtil.hpp"
#include "Interpreter.hpp"
+#include <NdbIndexScanOperation.hpp>
#ifdef VM_TRACE
#include <NdbEnv.h>
@@ -43,6 +44,31 @@ Adjust: 991029 UABRONM First version.
#define INT_DEBUG(x)
#endif
+void
+NdbOperation::initInterpreter(){
+ theFirstLabel = NULL;
+ theLastLabel = NULL;
+ theFirstBranch = NULL;
+ theLastBranch = NULL;
+
+ theFirstCall = NULL;
+ theLastCall = NULL;
+ theFirstSubroutine = NULL;
+ theLastSubroutine = NULL;
+
+ theNoOfLabels = 0;
+ theNoOfSubroutines = 0;
+
+ theSubroutineSize = 0;
+ theInitialReadSize = 0;
+ theInterpretedSize = 0;
+ theFinalUpdateSize = 0;
+ theFinalReadSize = 0;
+ theInterpretIndicator = 1;
+
+ theTotalCurrAI_Len = 5;
+}
+
int
NdbOperation::incCheck(const NdbColumnImpl* tNdbColumnImpl)
{
@@ -191,7 +217,7 @@ NdbOperation::initial_interpreterCheck()
{
if ((theInterpretIndicator == 1)) {
if (theStatus == SetBound) {
- saveBoundATTRINFO();
+ ((NdbIndexScanOperation*)this)->saveBoundATTRINFO();
theStatus = GetValue;
}
if (theStatus == ExecInterpretedValue) {
@@ -382,9 +408,7 @@ NdbOperation::incValue(const NdbColumnImpl* tNdbColumnImpl, Uint64 aValue)
// Load aValue into register 7
if (insertATTRINFO( Interpreter::LoadConst64(7)) == -1)
goto incValue_error1;
- if (insertATTRINFO((Uint32)(aValue >> 32)) == -1)
- goto incValue_error1;
- if (insertATTRINFO(Uint32(aValue & 0xFFFFFFFF)) == -1)
+ if (insertATTRINFOloop((Uint32*)&aValue, 2) == -1)
goto incValue_error1;
// Add register 6 and 7 and put result in register 7
if (insertATTRINFO( Interpreter::Add(7, 6, 7)) == -1)
@@ -425,9 +449,7 @@ NdbOperation::subValue(const NdbColumnImpl* tNdbColumnImpl, Uint64 aValue)
// Load aValue into register 7
if (insertATTRINFO( Interpreter::LoadConst64(7)) == -1)
goto subValue_error1;
- if (insertATTRINFO((Uint32)(aValue >> 32)) == -1)
- goto subValue_error1;
- if (insertATTRINFO(Uint32(aValue & 0xFFFFFFFF)) == -1)
+ if (insertATTRINFOloop((Uint32*)&aValue, 2) == -1)
goto subValue_error1;
// Subtract register 6 and 7 and put result in register 7
if (insertATTRINFO( Interpreter::Sub(7, 6, 7)) == -1)
@@ -664,8 +686,6 @@ int
NdbOperation::load_const_u64(Uint32 RegDest, Uint64 Constant)
{
INT_DEBUG(("load_const_u64 %u %llu", RegDest, Constant));
- Uint32 tTemp1;
- Uint32 tTemp2;
if (initial_interpreterCheck() == -1)
return -1;
if (RegDest >= 8)
@@ -673,15 +693,11 @@ NdbOperation::load_const_u64(Uint32 RegDest, Uint64 Constant)
setErrorCodeAbort(4229);
return -1;
}
- tTemp1 = (Uint32)(Constant & 0xFFFFFFFF);
- tTemp2 = (Uint32)(Constant >> 32);
-
+
// 64 bit value
if (insertATTRINFO( Interpreter::LoadConst64(RegDest)) == -1)
return -1;
- if (insertATTRINFO(tTemp1) == -1)
- return -1;
- if (insertATTRINFO(tTemp2) == -1)
+ if (insertATTRINFOloop((Uint32*)&Constant, 2) == -1)
return -1;
theErrorLine++;
return 0;
diff --git a/ndb/src/ndbapi/NdbOperationScan.cpp b/ndb/src/ndbapi/NdbOperationScan.cpp
index 299e6f2adea..283eb591bdb 100644
--- a/ndb/src/ndbapi/NdbOperationScan.cpp
+++ b/ndb/src/ndbapi/NdbOperationScan.cpp
@@ -14,590 +14,3 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-#include "NdbOperation.hpp"
-#include "NdbScanReceiver.hpp"
-
-#include <signaldata/TcKeyReq.hpp>
-#include <signaldata/ScanTab.hpp>
-#include <signaldata/ScanFrag.hpp>
-#include <signaldata/KeyInfo.hpp>
-
-
-/******************************************************************************
- * int openScanRead();
- *****************************************************************************/
-int
-NdbOperation::openScanRead(Uint32 aParallelism)
-{
- aParallelism = checkParallelism(aParallelism);
-
- if ((theNdbCon->theCommitStatus != NdbConnection::Started) &&
- (theStatus != Init) &&
- (aParallelism == 0)) {
- setErrorCode(4200);
- return -1;
- }
- return openScan(aParallelism, false, false, false);
-}
-
-/****************************************************************************
- * int openScanExclusive();
- ****************************************************************************/
-int
-NdbOperation::openScanExclusive(Uint32 aParallelism)
-{
- aParallelism = checkParallelism(aParallelism);
-
- if ((theNdbCon->theCommitStatus != NdbConnection::Started) &&
- (theStatus != Init) &&
- (aParallelism == 0)) {
- setErrorCode(4200);
- return -1;
- }
- return openScan(aParallelism, true, true, false);
-}
-
-/******************************************************************************
- * int openScanReadHoldLock();
- *****************************************************************************/
-int
-NdbOperation::openScanReadHoldLock(Uint32 aParallelism)
-{
- aParallelism = checkParallelism(aParallelism);
-
- if ((theNdbCon->theCommitStatus != NdbConnection::Started) &&
- (theStatus != Init) &&
- (aParallelism == 0)) {
- setErrorCode(4200);
- return -1;
- }
- return openScan(aParallelism, false, true, false);
-}
-
-/******************************************************************************
- * int openScanReadCommitted();
- *****************************************************************************/
-int
-NdbOperation::openScanReadCommitted(Uint32 aParallelism)
-{
- aParallelism = checkParallelism(aParallelism);
-
- if ((theNdbCon->theCommitStatus != NdbConnection::Started) &&
- (theStatus != Init) &&
- (aParallelism == 0)) {
- setErrorCode(4200);
- return -1;
- }
- return openScan(aParallelism, false, false, true);
-}
-
-/****************************************************************************
- * int checkParallelism();
- * Remark If the parallelism is set wrong the number of scan-operations
- * will not correspond to the number of TRANSID_AI signals returned
- * from NDB and the result will be a crash, therefore
- * we adjust it or return an error if the value is totally wrong.
- ****************************************************************************/
-int
-NdbOperation::checkParallelism(Uint32 aParallelism)
-{
- if (aParallelism == 0) {
- setErrorCodeAbort(4232);
- return 0;
- }
- if (aParallelism > 16) {
- if (aParallelism <= 240) {
-
- /**
- * If tscanConcurrency > 16 it must be a multiple of 16
- */
- if (((aParallelism >> 4) << 4) < aParallelism) {
- aParallelism = ((aParallelism >> 4) << 4) + 16;
- }//if
-
- /*---------------------------------------------------------------*/
- /* We cannot have a parallelism > 16 per node */
- /*---------------------------------------------------------------*/
- if ((aParallelism / theNdb->theNoOfDBnodes) > 16) {
- aParallelism = theNdb->theNoOfDBnodes * 16;
- }//if
-
- } else {
- setErrorCodeAbort(4232);
- aParallelism = 0;
- }//if
- }//if
- return aParallelism;
-}//NdbOperation::checkParallelism()
-
-/**********************************************************************
- * int openScan();
- *************************************************************************/
-int
-NdbOperation::openScan(Uint32 aParallelism,
- bool lockMode, bool lockHoldMode, bool readCommitted)
-{
- aParallelism = checkParallelism(aParallelism);
- if(aParallelism == 0){
- return 0;
- }
- NdbScanReceiver* tScanRec;
- // It is only possible to call openScan if
- // 1. this transcation don't already contain another scan operation
- // 2. this transaction don't already contain other operations
- // 3. theScanOp contains a NdbScanOperation
- if (theNdbCon->theScanningOp != NULL){
- setErrorCode(4605);
- return -1;
- }
-
- if ((theNdbCon->theFirstOpInList != this) ||
- (theNdbCon->theLastOpInList != this)) {
- setErrorCode(4603);
- return -1;
- }
- theNdbCon->theScanningOp = this;
-
- initScan();
- theParallelism = aParallelism;
-
- // If the scan is on ordered index then it is a range scan
- if (m_currentTable->m_indexType == NdbDictionary::Index::OrderedIndex ||
- m_currentTable->m_indexType == NdbDictionary::Index::UniqueOrderedIndex) {
- assert(m_currentTable == m_accessTable);
- m_currentTable = theNdb->theDictionary->getTable(m_currentTable->m_primaryTable.c_str());
- assert(m_currentTable != NULL);
- // Modify operation state
- theStatus = SetBound;
- theOperationType = OpenRangeScanRequest;
- }
-
- theScanReceiversArray = new NdbScanReceiver* [aParallelism];
- if (theScanReceiversArray == NULL){
- setErrorCodeAbort(4000);
- return -1;
- }
-
- for (Uint32 i = 0; i < aParallelism; i ++) {
- tScanRec = theNdb->getNdbScanRec();
- if (tScanRec == NULL) {
- setErrorCodeAbort(4000);
- return -1;
- }//if
- tScanRec->init(this, lockMode);
- theScanReceiversArray[i] = tScanRec;
- }
-
- theSCAN_TABREQ = theNdb->getSignal();
- if (theSCAN_TABREQ == NULL) {
- setErrorCodeAbort(4000);
- return -1;
- }//if
- ScanTabReq * const scanTabReq = CAST_PTR(ScanTabReq, theSCAN_TABREQ->getDataPtrSend());
- scanTabReq->apiConnectPtr = theNdbCon->theTCConPtr;
- scanTabReq->tableId = m_accessTable->m_tableId;
- scanTabReq->tableSchemaVersion = m_accessTable->m_version;
- scanTabReq->storedProcId = 0xFFFF;
- scanTabReq->buddyConPtr = theNdbCon->theBuddyConPtr;
-
- Uint32 reqInfo = 0;
- ScanTabReq::setParallelism(reqInfo, aParallelism);
- ScanTabReq::setLockMode(reqInfo, lockMode);
- ScanTabReq::setHoldLockFlag(reqInfo, lockHoldMode);
- ScanTabReq::setReadCommittedFlag(reqInfo, readCommitted);
- if (theOperationType == OpenRangeScanRequest)
- ScanTabReq::setRangeScanFlag(reqInfo, true);
- scanTabReq->requestInfo = reqInfo;
-
- Uint64 transId = theNdbCon->getTransactionId();
- scanTabReq->transId1 = (Uint32) transId;
- scanTabReq->transId2 = (Uint32) (transId >> 32);
-
- for (Uint32 i = 0; i < 16 && i < aParallelism ; i++) {
- scanTabReq->apiOperationPtr[i] = theScanReceiversArray[i]->ptr2int();
- }//for
-
- // Create one additional SCAN_TABINFO for each
- // 16 of parallelism
- NdbApiSignal* tSignal;
- Uint32 tParallelism = aParallelism;
- while (tParallelism > 16) {
- tSignal = theNdb->getSignal();
- if (tSignal == NULL) {
- setErrorCodeAbort(4000);
- return -1;
- }//if
- if (tSignal->setSignal(GSN_SCAN_TABINFO) == -1) {
- setErrorCode(4001);
- return -1;
- }
- tSignal->next(theFirstSCAN_TABINFO_Send);
- theFirstSCAN_TABINFO_Send = tSignal;
- tParallelism -= 16;
- }//while
-
- // Format all SCAN_TABINFO signals
- tParallelism = 16;
- tSignal = theFirstSCAN_TABINFO_Send;
- while (tSignal != NULL) {
- tSignal->setData(theNdbCon->theTCConPtr, 1);
- for (int i = 0; i < 16 ; i++) {
- tSignal->setData(theScanReceiversArray[i + tParallelism]->ptr2int(), i + 2);
- }//for
- tSignal = tSignal->next();
- tParallelism += 16;
- }//while
-
- getFirstATTRINFOScan();
- return 0;
-}//NdbScanOperation::openScan()
-
-/*****************************************************************************
- * int getFirstATTRINFOScan( U_int32 aData )
- *
- * Return Value: Return 0: Successful
- * Return -1: All other cases
- * Parameters: None: Only allocate the first signal.
- * Remark: When a scan is defined we need to use this method instead
- * of insertATTRINFO for the first signal.
- * This is because we need not to mess up the code in
- * insertATTRINFO with if statements since we are not
- * interested in the TCKEYREQ signal.
- *****************************************************************************/
-int
-NdbOperation::getFirstATTRINFOScan()
-{
- NdbApiSignal* tSignal;
-
- tSignal = theNdb->getSignal();
- if (tSignal == NULL){
- setErrorCodeAbort(4000);
- return -1;
- }
- tSignal->setSignal(m_attrInfoGSN);
- theAI_LenInCurrAI = 8;
- theATTRINFOptr = &tSignal->getDataPtrSend()[8];
- theFirstATTRINFO = tSignal;
- theCurrentATTRINFO = tSignal;
- theCurrentATTRINFO->next(NULL);
- return 0;
-}
-
-/*
- * After setBound() are done, move the accumulated ATTRINFO signals to
- * a separate list. Then continue with normal scan.
- */
-int
-NdbOperation::saveBoundATTRINFO()
-{
- theCurrentATTRINFO->setLength(theAI_LenInCurrAI);
- theBoundATTRINFO = theFirstATTRINFO;
- theTotalBoundAI_Len = theTotalCurrAI_Len;
- theTotalCurrAI_Len = 5;
- theBoundATTRINFO->setData(theTotalBoundAI_Len, 4);
- theBoundATTRINFO->setData(0, 5);
- theBoundATTRINFO->setData(0, 6);
- theBoundATTRINFO->setData(0, 7);
- theBoundATTRINFO->setData(0, 8);
- theStatus = GetValue;
- return getFirstATTRINFOScan();
-}
-
-/*****************************************************************************
- * void releaseScan()
- *
- * Return Value No return value.
- * Parameters: No parameters.
- * Remark: Release objects after scanning.
- *****************************************************************************/
-void
-NdbOperation::releaseScan()
-{
- NdbScanReceiver* tScanRec;
- TransporterFacade::instance()->lock_mutex();
- for (Uint32 i = 0; i < theParallelism && theScanReceiversArray != NULL; i++) {
- tScanRec = theScanReceiversArray[i];
- if (tScanRec != NULL) {
- tScanRec->release();
- tScanRec->next(NULL);
- }
- }
- TransporterFacade::instance()->unlock_mutex();
- releaseSignals();
-
- if (theScanReceiversArray != NULL) {
- for (Uint32 i = 0; i < theParallelism; i++) {
- NdbScanReceiver* tScanRec;
- tScanRec = theScanReceiversArray[i];
- if (tScanRec != NULL) {
- theNdb->releaseNdbScanRec(tScanRec);
- theScanReceiversArray[i] = NULL;
- }
- }
-
- delete [] theScanReceiversArray;
- }//if
- theScanReceiversArray = NULL;
-
- if (theSCAN_TABREQ != NULL){
- theNdb->releaseSignal(theSCAN_TABREQ);
- theSCAN_TABREQ = NULL;
- }
-}
-
-void NdbOperation::releaseSignals(){
- theNdb->releaseSignalsInList(&theFirstSCAN_TABINFO_Send);
- theFirstSCAN_TABINFO_Send = NULL;
- theLastSCAN_TABINFO_Send = NULL;
- // theNdb->releaseSignalsInList(&theFirstSCAN_TABINFO_Recv);
-
- while(theFirstSCAN_TABINFO_Recv != NULL){
- NdbApiSignal* tmp = theFirstSCAN_TABINFO_Recv;
- theFirstSCAN_TABINFO_Recv = tmp->next();
- delete tmp;
- }
- theFirstSCAN_TABINFO_Recv = NULL;
- theLastSCAN_TABINFO_Recv = NULL;
- if (theSCAN_TABCONF_Recv != NULL){
- // theNdb->releaseSignal(theSCAN_TABCONF_Recv);
- delete theSCAN_TABCONF_Recv;
- theSCAN_TABCONF_Recv = NULL;
- }
-}
-
-
-void NdbOperation::prepareNextScanResult(){
- NdbScanReceiver* tScanRec;
- for (Uint32 i = 0; i < theParallelism; i++) {
- tScanRec = theScanReceiversArray[i];
- assert(tScanRec != NULL);
- tScanRec->prepareNextScanResult();
- tScanRec->next(NULL);
- }
- releaseSignals();
-}
-
-/******************************************************************************
- * void initScan();
- *
- * Return Value: Return 0 : init was successful.
- * Return -1: In all other case.
- * Remark: Initiates operation record after allocation.
- *****************************************************************************/
-void
-NdbOperation::initScan()
-{
- theTotalRecAI_Len = 0;
- theCurrRecAI_Len = 0;
- theStatus = GetValue;
- theOperationType = OpenScanRequest;
- theCurrentRecAttr = theFirstRecAttr;
- theScanInfo = 0;
- theMagicNumber = 0xABCDEF01;
- theTotalCurrAI_Len = 5;
-
- theFirstLabel = NULL;
- theLastLabel = NULL;
- theFirstBranch = NULL;
- theLastBranch = NULL;
-
- theFirstCall = NULL;
- theLastCall = NULL;
- theFirstSubroutine = NULL;
- theLastSubroutine = NULL;
-
- theNoOfLabels = 0;
- theNoOfSubroutines = 0;
-
- theSubroutineSize = 0;
- theInitialReadSize = 0;
- theInterpretedSize = 0;
- theFinalUpdateSize = 0;
- theFinalReadSize = 0;
- theInterpretIndicator = 1;
-
-
- theFirstSCAN_TABINFO_Send = NULL;
- theLastSCAN_TABINFO_Send = NULL;
- theFirstSCAN_TABINFO_Recv = NULL;
- theLastSCAN_TABINFO_Recv = NULL;
- theSCAN_TABCONF_Recv = NULL;
-
- theScanReceiversArray = NULL;
-
- theTotalBoundAI_Len = 0;
- theBoundATTRINFO = NULL;
- return;
-}
-
-NdbOperation* NdbOperation::takeOverForDelete(NdbConnection* updateTrans){
- return takeOverScanOp(DeleteRequest, updateTrans);
-}
-
-NdbOperation* NdbOperation::takeOverForUpdate(NdbConnection* updateTrans){
- return takeOverScanOp(UpdateRequest, updateTrans);
-}
-/******************************************************************************
- * NdbOperation* takeOverScanOp(NdbConnection* updateTrans);
- *
- * Parameters: The update transactions NdbConnection pointer.
- * Return Value: A reference to the transferred operation object
- * or NULL if no success.
- * Remark: Take over the scanning transactions NdbOperation
- * object for a tuple to an update transaction,
- * which is the last operation read in nextScanResult()
- * (theNdbCon->thePreviousScanRec)
- *
- * FUTURE IMPLEMENTATION: (This note was moved from header file.)
- * In the future, it will even be possible to transfer
- * to a NdbConnection on another Ndb-object.
- * In this case the receiving NdbConnection-object must call
- * a method receiveOpFromScan to actually receive the information.
- * This means that the updating transactions can be placed
- * in separate threads and thus increasing the parallelism during
- * the scan process.
- *****************************************************************************/
-NdbOperation*
-NdbOperation::takeOverScanOp(OperationType opType, NdbConnection* updateTrans)
-{
- if (opType != UpdateRequest && opType != DeleteRequest) {
- setErrorCode(4604);
- return NULL;
- }
-
- const NdbScanReceiver* tScanRec = theNdbCon->thePreviousScanRec;
- if (tScanRec == NULL){
- // No operation read by nextScanResult
- setErrorCode(4609);
- return NULL;
- }
-
- if (tScanRec->theFirstKEYINFO20_Recv == NULL){
- // No KEYINFO20 received
- setErrorCode(4608);
- return NULL;
- }
-
- NdbOperation * newOp = updateTrans->getNdbOperation(m_currentTable);
- if (newOp == NULL){
- return NULL;
- }
-
- /**
- * Copy and caclulate attributes from the scanned operation to the
- * new operation
- */
- const KeyInfo20 * const firstKeyInfo20 =
- CAST_CONSTPTR(KeyInfo20, tScanRec->theFirstKEYINFO20_Recv->getDataPtr());
- const Uint32 totalKeyLen = firstKeyInfo20->keyLen;
- newOp->theTupKeyLen = totalKeyLen;
-
- newOp->theOperationType = opType;
- if (opType == DeleteRequest) {
- newOp->theStatus = GetValue;
- } else {
- newOp->theStatus = SetValue;
- }
- const Uint32 tScanInfo = firstKeyInfo20->scanInfo_Node & 0xFFFF;
- const Uint32 tTakeOverNode = firstKeyInfo20->scanInfo_Node >> 16;
- {
- UintR scanInfo = 0;
- TcKeyReq::setTakeOverScanFlag(scanInfo, 1);
- TcKeyReq::setTakeOverScanNode(scanInfo, tTakeOverNode);
- TcKeyReq::setTakeOverScanInfo(scanInfo, tScanInfo);
- newOp->theScanInfo = scanInfo;
- }
-
- /**
- * Copy received KEYINFO20 signals into TCKEYREQ and KEYINFO signals
- * put them in list of the new op
- */
- TcKeyReq * const tcKeyReq =
- CAST_PTR(TcKeyReq, newOp->theTCREQ->getDataPtrSend());
-
- // Copy the first 8 words of key info from KEYINF20 into TCKEYREQ
- for (Uint32 i = 0; i < TcKeyReq::MaxKeyInfo; i++) {
- tcKeyReq->keyInfo[i] = firstKeyInfo20->keyData[i];
- }
- if (totalKeyLen > TcKeyReq::MaxKeyInfo) {
-
- Uint32 keyWordsCopied = TcKeyReq::MaxKeyInfo;
-
- // Create KEYINFO signals in newOp
- for (Uint32 i = keyWordsCopied; i < totalKeyLen; i += KeyInfo::DataLength){
- NdbApiSignal* tSignal = theNdb->getSignal();
- if (tSignal == NULL){
- setErrorCodeAbort(4000);
- return NULL;
- }
- if (tSignal->setSignal(GSN_KEYINFO) == -1){
- setErrorCodeAbort(4001);
- return NULL;
- }
- tSignal->next(newOp->theFirstKEYINFO);
- newOp->theFirstKEYINFO = tSignal;
- }
-
- // Init pointers to KEYINFO20 signal
- NdbApiSignal* currKeyInfo20 = tScanRec->theFirstKEYINFO20_Recv;
- const KeyInfo20 * keyInfo20 =
- CAST_CONSTPTR(KeyInfo20, currKeyInfo20->getDataPtr());
- Uint32 posInKeyInfo20 = keyWordsCopied;
-
- // Init pointers to KEYINFO signal
- NdbApiSignal* currKeyInfo = newOp->theFirstKEYINFO;
- KeyInfo * keyInfo = CAST_PTR(KeyInfo, currKeyInfo->getDataPtrSend());
- Uint32 posInKeyInfo = 0;
-
- // Copy from KEYINFO20 to KEYINFO
- while(keyWordsCopied < totalKeyLen){
- keyInfo->keyData[posInKeyInfo++] = keyInfo20->keyData[posInKeyInfo20++];
- keyWordsCopied++;
- if(keyWordsCopied >= totalKeyLen)
- break;
- if (posInKeyInfo20 >=
- (currKeyInfo20->getLength()-KeyInfo20::HeaderLength)){
- currKeyInfo20 = currKeyInfo20->next();
- keyInfo20 = CAST_CONSTPTR(KeyInfo20, currKeyInfo20->getDataPtr());
- posInKeyInfo20 = 0;
- }
- if (posInKeyInfo >= KeyInfo::DataLength){
- currKeyInfo = currKeyInfo->next();
- keyInfo = CAST_PTR(KeyInfo, currKeyInfo->getDataPtrSend());
- posInKeyInfo = 0;
- }
- }
- }
-
- // create blob handles automatically
- if (opType == DeleteRequest && m_currentTable->m_noOfBlobs != 0) {
- for (unsigned i = 0; i < m_currentTable->m_columns.size(); i++) {
- NdbColumnImpl* c = m_currentTable->m_columns[i];
- assert(c != 0);
- if (c->getBlobType()) {
- if (newOp->getBlobHandle(updateTrans, c) == NULL)
- return NULL;
- }
- }
- }
-
- return newOp;
-}
-
-int
-NdbOperation::getKeyFromKEYINFO20(Uint32* data, unsigned size)
-{
- const NdbScanReceiver* tScanRec = theNdbCon->thePreviousScanRec;
- NdbApiSignal* tSignal = tScanRec->theFirstKEYINFO20_Recv;
- unsigned pos = 0;
- unsigned n = 0;
- while (pos < size) {
- if (n == 20) {
- tSignal = tSignal->next();
- n = 0;
- }
- const unsigned h = KeyInfo20::HeaderLength;
- data[pos++] = tSignal->getDataPtrSend()[h + n++];
- }
- return 0;
-}
diff --git a/ndb/src/ndbapi/NdbRecAttr.cpp b/ndb/src/ndbapi/NdbRecAttr.cpp
index 0ed2ff4e796..2e753f13006 100644
--- a/ndb/src/ndbapi/NdbRecAttr.cpp
+++ b/ndb/src/ndbapi/NdbRecAttr.cpp
@@ -29,6 +29,7 @@ Adjust: 971206 UABRONM First version
#include <ndb_global.h>
#include <NdbOut.hpp>
#include <NdbRecAttr.hpp>
+#include <NdbBlob.hpp>
#include "NdbDictionaryImpl.hpp"
#include <NdbTCP.h>
@@ -60,6 +61,8 @@ NdbRecAttr::setup(const NdbColumnImpl* anAttrInfo, char* aValue)
theAttrSize = tAttrSize;
theArraySize = tArraySize;
theValue = aValue;
+ theNULLind = 0;
+ m_nullable = anAttrInfo->m_nullable;
// check alignment to signal data
// a future version could check alignment per data type as well
@@ -128,78 +131,117 @@ NdbRecAttr::clone() const {
return ret;
}
-NdbOut& operator<<(NdbOut& ndbout, const NdbRecAttr &r)
+bool
+NdbRecAttr::receive_data(const Uint32 * data, Uint32 sz){
+ const Uint32 n = (theAttrSize * theArraySize + 3) >> 2;
+ if(n == sz){
+ theNULLind = 0;
+ if(!copyoutRequired())
+ memcpy(theRef, data, 4 * sz);
+ else
+ memcpy(theValue, data, theAttrSize * theArraySize);
+ return true;
+ } else if(sz == 0){
+ setNULL();
+ return true;
+ }
+ return false;
+}
+
+NdbOut& operator<<(NdbOut& out, const NdbRecAttr &r)
{
if (r.isNULL())
{
- ndbout << "[NULL]";
- return ndbout;
+ out << "[NULL]";
+ return out;
}
if (r.arraySize() > 1)
- ndbout << "[";
+ out << "[";
for (Uint32 j = 0; j < r.arraySize(); j++)
{
if (j > 0)
- ndbout << " ";
+ out << " ";
switch(r.getType())
{
case NdbDictionary::Column::Bigunsigned:
- ndbout << r.u_64_value();
+ out << r.u_64_value();
break;
case NdbDictionary::Column::Unsigned:
- ndbout << r.u_32_value();
+ out << r.u_32_value();
break;
case NdbDictionary::Column::Smallunsigned:
- ndbout << r.u_short_value();
+ out << r.u_short_value();
break;
case NdbDictionary::Column::Tinyunsigned:
- ndbout << (unsigned) r.u_char_value();
+ out << (unsigned) r.u_char_value();
break;
case NdbDictionary::Column::Bigint:
- ndbout << r.int64_value();
+ out << r.int64_value();
break;
case NdbDictionary::Column::Int:
- ndbout << r.int32_value();
+ out << r.int32_value();
break;
case NdbDictionary::Column::Smallint:
- ndbout << r.short_value();
+ out << r.short_value();
break;
case NdbDictionary::Column::Tinyint:
- ndbout << (int) r.char_value();
+ out << (int) r.char_value();
break;
case NdbDictionary::Column::Char:
- ndbout.print("%.*s", r.arraySize(), r.aRef());
+ out.print("%.*s", r.arraySize(), r.aRef());
j = r.arraySize();
break;
case NdbDictionary::Column::Varchar:
{
short len = ntohs(r.u_short_value());
- ndbout.print("%.*s", len, r.aRef()+2);
+ out.print("%.*s", len, r.aRef()+2);
}
j = r.arraySize();
break;
case NdbDictionary::Column::Float:
- ndbout << r.float_value();
+ out << r.float_value();
break;
case NdbDictionary::Column::Double:
- ndbout << r.double_value();
+ out << r.double_value();
break;
+ case NdbDictionary::Column::Blob:
+ {
+ const NdbBlob::Head* h = (const NdbBlob::Head*)r.aRef();
+ out << h->length << ":";
+ const unsigned char* p = (const unsigned char*)(h + 1);
+ unsigned n = r.arraySize() - sizeof(*h);
+ for (unsigned k = 0; k < n && k < h->length; k++)
+ out.print("%02X", (int)p[k]);
+ j = r.arraySize();
+ }
+ break;
+ case NdbDictionary::Column::Text:
+ {
+ const NdbBlob::Head* h = (const NdbBlob::Head*)r.aRef();
+ out << h->length << ":";
+ const unsigned char* p = (const unsigned char*)(h + 1);
+ unsigned n = r.arraySize() - sizeof(*h);
+ for (unsigned k = 0; k < n && k < h->length; k++)
+ out.print("%c", (int)p[k]);
+ j = r.arraySize();
+ }
+ break;
default: /* no print functions for the rest, just print type */
- ndbout << r.getType();
+ out << r.getType();
j = r.arraySize();
if (j > 1)
- ndbout << " %u times" << j;
+ out << " " << j << " times";
break;
}
}
if (r.arraySize() > 1)
{
- ndbout << "]";
+ out << "]";
}
- return ndbout;
+ return out;
}
diff --git a/ndb/src/ndbapi/NdbReceiver.cpp b/ndb/src/ndbapi/NdbReceiver.cpp
index 4c461698a4a..bdb5e6c7e78 100644
--- a/ndb/src/ndbapi/NdbReceiver.cpp
+++ b/ndb/src/ndbapi/NdbReceiver.cpp
@@ -16,6 +16,10 @@
#include "NdbImpl.hpp"
#include <NdbReceiver.hpp>
+#include "NdbDictionaryImpl.hpp"
+#include <NdbRecAttr.hpp>
+#include <AttributeHeader.hpp>
+#include <NdbConnection.hpp>
NdbReceiver::NdbReceiver(Ndb *aNdb) :
theMagicNumber(0),
@@ -24,8 +28,19 @@ NdbReceiver::NdbReceiver(Ndb *aNdb) :
m_type(NDB_UNINITIALIZED),
m_owner(0)
{
+ theCurrentRecAttr = theFirstRecAttr = 0;
+ m_defined_rows = 0;
+ m_rows = new NdbRecAttr*[0];
}
+NdbReceiver::~NdbReceiver()
+{
+ if (m_id != NdbObjectIdMap::InvalidId) {
+ m_ndb->theNdbObjectIdMap->unmap(m_id, this);
+ }
+ delete[] m_rows;
+}
+
void
NdbReceiver::init(ReceiverType type, void* owner)
{
@@ -36,11 +51,175 @@ NdbReceiver::init(ReceiverType type, void* owner)
if (m_ndb)
m_id = m_ndb->theNdbObjectIdMap->map(this);
}
+
+ theFirstRecAttr = NULL;
+ theCurrentRecAttr = NULL;
+}
+
+void
+NdbReceiver::release(){
+ NdbRecAttr* tRecAttr = theFirstRecAttr;
+ while (tRecAttr != NULL)
+ {
+ NdbRecAttr* tSaveRecAttr = tRecAttr;
+ tRecAttr = tRecAttr->next();
+ m_ndb->releaseRecAttr(tSaveRecAttr);
+ }
+ theFirstRecAttr = NULL;
+ theCurrentRecAttr = NULL;
}
-NdbReceiver::~NdbReceiver()
+NdbRecAttr *
+NdbReceiver::getValue(const NdbColumnImpl* tAttrInfo, char * user_dst_ptr){
+ NdbRecAttr* tRecAttr = m_ndb->getRecAttr();
+ if(tRecAttr && !tRecAttr->setup(tAttrInfo, user_dst_ptr)){
+ if (theFirstRecAttr == NULL)
+ theFirstRecAttr = tRecAttr;
+ else
+ theCurrentRecAttr->next(tRecAttr);
+ theCurrentRecAttr = tRecAttr;
+ tRecAttr->next(NULL);
+ return tRecAttr;
+ }
+ if(tRecAttr){
+ m_ndb->releaseRecAttr(tRecAttr);
+ }
+ return 0;
+}
+
+#define KEY_ATTR_ID (~0)
+
+void
+NdbReceiver::do_get_value(NdbReceiver * org, Uint32 rows, Uint32 key_size){
+ if(rows > m_defined_rows){
+ delete[] m_rows;
+ m_defined_rows = rows;
+ m_rows = new NdbRecAttr*[rows + 1];
+ }
+ m_rows[rows] = 0;
+
+ NdbColumnImpl key;
+ if(key_size){
+ key.m_attrId = KEY_ATTR_ID;
+ key.m_arraySize = key_size+1;
+ key.m_attrSize = 4;
+ key.m_nullable = true; // So that receive works w.r.t KEYINFO20
+ }
+ m_key_info = key_size;
+
+ for(Uint32 i = 0; i<rows; i++){
+ NdbRecAttr * prev = theCurrentRecAttr;
+ assert(prev == 0 || i > 0);
+
+ // Put key-recAttr fir on each row
+ if(key_size && !getValue(&key, (char*)0)){
+ abort();
+ return ; // -1
+ }
+
+ NdbRecAttr* tRecAttr = org->theFirstRecAttr;
+ while(tRecAttr != 0){
+ if(getValue(&NdbColumnImpl::getImpl(*tRecAttr->m_column), (char*)0) != 0)
+ tRecAttr = tRecAttr->next();
+ else
+ break;
+ }
+
+ if(tRecAttr){
+ abort();
+ return ;// -1;
+ }
+
+ // Store first recAttr for each row in m_rows[i]
+ if(prev){
+ m_rows[i] = prev->next();
+ } else {
+ m_rows[i] = theFirstRecAttr;
+ }
+ }
+
+ prepareSend();
+ return ; //0;
+}
+
+void
+NdbReceiver::copyout(NdbReceiver & dstRec){
+ NdbRecAttr* src = m_rows[m_current_row++];
+ NdbRecAttr* dst = dstRec.theFirstRecAttr;
+ Uint32 tmp = m_key_info;
+ if(tmp > 0){
+ src = src->next();
+ }
+
+ while(dst){
+ Uint32 len = ((src->theAttrSize * src->theArraySize)+3)/4;
+ dst->receive_data((Uint32*)src->aRef(), src->isNULL() ? 0 : len);
+ src = src->next();
+ dst = dst->next();
+ }
+}
+
+int
+NdbReceiver::execTRANSID_AI(const Uint32* aDataPtr, Uint32 aLength)
{
- if (m_id != NdbObjectIdMap::InvalidId) {
- m_ndb->theNdbObjectIdMap->unmap(m_id, this);
+ bool ok = true;
+ NdbRecAttr* currRecAttr = theCurrentRecAttr;
+
+ for (Uint32 used = 0; used < aLength ; used++){
+ AttributeHeader ah(* aDataPtr++);
+ const Uint32 tAttrId = ah.getAttributeId();
+ const Uint32 tAttrSize = ah.getDataSize();
+
+ /**
+ * Set all results to NULL if not found...
+ */
+ while(currRecAttr && currRecAttr->attrId() != tAttrId){
+ ok &= currRecAttr->setNULL();
+ currRecAttr = currRecAttr->next();
+ }
+
+ if(ok && currRecAttr && currRecAttr->receive_data(aDataPtr, tAttrSize)){
+ used += tAttrSize;
+ aDataPtr += tAttrSize;
+ currRecAttr = currRecAttr->next();
+ } else {
+ ndbout_c("%p: ok: %d tAttrId: %d currRecAttr: %p",
+ this,ok, tAttrId, currRecAttr);
+ currRecAttr = theCurrentRecAttr;
+ while(currRecAttr != 0){
+ ndbout_c("%d ", currRecAttr->attrId());
+ currRecAttr = currRecAttr->next();
+ }
+ abort();
+ return -1;
+ }
}
+
+ theCurrentRecAttr = currRecAttr;
+
+ /**
+ * Update m_received_result_length
+ */
+ Uint32 tmp = m_received_result_length + aLength;
+ m_received_result_length = tmp;
+
+ return (tmp == m_expected_result_length ? 1 : 0);
+}
+
+int
+NdbReceiver::execKEYINFO20(Uint32 info, const Uint32* aDataPtr, Uint32 aLength)
+{
+ NdbRecAttr* currRecAttr = m_rows[m_current_row++];
+ assert(currRecAttr->attrId() == KEY_ATTR_ID);
+ currRecAttr->receive_data(aDataPtr, aLength + 1);
+
+ /**
+ * Save scanInfo in the end of keyinfo
+ */
+ ((Uint32*)currRecAttr->aRef())[aLength] = info;
+
+ Uint32 tmp = m_received_result_length + aLength;
+ m_received_result_length = tmp;
+
+ return (tmp == m_expected_result_length ? 1 : 0);
}
diff --git a/ndb/src/ndbapi/NdbResultSet.cpp b/ndb/src/ndbapi/NdbResultSet.cpp
index 65ed43f60d8..f270584d227 100644
--- a/ndb/src/ndbapi/NdbResultSet.cpp
+++ b/ndb/src/ndbapi/NdbResultSet.cpp
@@ -29,8 +29,9 @@
#include <Ndb.hpp>
#include <NdbConnection.hpp>
#include <NdbResultSet.hpp>
+#include <NdbBlob.hpp>
-NdbResultSet::NdbResultSet(NdbCursorOperation *owner)
+NdbResultSet::NdbResultSet(NdbScanOperation *owner)
: m_operation(owner)
{
}
@@ -45,7 +46,25 @@ void NdbResultSet::init()
int NdbResultSet::nextResult(bool fetchAllowed)
{
- return m_operation->nextResult(fetchAllowed);
+ int res;
+ if ((res = m_operation->nextResult(fetchAllowed)) == 0) {
+ // handle blobs
+ NdbBlob* tBlob = m_operation->theBlobList;
+ while (tBlob != 0) {
+ if (tBlob->atNextResult() == -1)
+ return -1;
+ tBlob = tBlob->theNext;
+ }
+ /*
+ * Flush blob part ops on behalf of user because
+ * - nextResult is analogous to execute(NoCommit)
+ * - user is likely to want blob value before next execute
+ */
+ if (m_operation->m_transConnection->executePendingBlobOps() == -1)
+ return -1;
+ return 0;
+ }
+ return res;
}
void NdbResultSet::close()
@@ -55,52 +74,30 @@ void NdbResultSet::close()
NdbOperation*
NdbResultSet::updateTuple(){
- if(m_operation->cursorType() != NdbCursorOperation::ScanCursor){
- m_operation->setErrorCode(4003);
- return 0;
- }
-
- NdbScanOperation * op = (NdbScanOperation*)(m_operation);
- return op->takeOverScanOp(NdbOperation::UpdateRequest,
- op->m_transConnection);
+ return updateTuple(m_operation->m_transConnection);
}
NdbOperation*
NdbResultSet::updateTuple(NdbConnection* takeOverTrans){
- if(m_operation->cursorType() != NdbCursorOperation::ScanCursor){
- m_operation->setErrorCode(4003);
- return 0;
- }
-
return m_operation->takeOverScanOp(NdbOperation::UpdateRequest,
takeOverTrans);
}
int
NdbResultSet::deleteTuple(){
- if(m_operation->cursorType() != NdbCursorOperation::ScanCursor){
- m_operation->setErrorCode(4003);
- return 0;
- }
-
- NdbScanOperation * op = (NdbScanOperation*)(m_operation);
- void * res = op->takeOverScanOp(NdbOperation::DeleteRequest,
- op->m_transConnection);
- if(res == 0)
- return -1;
- return 0;
+ return deleteTuple(m_operation->m_transConnection);
}
int
NdbResultSet::deleteTuple(NdbConnection * takeOverTrans){
- if(m_operation->cursorType() != NdbCursorOperation::ScanCursor){
- m_operation->setErrorCode(4003);
- return 0;
- }
-
void * res = m_operation->takeOverScanOp(NdbOperation::DeleteRequest,
takeOverTrans);
if(res == 0)
return -1;
return 0;
}
+
+int
+NdbResultSet::restart(){
+ return m_operation->restart();
+}
diff --git a/ndb/src/ndbapi/NdbScanFilter.cpp b/ndb/src/ndbapi/NdbScanFilter.cpp
index 9542b226d7d..3813ab139de 100644
--- a/ndb/src/ndbapi/NdbScanFilter.cpp
+++ b/ndb/src/ndbapi/NdbScanFilter.cpp
@@ -337,7 +337,6 @@ static const tab2 table2[] = {
const int tab_sz = sizeof(table)/sizeof(table[0]);
const int tab2_sz = sizeof(table2)/sizeof(table2[0]);
-template<typename T>
int
matchType(const NdbDictionary::Column * col){
return 1;
@@ -382,7 +381,7 @@ NdbScanFilterImpl::cond_col_const(Interpreter::BinaryCondition op,
return -1;
}
- if(!matchType<T>(col)){
+ if(!matchType(col)){
/**
* Code not reached
*/
@@ -777,3 +776,10 @@ main(void){
return 0;
}
#endif
+
+template class Vector<NdbScanFilterImpl::State>;
+#if __SUNPRO_CC != 0x560
+template int NdbScanFilterImpl::cond_col_const(Interpreter::BinaryCondition, Uint32 attrId, Uint32);
+template int NdbScanFilterImpl::cond_col_const(Interpreter::BinaryCondition, Uint32 attrId, Uint64);
+#endif
+
diff --git a/ndb/src/ndbapi/NdbScanOperation.cpp b/ndb/src/ndbapi/NdbScanOperation.cpp
index cc090ac0364..0aa40f968bb 100644
--- a/ndb/src/ndbapi/NdbScanOperation.cpp
+++ b/ndb/src/ndbapi/NdbScanOperation.cpp
@@ -14,49 +14,62 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-/*****************************************************************************
- * Name: NdbScanOperation.cpp
- * Include:
- * Link:
- * Author: UABMASD Martin Sköld INN/V Alzato
- * Date: 2002-04-01
- * Version: 0.1
- * Description: Table scan support
- * Documentation:
- * Adjust: 2002-04-01 UABMASD First version.
- ****************************************************************************/
-
#include <ndb_global.h>
#include <Ndb.hpp>
#include <NdbScanOperation.hpp>
+#include <NdbIndexScanOperation.hpp>
#include <NdbConnection.hpp>
#include <NdbResultSet.hpp>
#include "NdbApiSignal.hpp"
#include <NdbOut.hpp>
#include "NdbDictionaryImpl.hpp"
-#include "NdbBlob.hpp"
+
+#include <NdbRecAttr.hpp>
+#include <NdbReceiver.hpp>
+
+#include <stdlib.h>
+#include <NdbSqlUtil.hpp>
+
+#include <signaldata/ScanTab.hpp>
+#include <signaldata/KeyInfo.hpp>
+#include <signaldata/TcKeyReq.hpp>
NdbScanOperation::NdbScanOperation(Ndb* aNdb) :
- NdbCursorOperation(aNdb),
- m_transConnection(NULL),
- m_autoExecute(false),
- m_updateOp(false),
- m_deleteOp(false),
- m_setValueList(new SetValueRecList())
+ NdbOperation(aNdb),
+ m_resultSet(0),
+ m_transConnection(NULL)
{
+ theParallelism = 0;
+ m_allocated_receivers = 0;
+ m_prepared_receivers = 0;
+ m_api_receivers = 0;
+ m_conf_receivers = 0;
+ m_sent_receivers = 0;
+ m_receivers = 0;
+ m_array = new Uint32[1]; // skip if on delete in fix_receivers
}
NdbScanOperation::~NdbScanOperation()
{
- if (m_setValueList) delete m_setValueList;
+ for(Uint32 i = 0; i<m_allocated_receivers; i++){
+ theNdb->releaseNdbScanRec(m_receivers[i]);
+ }
+ delete[] m_array;
+ if (m_resultSet)
+ delete m_resultSet;
}
-NdbCursorOperation::CursorType
-NdbScanOperation::cursorType()
+NdbResultSet*
+NdbScanOperation::getResultSet()
{
- return NdbCursorOperation::ScanCursor;
+ if (!m_resultSet)
+ m_resultSet = new NdbResultSet(this);
+
+ return m_resultSet;
}
+
+
void
NdbScanOperation::setErrorCode(int aErrorCode){
NdbConnection* tmp = theNdbCon;
@@ -91,288 +104,543 @@ NdbScanOperation::init(NdbTableImpl* tab, NdbConnection* myConnection)
setErrorCodeAbort(theNdb->getNdbError().code);
return -1;
}
- aScanConnection->theFirstOpInList = this;
- aScanConnection->theLastOpInList = this;
- NdbCursorOperation::cursInit();
+
// NOTE! The hupped trans becomes the owner of the operation
- return NdbOperation::init(tab, aScanConnection);
+ if(NdbOperation::init(tab, aScanConnection) != 0){
+ return -1;
+ }
+
+ initInterpreter();
+
+ theStatus = GetValue;
+ theOperationType = OpenScanRequest;
+
+ theTotalBoundAI_Len = 0;
+ theBoundATTRINFO = NULL;
+
+ return 0;
}
-NdbResultSet* NdbScanOperation::readTuples(Uint32 parallell,
- NdbCursorOperation::LockMode lm)
+NdbResultSet* NdbScanOperation::readTuples(NdbScanOperation::LockMode lm,
+ Uint32 batch,
+ Uint32 parallel)
{
- int res = 0;
+ m_ordered = 0;
+
+ Uint32 fragCount = m_currentTable->m_fragmentCount;
+
+ if (batch + parallel == 0) {
+ batch = 16;
+ parallel= fragCount;
+ } else {
+ if (batch == 0 && parallel > 0) { // Backward
+ batch = (parallel >= 16 ? 16 : parallel);
+ parallel = (parallel + 15) / 16;
+ }
+ if (parallel > fragCount || parallel == 0)
+ parallel = fragCount;
+ }
+
+ // It is only possible to call openScan if
+ // 1. this transcation don't already contain another scan operation
+ // 2. this transaction don't already contain other operations
+ // 3. theScanOp contains a NdbScanOperation
+ if (theNdbCon->theScanningOp != NULL){
+ setErrorCode(4605);
+ return 0;
+ }
+
+ theNdbCon->theScanningOp = this;
+
+ bool lockExcl, lockHoldMode, readCommitted;
switch(lm){
- case NdbCursorOperation::LM_Read:
- parallell = (parallell == 0 ? 240 : parallell);
- res = openScan(parallell, false, true, false);
+ case NdbScanOperation::LM_Read:
+ lockExcl = false;
+ lockHoldMode = true;
+ readCommitted = false;
break;
- case NdbCursorOperation::LM_Exclusive:
- parallell = (parallell == 0 ? 1 : parallell);
- res = openScan(parallell, true, true, false);
+ case NdbScanOperation::LM_Exclusive:
+ lockExcl = true;
+ lockHoldMode = true;
+ readCommitted = false;
break;
- case NdbCursorOperation::LM_Dirty:
- parallell = (parallell == 0 ? 240 : parallell);
- res = openScan(parallell, false, false, true);
+ case NdbScanOperation::LM_CommittedRead:
+ lockExcl = false;
+ lockHoldMode = false;
+ readCommitted = true;
break;
default:
- res = -1;
setErrorCode(4003);
+ return 0;
}
- if(res == -1){
- return NULL;
- }
- theNdbCon->theFirstOpInList = 0;
- theNdbCon->theLastOpInList = 0;
- return getResultSet();
-}
+ m_keyInfo = lockExcl;
-int NdbScanOperation::updateTuples(Uint32 parallelism)
-{
- if (openScanExclusive(parallelism) == -1) {
- return -1;
+ bool range = false;
+ if (m_accessTable->m_indexType == NdbDictionary::Index::OrderedIndex ||
+ m_accessTable->m_indexType == NdbDictionary::Index::UniqueOrderedIndex){
+ if (m_currentTable == m_accessTable){
+ // Old way of scanning indexes, should not be allowed
+ m_currentTable = theNdb->theDictionary->
+ getTable(m_currentTable->m_primaryTable.c_str());
+ assert(m_currentTable != NULL);
+ }
+ assert (m_currentTable != m_accessTable);
+ // Modify operation state
+ theStatus = SetBound;
+ theOperationType = OpenRangeScanRequest;
+ range = true;
}
- theNdbCon->theFirstOpInList = 0;
- theNdbCon->theLastOpInList = 0;
-
- m_updateOp = true;
-
- return 0;
-}
+
+ theParallelism = parallel;
+ theBatchSize = batch;
-int NdbScanOperation::deleteTuples(Uint32 parallelism)
-{
- if (openScanExclusive(parallelism) == -1) {
- return -1;
+ if(fix_receivers(parallel) == -1){
+ setErrorCodeAbort(4000);
+ return 0;
}
- theNdbCon->theFirstOpInList = 0;
- theNdbCon->theLastOpInList = 0;
-
- m_deleteOp = true;
-
- return 0;
-}
-
-int NdbScanOperation::setValue(const char* anAttrName, const char* aValue, Uint32 len)
-{
- // Check if attribute exist
- if (m_currentTable->getColumn(anAttrName) == NULL)
- return -1;
- m_setValueList->add(anAttrName, aValue, len);
- return 0;
-}
-
-int NdbScanOperation::setValue(const char* anAttrName, Int32 aValue)
-{
- // Check if attribute exist
- if (m_currentTable->getColumn(anAttrName) == NULL)
- return -1;
-
- m_setValueList->add(anAttrName, aValue);
- return 0;
-}
-
-int NdbScanOperation::setValue(const char* anAttrName, Uint32 aValue)
-{
- // Check if attribute exist
- if (m_currentTable->getColumn(anAttrName) == NULL)
- return -1;
-
- m_setValueList->add(anAttrName, aValue);
- return 0;
-}
-
-int NdbScanOperation::setValue(const char* anAttrName, Uint64 aValue)
-{
- // Check if attribute exist
- if (m_currentTable->getColumn(anAttrName) == NULL)
- return -1;
-
- m_setValueList->add(anAttrName, aValue);
- return 0;
-}
-
-int NdbScanOperation::setValue(const char* anAttrName, Int64 aValue)
-{
- // Check if attribute exist
- if (m_currentTable->getColumn(anAttrName) == NULL)
- return -1;
-
- m_setValueList->add(anAttrName, aValue);
- return 0;
-}
-
-int NdbScanOperation::setValue(const char* anAttrName, float aValue)
-{
- // Check if attribute exist
- if (m_currentTable->getColumn(anAttrName) == NULL)
- return -1;
+ theSCAN_TABREQ = theNdb->getSignal();
+ if (theSCAN_TABREQ == NULL) {
+ setErrorCodeAbort(4000);
+ return 0;
+ }//if
+
+ ScanTabReq * req = CAST_PTR(ScanTabReq, theSCAN_TABREQ->getDataPtrSend());
+ req->apiConnectPtr = theNdbCon->theTCConPtr;
+ req->tableId = m_accessTable->m_tableId;
+ req->tableSchemaVersion = m_accessTable->m_version;
+ req->storedProcId = 0xFFFF;
+ req->buddyConPtr = theNdbCon->theBuddyConPtr;
+
+ Uint32 reqInfo = 0;
+ ScanTabReq::setParallelism(reqInfo, parallel);
+ ScanTabReq::setScanBatch(reqInfo, batch);
+ ScanTabReq::setLockMode(reqInfo, lockExcl);
+ ScanTabReq::setHoldLockFlag(reqInfo, lockHoldMode);
+ ScanTabReq::setReadCommittedFlag(reqInfo, readCommitted);
+ ScanTabReq::setRangeScanFlag(reqInfo, range);
+ req->requestInfo = reqInfo;
- m_setValueList->add(anAttrName, aValue);
- return 0;
-}
+ Uint64 transId = theNdbCon->getTransactionId();
+ req->transId1 = (Uint32) transId;
+ req->transId2 = (Uint32) (transId >> 32);
-int NdbScanOperation::setValue(const char* anAttrName, double aValue)
-{
- // Check if attribute exist
- if (m_currentTable->getColumn(anAttrName) == NULL)
- return -1;
+ getFirstATTRINFOScan();
- m_setValueList->add(anAttrName, aValue);
- return 0;
+ return getResultSet();
}
-
-int NdbScanOperation::setValue(Uint32 anAttrId, const char* aValue, Uint32 len)
-{
- // Check if attribute exist
- if (m_currentTable->getColumn(anAttrId) == NULL)
- return -1;
-
- m_setValueList->add(anAttrId, aValue, len);
+int
+NdbScanOperation::fix_receivers(Uint32 parallel){
+ assert(parallel > 0);
+ if(parallel > m_allocated_receivers){
+ const Uint32 sz = parallel * (4*sizeof(char*)+sizeof(Uint32));
+
+ Uint32 * tmp = new Uint32[(sz+3)/4];
+ // Save old receivers
+ memcpy(tmp+parallel, m_receivers, m_allocated_receivers*sizeof(char*));
+ delete[] m_array;
+ m_array = tmp;
+
+ m_prepared_receivers = tmp;
+ m_receivers = (NdbReceiver**)(tmp + parallel);
+ m_api_receivers = m_receivers + parallel;
+ m_conf_receivers = m_api_receivers + parallel;
+ m_sent_receivers = m_conf_receivers + parallel;
+
+ // Only get/init "new" receivers
+ NdbReceiver* tScanRec;
+ for (Uint32 i = m_allocated_receivers; i < parallel; i ++) {
+ tScanRec = theNdb->getNdbScanRec();
+ if (tScanRec == NULL) {
+ setErrorCodeAbort(4000);
+ return -1;
+ }//if
+ m_receivers[i] = tScanRec;
+ tScanRec->init(NdbReceiver::NDB_SCANRECEIVER, this);
+ }
+ 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;
return 0;
}
-int NdbScanOperation::setValue(Uint32 anAttrId, Int32 aValue)
-{
- // Check if attribute exist
- if (m_currentTable->getColumn(anAttrId) == NULL)
- return -1;
-
- m_setValueList->add(anAttrId, aValue);
- return 0;
+/**
+ * Move receiver from send array to conf:ed array
+ */
+void
+NdbScanOperation::receiver_delivered(NdbReceiver* tRec){
+ if(theError.code == 0){
+ Uint32 idx = tRec->m_list_index;
+ Uint32 last = m_sent_receivers_count - 1;
+ if(idx != last){
+ NdbReceiver * move = m_sent_receivers[last];
+ m_sent_receivers[idx] = move;
+ move->m_list_index = idx;
+ }
+ m_sent_receivers_count = last;
+
+ last = m_conf_receivers_count;
+ m_conf_receivers[last] = tRec;
+ m_conf_receivers_count = last + 1;
+ tRec->m_list_index = last;
+ tRec->m_current_row = 0;
+ }
}
-int NdbScanOperation::setValue(Uint32 anAttrId, Uint32 aValue)
-{
- // Check if attribute exist
- if (m_currentTable->getColumn(anAttrId) == NULL)
- return -1;
-
- m_setValueList->add(anAttrId, aValue);
- return 0;
+/**
+ * Remove receiver as it's completed
+ */
+void
+NdbScanOperation::receiver_completed(NdbReceiver* tRec){
+ if(theError.code == 0){
+ Uint32 idx = tRec->m_list_index;
+ Uint32 last = m_sent_receivers_count - 1;
+ if(idx != last){
+ NdbReceiver * move = m_sent_receivers[last];
+ m_sent_receivers[idx] = move;
+ move->m_list_index = idx;
+ }
+ m_sent_receivers_count = last;
+ }
}
-int NdbScanOperation::setValue(Uint32 anAttrId, Uint64 aValue)
+/*****************************************************************************
+ * int getFirstATTRINFOScan( U_int32 aData )
+ *
+ * Return Value: Return 0: Successful
+ * Return -1: All other cases
+ * Parameters: None: Only allocate the first signal.
+ * Remark: When a scan is defined we need to use this method instead
+ * of insertATTRINFO for the first signal.
+ * This is because we need not to mess up the code in
+ * insertATTRINFO with if statements since we are not
+ * interested in the TCKEYREQ signal.
+ *****************************************************************************/
+int
+NdbScanOperation::getFirstATTRINFOScan()
{
- // Check if attribute exist
- if (m_currentTable->getColumn(anAttrId) == NULL)
- return -1;
-
- m_setValueList->add(anAttrId, aValue);
- return 0;
-}
+ NdbApiSignal* tSignal;
-int NdbScanOperation::setValue(Uint32 anAttrId, Int64 aValue)
-{
- // Check if attribute exist
- if (m_currentTable->getColumn(anAttrId) == NULL)
- return -1;
+ tSignal = theNdb->getSignal();
+ if (tSignal == NULL){
+ setErrorCodeAbort(4000);
+ return -1;
+ }
+ tSignal->setSignal(m_attrInfoGSN);
+ theAI_LenInCurrAI = 8;
+ theATTRINFOptr = &tSignal->getDataPtrSend()[8];
+ theFirstATTRINFO = tSignal;
+ theCurrentATTRINFO = tSignal;
+ theCurrentATTRINFO->next(NULL);
- m_setValueList->add(anAttrId, aValue);
return 0;
}
-int NdbScanOperation::setValue(Uint32 anAttrId, float aValue)
-{
- // Check if attribute exist
- if (m_currentTable->getColumn(anAttrId) == NULL)
- return -1;
+/**
+ * Constats for theTupleKeyDefined[][0]
+ */
+#define SETBOUND_EQ 1
+#define FAKE_PTR 2
+#define API_PTR 3
- m_setValueList->add(anAttrId, aValue);
- return 0;
-}
-int NdbScanOperation::setValue(Uint32 anAttrId, double aValue)
+/*
+ * After setBound() are done, move the accumulated ATTRINFO signals to
+ * a separate list. Then continue with normal scan.
+ */
+int
+NdbIndexScanOperation::saveBoundATTRINFO()
{
- // Check if attribute exist
- if (m_currentTable->getColumn(anAttrId) == NULL)
- return -1;
-
- m_setValueList->add(anAttrId, aValue);
- return 0;
+ theCurrentATTRINFO->setLength(theAI_LenInCurrAI);
+ theBoundATTRINFO = theFirstATTRINFO;
+ theTotalBoundAI_Len = theTotalCurrAI_Len;
+ theTotalCurrAI_Len = 5;
+ theBoundATTRINFO->setData(theTotalBoundAI_Len, 4);
+ theBoundATTRINFO->setData(0, 5);
+ theBoundATTRINFO->setData(0, 6);
+ theBoundATTRINFO->setData(0, 7);
+ theBoundATTRINFO->setData(0, 8);
+ theStatus = GetValue;
+
+ int res = getFirstATTRINFOScan();
+
+ /**
+ * Define each key with getValue (if ordered)
+ * unless the one's with EqBound
+ */
+ if(!res && m_ordered){
+
+ /**
+ * If setBound EQ
+ */
+ Uint32 i = 0;
+ while(theTupleKeyDefined[i][0] == SETBOUND_EQ)
+ i++;
+
+
+ Uint32 cnt = m_accessTable->getNoOfColumns() - 1;
+ m_sort_columns = cnt - i;
+ for(; i<cnt; i++){
+ NdbColumnImpl* key = m_accessTable->m_index->m_columns[i];
+ 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 res;
}
-NdbBlob*
-NdbScanOperation::getBlobHandle(const char* anAttrName)
-{
- return NdbOperation::getBlobHandle(m_transConnection, m_currentTable->getColumn(anAttrName));
-}
+#define WAITFOR_SCAN_TIMEOUT 120000
-NdbBlob*
-NdbScanOperation::getBlobHandle(Uint32 anAttrId)
-{
- return NdbOperation::getBlobHandle(m_transConnection, m_currentTable->getColumn(anAttrId));
+int
+NdbScanOperation::executeCursor(int nodeId){
+ NdbConnection * tCon = theNdbCon;
+ TransporterFacade* tp = TransporterFacade::instance();
+ Guard guard(tp->theMutexPtr);
+ Uint32 seq = tCon->theNodeSequence;
+ if (tp->get_node_alive(nodeId) &&
+ (tp->getNodeSequence(nodeId) == seq)) {
+
+ if(prepareSendScan(tCon->theTCConPtr, tCon->theTransactionId) == -1)
+ return -1;
+
+ tCon->theMagicNumber = 0x37412619;
+
+ if (doSendScan(nodeId) == -1)
+ return -1;
+
+ return 0;
+ } else {
+ if (!(tp->get_node_stopping(nodeId) &&
+ (tp->getNodeSequence(nodeId) == seq))){
+ 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);
+ }//if
+ tCon->theCommitStatus = NdbConnection::Aborted;
+ }//if
+ return -1;
}
-// Private methods
+#define DEBUG_NEXT_RESULT 0
-int NdbScanOperation::executeCursor(int ProcessorId)
+int NdbScanOperation::nextResult(bool fetchAllowed)
{
- int result = theNdbCon->executeScan();
- // If the scan started ok and we are updating or deleting
- // iterate over all tuples
- if ((m_updateOp) || (m_deleteOp)) {
- NdbOperation* newOp;
-
- while ((result != -1) && (nextResult() == 0)) {
- if (m_updateOp) {
- newOp = takeOverScanOp(UpdateRequest, m_transConnection);
- // Pass setValues from scan operation to new operation
- m_setValueList->iterate(SetValueRecList::callSetValueFn, *newOp);
- // No need to call updateTuple since scan was taken over for update
- // it should be the same with delete - MASV
- // newOp->updateTuple();
+ if(m_ordered)
+ return ((NdbIndexScanOperation*)this)->next_result_ordered(fetchAllowed);
+
+ /**
+ * Check current receiver
+ */
+ int retVal = 2;
+ Uint32 idx = m_current_api_receiver;
+ Uint32 last = m_api_receivers_count;
+
+ if(DEBUG_NEXT_RESULT)
+ ndbout_c("nextResult(%d) idx=%d last=%d", fetchAllowed, idx, last);
+
+ /**
+ * Check next buckets
+ */
+ for(; idx < last; idx++){
+ NdbReceiver* tRec = m_api_receivers[idx];
+ if(tRec->nextResult()){
+ tRec->copyout(theReceiver);
+ retVal = 0;
+ break;
+ }
+ }
+
+ /**
+ * We have advanced atleast one bucket
+ */
+ if(!fetchAllowed || !retVal){
+ m_current_api_receiver = idx;
+ if(DEBUG_NEXT_RESULT) ndbout_c("return %d", retVal);
+ return retVal;
+ }
+
+ Uint32 nodeId = theNdbCon->theDBnode;
+ TransporterFacade* tp = TransporterFacade::instance();
+ Guard guard(tp->theMutexPtr);
+ Uint32 seq = theNdbCon->theNodeSequence;
+ if(seq == tp->getNodeSequence(nodeId) && send_next_scan(idx, false) == 0){
+
+ idx = m_current_api_receiver;
+ last = m_api_receivers_count;
+
+ do {
+ if(theError.code){
+ setErrorCode(theError.code);
+ if(DEBUG_NEXT_RESULT) ndbout_c("return -1");
+ return -1;
}
- else if (m_deleteOp) {
- newOp = takeOverScanOp(DeleteRequest, m_transConnection);
- // newOp->deleteTuple();
+
+ Uint32 cnt = m_conf_receivers_count;
+ Uint32 sent = m_sent_receivers_count;
+
+ if(DEBUG_NEXT_RESULT)
+ ndbout_c("idx=%d last=%d cnt=%d sent=%d", idx, last, cnt, sent);
+
+ if(cnt > 0){
+ /**
+ * Just move completed receivers
+ */
+ memcpy(m_api_receivers+last, m_conf_receivers, cnt * sizeof(char*));
+ last += cnt;
+ m_conf_receivers_count = 0;
+ } else if(retVal == 2 && sent > 0){
+ /**
+ * No completed...
+ */
+ theNdb->theWaiter.m_node = nodeId;
+ theNdb->theWaiter.m_state = WAIT_SCAN;
+ int return_code = theNdb->receiveResponse(WAITFOR_SCAN_TIMEOUT);
+ if (return_code == 0 && seq == tp->getNodeSequence(nodeId)) {
+ continue;
+ } else {
+ idx = last;
+ retVal = -2; //return_code;
+ }
+ } else if(retVal == 2){
+ /**
+ * No completed & no sent -> EndOfData
+ */
+ if(send_next_scan(0, true) == 0){ // Close scan
+ theNdb->theWaiter.m_node = nodeId;
+ theNdb->theWaiter.m_state = WAIT_SCAN;
+ int return_code = theNdb->receiveResponse(WAITFOR_SCAN_TIMEOUT);
+ if (return_code == 0 && seq == tp->getNodeSequence(nodeId)) {
+ theError.code = -1; // make sure user gets error if he tries again
+ if(DEBUG_NEXT_RESULT) ndbout_c("return 1");
+ return 1;
+ }
+ retVal = -1; //return_code;
+ } else {
+ retVal = -3;
+ }
+ idx = last;
}
-#if 0
- // takeOverScanOp will take over the lock that scan aquired
- // the lock is released when nextScanResult is called
- // That means that the "takeover" has to be sent to the kernel
- // before nextScanresult is called - MASV
- if (m_autoExecute){
- m_transConnection->execute(NoCommit);
+
+ if(retVal == 0)
+ break;
+
+ for(; idx < last; idx++){
+ NdbReceiver* tRec = m_api_receivers[idx];
+ if(tRec->nextResult()){
+ tRec->copyout(theReceiver);
+ retVal = 0;
+ break;
+ }
}
-#else
- m_transConnection->execute(NoCommit);
-#endif
- }
- closeScan();
+ } while(retVal == 2);
+ } else {
+ retVal = -3;
}
-
- return result;
+
+ m_api_receivers_count = last;
+ m_current_api_receiver = idx;
+
+ switch(retVal){
+ case 0:
+ case 1:
+ case 2:
+ if(DEBUG_NEXT_RESULT) ndbout_c("return %d", retVal);
+ return retVal;
+ case -1:
+ setErrorCode(4008); // Timeout
+ break;
+ case -2:
+ setErrorCode(4028); // Node fail
+ break;
+ case -3: // send_next_scan -> return fail (set error-code self)
+ break;
+ }
+
+ theNdbCon->theTransactionIsStarted = false;
+ theNdbCon->theReleaseOnClose = true;
+ if(DEBUG_NEXT_RESULT) ndbout_c("return -1", retVal);
+ return -1;
}
-int NdbScanOperation::nextResult(bool fetchAllowed)
-{
- int result = theNdbCon->nextScanResult(fetchAllowed);
- if (result == -1){
- // Move the error code from hupped transaction
- // to the real trans
- const NdbError err = theNdbCon->getNdbError();
- m_transConnection->setOperationErrorCode(err.code);
- }
- if (result == 0) {
- // handle blobs
- NdbBlob* tBlob = theBlobList;
- while (tBlob != NULL) {
- if (tBlob->atNextResult() == -1)
- return -1;
- tBlob = tBlob->theNext;
+int
+NdbScanOperation::send_next_scan(Uint32 cnt, bool stopScanFlag){
+ if(cnt > 0 || stopScanFlag){
+ NdbApiSignal tSignal(theNdb->theMyRef);
+ tSignal.setSignal(GSN_SCAN_NEXTREQ);
+
+ Uint32* theData = tSignal.getDataPtrSend();
+ theData[0] = theNdbCon->theTCConPtr;
+ theData[1] = stopScanFlag == true ? 1 : 0;
+ Uint64 transId = theNdbCon->theTransactionId;
+ theData[2] = transId;
+ theData[3] = (Uint32) (transId >> 32);
+
+ /**
+ * Prepare ops
+ */
+ Uint32 last = m_sent_receivers_count;
+ Uint32 * prep_array = (cnt > 21 ? m_prepared_receivers : theData + 4);
+ for(Uint32 i = 0; i<cnt; i++){
+ NdbReceiver * tRec = m_api_receivers[i];
+ m_sent_receivers[last+i] = tRec;
+ tRec->m_list_index = last+i;
+ prep_array[i] = tRec->m_tcPtrI;
+ tRec->prepareSend();
}
+ memcpy(&m_api_receivers[0], &m_api_receivers[cnt], cnt * sizeof(char*));
+
+ Uint32 nodeId = theNdbCon->theDBnode;
+ TransporterFacade * tp = TransporterFacade::instance();
+ int ret;
+ if(cnt > 21){
+ tSignal.setLength(4);
+ LinearSectionPtr ptr[3];
+ ptr[0].p = prep_array;
+ ptr[0].sz = cnt;
+ ret = tp->sendFragmentedSignal(&tSignal, nodeId, ptr, 1);
+ } else {
+ tSignal.setLength(4+cnt);
+ ret = tp->sendSignal(&tSignal, nodeId);
+ }
+
+ m_sent_receivers_count = last + cnt + stopScanFlag;
+ m_api_receivers_count -= cnt;
+ m_current_api_receiver = 0;
+
+ return ret;
}
- return result;
+ return 0;
}
int
NdbScanOperation::prepareSend(Uint32 TC_ConnectPtr, Uint64 TransactionId)
{
printf("NdbScanOperation::prepareSend\n");
+ abort();
return 0;
}
@@ -385,300 +653,834 @@ NdbScanOperation::doSend(int ProcessorId)
void NdbScanOperation::closeScan()
{
- if(theNdbCon){
- if (theNdbCon->stopScan() == -1)
- theError = theNdbCon->getNdbError();
- theNdb->closeTransaction(theNdbCon);
- theNdbCon = 0;
- }
+ if(m_transConnection) do {
+ if(DEBUG_NEXT_RESULT)
+ ndbout_c("closeScan() theError.code = %d "
+ "m_api_receivers_count = %d "
+ "m_conf_receivers_count = %d "
+ "m_sent_receivers_count = %d",
+ theError.code,
+ m_api_receivers_count,
+ m_conf_receivers_count,
+ m_sent_receivers_count);
+
+ 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
+ }
+
+ /**
+ * 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;
+ theNdb->closeTransaction(theNdbCon);
+
+ theNdbCon = 0;
m_transConnection = NULL;
}
-void NdbScanOperation::release(){
- closeScan();
- NdbCursorOperation::release();
+void
+NdbScanOperation::execCLOSE_SCAN_REP(){
+ m_api_receivers_count = 0;
+ m_conf_receivers_count = 0;
+ m_sent_receivers_count = 0;
}
-void SetValueRecList::add(const char* anAttrName, const char* aValue, Uint32 len)
+void NdbScanOperation::release()
{
- SetValueRec* newSetValueRec = new SetValueRec();
-
- newSetValueRec->stype = SetValueRec::SET_STRING_ATTR1;
- newSetValueRec->anAttrName = strdup(anAttrName);
- newSetValueRec->stringStruct.aStringValue = (char *) malloc(len);
- strlcpy(newSetValueRec->stringStruct.aStringValue, aValue, len);
- if (!last)
- first = last = newSetValueRec;
- else {
- last->next = newSetValueRec;
- last = newSetValueRec;
+ if(theNdbCon != 0 || m_transConnection != 0){
+ closeScan();
+ }
+ for(Uint32 i = 0; i<m_allocated_receivers; i++){
+ m_receivers[i]->release();
}
}
-void SetValueRecList::add(const char* anAttrName, Int32 aValue)
-{
- SetValueRec* newSetValueRec = new SetValueRec();
+/***************************************************************************
+int prepareSendScan(Uint32 aTC_ConnectPtr,
+ Uint64 aTransactionId)
+
+Return Value: Return 0 : preparation of send was succesful.
+ Return -1: In all other case.
+Parameters: aTC_ConnectPtr: the Connect pointer to TC.
+ aTransactionId: the Transaction identity of the transaction.
+Remark: Puts the the final data into ATTRINFO signal(s) after this
+ we know the how many signal to send and their sizes
+***************************************************************************/
+int NdbScanOperation::prepareSendScan(Uint32 aTC_ConnectPtr,
+ Uint64 aTransactionId){
+
+ if (theInterpretIndicator != 1 ||
+ (theOperationType != OpenScanRequest &&
+ theOperationType != OpenRangeScanRequest)) {
+ setErrorCodeAbort(4005);
+ return -1;
+ }
- newSetValueRec->stype = SetValueRec::SET_INT32_ATTR1;
- newSetValueRec->anAttrName = strdup(anAttrName);
- newSetValueRec->anInt32Value = aValue;
- if (!last)
- first = last = newSetValueRec;
- else {
- last->next = newSetValueRec;
- last = newSetValueRec;
+ if (theStatus == SetBound) {
+ ((NdbIndexScanOperation*)this)->saveBoundATTRINFO();
+ theStatus = GetValue;
}
-}
-void SetValueRecList::add(const char* anAttrName, Uint32 aValue)
-{
- SetValueRec* newSetValueRec = new SetValueRec();
+ theErrorLine = 0;
- newSetValueRec->stype = SetValueRec::SET_UINT32_ATTR1;
- newSetValueRec->anAttrName = strdup(anAttrName);
- newSetValueRec->anUint32Value = aValue;
- if (!last)
- first = last = newSetValueRec;
- else {
- last->next = newSetValueRec;
- last = newSetValueRec;
+ // In preapareSendInterpreted we set the sizes (word 4-8) in the
+ // first ATTRINFO signal.
+ if (prepareSendInterpreted() == -1)
+ return -1;
+
+ if(m_ordered){
+ ((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
+ */
+ theReceiver.prepareSend();
+ bool keyInfo = m_keyInfo;
+ Uint32 key_size = keyInfo ? m_currentTable->m_keyLenInWords : 0;
+ for(Uint32 i = 0; i<theParallelism; i++){
+ m_receivers[i]->do_get_value(&theReceiver, theBatchSize, key_size);
}
+ return 0;
}
-void SetValueRecList::add(const char* anAttrName, Int64 aValue)
+/******************************************************************************
+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)
{
- SetValueRec* newSetValueRec = new SetValueRec();
+ Uint32 tSignalCount = 0;
+ NdbApiSignal* tSignal;
+
+ if (theInterpretIndicator != 1 ||
+ (theOperationType != OpenScanRequest &&
+ theOperationType != OpenRangeScanRequest)) {
+ setErrorCodeAbort(4005);
+ return -1;
+ }
+
+ assert(theSCAN_TABREQ != NULL);
+ tSignal = theSCAN_TABREQ;
+ if (tSignal->setSignal(GSN_SCAN_TABREQ) == -1) {
+ setErrorCode(4001);
+ return -1;
+ }
+ // 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;
+ TransporterFacade *tp = TransporterFacade::instance();
+ if(theParallelism > 16){
+ LinearSectionPtr ptr[3];
+ ptr[0].p = m_prepared_receivers;
+ ptr[0].sz = theParallelism;
+ if (tp->sendFragmentedSignal(tSignal, aProcessorId, ptr, 1) == -1) {
+ setErrorCode(4002);
+ return -1;
+ }
+ } else {
+ tSignal->setLength(9+theParallelism);
+ memcpy(tSignal->getDataPtrSend()+9, m_prepared_receivers, 4*theParallelism);
+ if (tp->sendSignal(tSignal, aProcessorId) == -1) {
+ setErrorCode(4002);
+ return -1;
+ }
+ }
- newSetValueRec->stype = SetValueRec::SET_INT64_ATTR1;
- newSetValueRec->anAttrName = strdup(anAttrName);
- newSetValueRec->anInt64Value = aValue;
- if (!last)
- first = last = newSetValueRec;
- else {
- last->next = newSetValueRec;
- last = newSetValueRec;
+ if (theOperationType == OpenRangeScanRequest) {
+ // must have at least one signal since it contains attrLen for bounds
+ assert(theBoundATTRINFO != NULL);
+ tSignal = theBoundATTRINFO;
+ while (tSignal != NULL) {
+ if (tp->sendSignal(tSignal,aProcessorId) == -1){
+ setErrorCode(4002);
+ return -1;
+ }
+ tSignalCount++;
+ tSignal = tSignal->next();
+ }
+ }
+
+ tSignal = theFirstATTRINFO;
+ while (tSignal != NULL) {
+ if (tp->sendSignal(tSignal,aProcessorId) == -1){
+ setErrorCode(4002);
+ return -1;
+ }
+ tSignalCount++;
+ tSignal = tSignal->next();
+ }
+ theStatus = WaitResponse;
+ return tSignalCount;
+}//NdbOperation::doSendScan()
+
+/******************************************************************************
+ * NdbOperation* takeOverScanOp(NdbConnection* updateTrans);
+ *
+ * Parameters: The update transactions NdbConnection pointer.
+ * Return Value: A reference to the transferred operation object
+ * or NULL if no success.
+ * Remark: Take over the scanning transactions NdbOperation
+ * object for a tuple to an update transaction,
+ * which is the last operation read in nextScanResult()
+ * (theNdbCon->thePreviousScanRec)
+ *
+ * FUTURE IMPLEMENTATION: (This note was moved from header file.)
+ * In the future, it will even be possible to transfer
+ * to a NdbConnection on another Ndb-object.
+ * In this case the receiving NdbConnection-object must call
+ * a method receiveOpFromScan to actually receive the information.
+ * 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)
+{
+ Uint32 idx = m_current_api_receiver;
+ Uint32 last = m_api_receivers_count;
+
+ Uint32 row;
+ NdbReceiver * tRec;
+ NdbRecAttr * tRecAttr;
+ if(idx < last && (tRec = m_api_receivers[idx])
+ && ((row = tRec->m_current_row) <= tRec->m_defined_rows)
+ && (tRecAttr = tRec->m_rows[row-1])){
+
+ const Uint32 * src = (Uint32*)tRecAttr->aRef();
+ memcpy(data, src, 4*size);
+ return 0;
}
+ return -1;
}
-void SetValueRecList::add(const char* anAttrName, Uint64 aValue)
-{
- SetValueRec* newSetValueRec = new SetValueRec();
+NdbOperation*
+NdbScanOperation::takeOverScanOp(OperationType opType, NdbConnection* pTrans){
+
+ Uint32 idx = m_current_api_receiver;
+ Uint32 last = m_api_receivers_count;
+
+ Uint32 row;
+ NdbReceiver * tRec;
+ NdbRecAttr * tRecAttr;
+ if(idx < last && (tRec = m_api_receivers[idx])
+ && ((row = tRec->m_current_row) <= tRec->m_defined_rows)
+ && (tRecAttr = tRec->m_rows[row-1])){
+
+ NdbOperation * newOp = pTrans->getNdbOperation(m_currentTable);
+ if (newOp == NULL){
+ return NULL;
+ }
+
+ const Uint32 len = (tRecAttr->attrSize() * tRecAttr->arraySize() + 3)/4-1;
+
+ newOp->theTupKeyLen = len;
+ newOp->theOperationType = opType;
+ if (opType == DeleteRequest) {
+ newOp->theStatus = GetValue;
+ } else {
+ newOp->theStatus = SetValue;
+ }
+
+ const Uint32 * src = (Uint32*)tRecAttr->aRef();
+ const Uint32 tScanInfo = src[len] & 0xFFFF;
+ const Uint32 tTakeOverNode = src[len] >> 16;
+ {
+ UintR scanInfo = 0;
+ TcKeyReq::setTakeOverScanFlag(scanInfo, 1);
+ TcKeyReq::setTakeOverScanNode(scanInfo, tTakeOverNode);
+ TcKeyReq::setTakeOverScanInfo(scanInfo, tScanInfo);
+ newOp->theScanInfo = scanInfo;
+ }
- newSetValueRec->stype = SetValueRec::SET_UINT64_ATTR1;
- newSetValueRec->anAttrName = strdup(anAttrName);
- newSetValueRec->anUint64Value = aValue;
- if (!last)
- first = last = newSetValueRec;
- else {
- last->next = newSetValueRec;
- last = newSetValueRec;
+ // Copy the first 8 words of key info from KEYINF20 into TCKEYREQ
+ TcKeyReq * tcKeyReq = CAST_PTR(TcKeyReq,newOp->theTCREQ->getDataPtrSend());
+ Uint32 i = 0;
+ for (i = 0; i < TcKeyReq::MaxKeyInfo && i < len; i++) {
+ tcKeyReq->keyInfo[i] = * src++;
+ }
+
+ if(i < len){
+ NdbApiSignal* tSignal = theNdb->getSignal();
+ newOp->theFirstKEYINFO = tSignal;
+
+ Uint32 left = len - i;
+ while(tSignal && left > KeyInfo::DataLength){
+ tSignal->setSignal(GSN_KEYINFO);
+ KeyInfo * keyInfo = CAST_PTR(KeyInfo, tSignal->getDataPtrSend());
+ memcpy(keyInfo->keyData, src, 4 * KeyInfo::DataLength);
+ src += KeyInfo::DataLength;
+ left -= KeyInfo::DataLength;
+
+ tSignal->next(theNdb->getSignal());
+ tSignal = tSignal->next();
+ }
+
+ if(tSignal && left > 0){
+ tSignal->setSignal(GSN_KEYINFO);
+ KeyInfo * keyInfo = CAST_PTR(KeyInfo, tSignal->getDataPtrSend());
+ memcpy(keyInfo->keyData, src, 4 * left);
+ }
+ }
+ // create blob handles automatically
+ if (opType == DeleteRequest && m_currentTable->m_noOfBlobs != 0) {
+ for (unsigned i = 0; i < m_currentTable->m_columns.size(); i++) {
+ NdbColumnImpl* c = m_currentTable->m_columns[i];
+ assert(c != 0);
+ if (c->getBlobType()) {
+ if (newOp->getBlobHandle(pTrans, c) == NULL)
+ return NULL;
+ }
+ }
+ }
+
+ return newOp;
}
+ return 0;
}
-void SetValueRecList::add(const char* anAttrName, float aValue)
+NdbBlob*
+NdbScanOperation::getBlobHandle(const char* anAttrName)
{
- SetValueRec* newSetValueRec = new SetValueRec();
+ return NdbOperation::getBlobHandle(m_transConnection,
+ m_currentTable->getColumn(anAttrName));
+}
- newSetValueRec->stype = SetValueRec::SET_FLOAT_ATTR1;
- newSetValueRec->anAttrName = strdup(anAttrName);
- newSetValueRec->aFloatValue = aValue;
- if (!last)
- first = last = newSetValueRec;
- else {
- last->next = newSetValueRec;
- last = newSetValueRec;
- }
+NdbBlob*
+NdbScanOperation::getBlobHandle(Uint32 anAttrId)
+{
+ return NdbOperation::getBlobHandle(m_transConnection,
+ m_currentTable->getColumn(anAttrId));
}
-void SetValueRecList::add(const char* anAttrName, double aValue)
+NdbIndexScanOperation::NdbIndexScanOperation(Ndb* aNdb)
+ : NdbScanOperation(aNdb)
{
- SetValueRec* newSetValueRec = new SetValueRec();
+}
- newSetValueRec->stype = SetValueRec::SET_DOUBLE_ATTR1;
- newSetValueRec->anAttrName = strdup(anAttrName);
- newSetValueRec->aDoubleValue = aValue;
- if (!last)
- first = last = newSetValueRec;
- else {
- last->next = newSetValueRec;
- last = newSetValueRec;
- }
+NdbIndexScanOperation::~NdbIndexScanOperation(){
}
-void SetValueRecList::add(Uint32 anAttrId, const char* aValue, Uint32 len)
+int
+NdbIndexScanOperation::setBound(const char* anAttrName, int type, const void* aValue, Uint32 len)
{
- SetValueRec* newSetValueRec = new SetValueRec();
-
- newSetValueRec->stype = SetValueRec::SET_STRING_ATTR2;
- newSetValueRec->anAttrId = anAttrId;
- newSetValueRec->stringStruct.aStringValue = (char *) malloc(len);
- strlcpy(newSetValueRec->stringStruct.aStringValue, aValue, len);
- if (!last)
- first = last = newSetValueRec;
- else {
- last->next = newSetValueRec;
- last = newSetValueRec;
- }
+ return setBound(m_accessTable->getColumn(anAttrName), type, aValue, len);
}
-void SetValueRecList::add(Uint32 anAttrId, Int32 aValue)
+int
+NdbIndexScanOperation::setBound(Uint32 anAttrId, int type, const void* aValue, Uint32 len)
{
- SetValueRec* newSetValueRec = new SetValueRec();
+ return setBound(m_accessTable->getColumn(anAttrId), type, aValue, len);
+}
- newSetValueRec->stype = SetValueRec::SET_INT32_ATTR2;
- newSetValueRec->anAttrId = anAttrId;
- newSetValueRec->anInt32Value = aValue;
- last->next = newSetValueRec;
- last = newSetValueRec;
+int
+NdbIndexScanOperation::equal_impl(const NdbColumnImpl* anAttrObject,
+ const char* aValue,
+ Uint32 len){
+ return setBound(anAttrObject, BoundEQ, aValue, len);
}
-void SetValueRecList::add(Uint32 anAttrId, Uint32 aValue)
-{
- SetValueRec* newSetValueRec = new SetValueRec();
+NdbRecAttr*
+NdbIndexScanOperation::getValue_impl(const NdbColumnImpl* attrInfo,
+ char* aValue){
+ if(!m_ordered){
+ return NdbScanOperation::getValue_impl(attrInfo, aValue);
+ }
+
+ if (theStatus == SetBound) {
+ saveBoundATTRINFO();
+ theStatus = GetValue;
+ }
- newSetValueRec->stype = SetValueRec::SET_UINT32_ATTR2;
- newSetValueRec->anAttrId = anAttrId;
- newSetValueRec->anUint32Value = aValue;
- if (!last)
- first = last = newSetValueRec;
- else {
- last->next = newSetValueRec;
- last = newSetValueRec;
+ int id = attrInfo->m_attrId; // In "real" table
+ assert(m_accessTable->m_index);
+ int sz = (int)m_accessTable->m_index->m_key_ids.size();
+ if(id >= sz || (id = m_accessTable->m_index->m_key_ids[id]) == -1){
+ return NdbScanOperation::getValue_impl(attrInfo, aValue);
+ }
+
+ assert(id < NDB_MAX_NO_OF_ATTRIBUTES_IN_KEY);
+ Uint32 marker = theTupleKeyDefined[id][0];
+
+ if(marker == SETBOUND_EQ){
+ return NdbScanOperation::getValue_impl(attrInfo, aValue);
+ } else if(marker == API_PTR){
+ return NdbScanOperation::getValue_impl(attrInfo, aValue);
}
+
+ assert(marker == FAKE_PTR);
+
+ UintPtr oldVal;
+ oldVal = theTupleKeyDefined[id][1];
+#if (SIZEOF_CHARP == 8)
+ oldVal = oldVal | (((UintPtr)theTupleKeyDefined[id][2]) << 32);
+#endif
+ theTupleKeyDefined[id][0] = API_PTR;
+
+ NdbRecAttr* tmp = (NdbRecAttr*)oldVal;
+ tmp->setup(attrInfo, aValue);
+
+ return tmp;
}
-void SetValueRecList::add(Uint32 anAttrId, Int64 aValue)
+#include <AttributeHeader.hpp>
+/*
+ * Define bound on index column in range scan.
+ */
+int
+NdbIndexScanOperation::setBound(const NdbColumnImpl* tAttrInfo,
+ int type, const void* aValue, Uint32 len)
{
- SetValueRec* newSetValueRec = new SetValueRec();
+ if (theOperationType == OpenRangeScanRequest &&
+ theStatus == SetBound &&
+ (0 <= type && type <= 4) &&
+ len <= 8000) {
+ // bound type
+
+ insertATTRINFO(type);
+ // attribute header
+ Uint32 sizeInBytes = tAttrInfo->m_attrSize * tAttrInfo->m_arraySize;
+ if (len != sizeInBytes && (len != 0)) {
+ setErrorCodeAbort(4209);
+ return -1;
+ }
+ len = aValue != NULL ? sizeInBytes : 0;
+ Uint32 tIndexAttrId = tAttrInfo->m_attrId;
+ Uint32 sizeInWords = (len + 3) / 4;
+ AttributeHeader ah(tIndexAttrId, sizeInWords);
+ insertATTRINFO(ah.m_value);
+ if (len != 0) {
+ // attribute data
+ if ((UintPtr(aValue) & 0x3) == 0 && (len & 0x3) == 0)
+ insertATTRINFOloop((const Uint32*)aValue, sizeInWords);
+ else {
+ Uint32 temp[2000];
+ memcpy(temp, aValue, len);
+ while ((len & 0x3) != 0)
+ ((char*)temp)[len++] = 0;
+ insertATTRINFOloop(temp, sizeInWords);
+ }
+ }
- newSetValueRec->stype = SetValueRec::SET_INT64_ATTR2;
- newSetValueRec->anAttrId = anAttrId;
- newSetValueRec->anInt64Value = aValue;
- if (!last)
- first = last = newSetValueRec;
- else {
- last->next = newSetValueRec;
- last = newSetValueRec;
+ /**
+ * Do sorted stuff
+ */
+
+ /**
+ * The primary keys for an ordered index is defined in the beginning
+ * so it's safe to use [tIndexAttrId]
+ * (instead of looping as is NdbOperation::equal_impl)
+ */
+ if(type == BoundEQ && !theTupleKeyDefined[tIndexAttrId][0]){
+ theNoOfTupKeyDefined++;
+ theTupleKeyDefined[tIndexAttrId][0] = SETBOUND_EQ;
+ }
+
+ return 0;
+ } else {
+ setErrorCodeAbort(4228); // XXX wrong code
+ return -1;
}
}
-void SetValueRecList::add(Uint32 anAttrId, Uint64 aValue)
-{
- SetValueRec* newSetValueRec = new SetValueRec();
+NdbResultSet*
+NdbIndexScanOperation::readTuples(LockMode lm,
+ Uint32 batch,
+ Uint32 parallel,
+ bool order_by){
+ 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
+ m_current_api_receiver = m_sent_receivers_count;
+ m_api_receivers_count = m_sent_receivers_count;
+ }
+ return rs;
+}
- newSetValueRec->stype = SetValueRec::SET_UINT64_ATTR2;
- newSetValueRec->anAttrId = anAttrId;
- newSetValueRec->anUint64Value = aValue;
- if (!last)
- first = last = newSetValueRec;
- else {
- last->next = newSetValueRec;
- last = newSetValueRec;
+void
+NdbIndexScanOperation::fix_get_values(){
+ /**
+ * Loop through all getValues and set buffer pointer to "API" pointer
+ */
+ NdbRecAttr * curr = theReceiver.theFirstRecAttr;
+ Uint32 cnt = m_accessTable->getNoOfColumns() - 1;
+ assert(cnt < NDB_MAX_NO_OF_ATTRIBUTES_IN_KEY);
+
+ NdbIndexImpl * idx = m_accessTable->m_index;
+ NdbTableImpl * tab = m_currentTable;
+ for(Uint32 i = 0; i<cnt; i++){
+ Uint32 val = theTupleKeyDefined[i][0];
+ switch(val){
+ case FAKE_PTR:
+ curr->setup(curr->m_column, 0);
+ case API_PTR:
+ curr = curr->next();
+ break;
+ case SETBOUND_EQ:
+ break;
+#ifdef VM_TRACE
+ default:
+ abort();
+#endif
+ }
}
}
-void SetValueRecList::add(Uint32 anAttrId, float aValue)
-{
- SetValueRec* newSetValueRec = new SetValueRec();
+int
+NdbIndexScanOperation::compare(Uint32 skip, Uint32 cols,
+ const NdbReceiver* t1,
+ const NdbReceiver* t2){
+
+ NdbRecAttr * r1 = t1->m_rows[t1->m_current_row];
+ NdbRecAttr * r2 = t2->m_rows[t2->m_current_row];
- newSetValueRec->stype = SetValueRec::SET_FLOAT_ATTR2;
- newSetValueRec->anAttrId = anAttrId;
- newSetValueRec->aFloatValue = aValue;
- if (!last)
- first = last = newSetValueRec;
- else {
- last->next = newSetValueRec;
- last = newSetValueRec;
+ r1 = (skip ? r1->next() : r1);
+ r2 = (skip ? r2->next() : r2);
+
+ while(cols > 0){
+ Uint32 * d1 = (Uint32*)r1->aRef();
+ Uint32 * d2 = (Uint32*)r2->aRef();
+ unsigned r1_null = r1->isNULL();
+ if((r1_null ^ (unsigned)r2->isNULL())){
+ return (r1_null ? -1 : 1);
+ }
+ Uint32 type = NdbColumnImpl::getImpl(* r1->m_column).m_extType;
+ Uint32 size = (r1->theAttrSize * r1->theArraySize + 3) / 4;
+ if(!r1_null){
+ char r = NdbSqlUtil::cmp(type, d1, d2, size, size);
+ if(r){
+ assert(r != NdbSqlUtil::CmpUnknown);
+ assert(r != NdbSqlUtil::CmpError);
+ return r;
+ }
+ }
+ cols--;
+ r1 = r1->next();
+ r2 = r2->next();
}
+ return 0;
}
-void SetValueRecList::add(Uint32 anAttrId, double aValue)
-{
- SetValueRec* newSetValueRec = new SetValueRec();
+int
+NdbIndexScanOperation::next_result_ordered(bool fetchAllowed){
+
+ Uint32 u_idx = 0, u_last = 0;
+ Uint32 s_idx = m_current_api_receiver; // first sorted
+ Uint32 s_last = theParallelism; // last sorted
- newSetValueRec->stype = SetValueRec::SET_DOUBLE_ATTR2;
- newSetValueRec->anAttrId = anAttrId;
- newSetValueRec->aDoubleValue = aValue;
- if (!last)
- first = last = newSetValueRec;
- else {
- last->next = newSetValueRec;
- last = newSetValueRec;
+ NdbReceiver** arr = m_api_receivers;
+ NdbReceiver* tRec = arr[s_idx];
+
+ if(DEBUG_NEXT_RESULT) ndbout_c("nextOrderedResult(%d) nextResult: %d",
+ fetchAllowed,
+ (s_idx < s_last ? tRec->nextResult() : 0));
+
+ if(DEBUG_NEXT_RESULT) ndbout_c("u=[%d %d] s=[%d %d]",
+ u_idx, u_last,
+ s_idx, s_last);
+
+ bool fetchNeeded = (s_idx == s_last) || !tRec->nextResult();
+
+ if(fetchNeeded){
+ if(fetchAllowed){
+ if(DEBUG_NEXT_RESULT) ndbout_c("performing fetch...");
+ TransporterFacade* tp = TransporterFacade::instance();
+ Guard guard(tp->theMutexPtr);
+ Uint32 seq = theNdbCon->theNodeSequence;
+ Uint32 nodeId = theNdbCon->theDBnode;
+ if(seq == tp->getNodeSequence(nodeId) && !send_next_scan_ordered(s_idx)){
+ Uint32 tmp = m_sent_receivers_count;
+ s_idx = m_current_api_receiver;
+ while(m_sent_receivers_count > 0 && !theError.code){
+ theNdb->theWaiter.m_node = nodeId;
+ theNdb->theWaiter.m_state = WAIT_SCAN;
+ int return_code = theNdb->receiveResponse(WAITFOR_SCAN_TIMEOUT);
+ if (return_code == 0 && seq == tp->getNodeSequence(nodeId)) {
+ continue;
+ }
+ if(DEBUG_NEXT_RESULT) ndbout_c("return -1");
+ return -1;
+ }
+
+ u_idx = 0;
+ u_last = m_conf_receivers_count;
+ m_conf_receivers_count = 0;
+ memcpy(arr, m_conf_receivers, u_last * sizeof(char*));
+
+ if(DEBUG_NEXT_RESULT) ndbout_c("sent: %d recv: %d", tmp, u_last);
+ if(theError.code){
+ setErrorCode(theError.code);
+ if(DEBUG_NEXT_RESULT) ndbout_c("return -1");
+ return -1;
+ }
+ }
+ } else {
+ if(DEBUG_NEXT_RESULT) ndbout_c("return 2");
+ return 2;
+ }
+ } else {
+ u_idx = s_idx;
+ u_last = s_idx + 1;
+ s_idx++;
+ }
+
+ if(DEBUG_NEXT_RESULT) ndbout_c("u=[%d %d] s=[%d %d]",
+ u_idx, u_last,
+ s_idx, s_last);
+
+
+ Uint32 cols = m_sort_columns;
+ Uint32 skip = m_keyInfo;
+ while(u_idx < u_last){
+ u_last--;
+ tRec = arr[u_last];
+
+ // Do binary search instead to find place
+ Uint32 place = s_idx;
+ for(; place < s_last; place++){
+ if(compare(skip, cols, tRec, arr[place]) <= 0){
+ break;
+ }
+ }
+
+ if(place != s_idx){
+ if(DEBUG_NEXT_RESULT)
+ ndbout_c("memmove(%d, %d, %d)", s_idx-1, s_idx, (place - s_idx));
+ memmove(arr+s_idx-1, arr+s_idx, sizeof(char*)*(place - s_idx));
+ }
+
+ if(DEBUG_NEXT_RESULT) ndbout_c("putting %d @ %d", u_last, place - 1);
+ m_api_receivers[place-1] = tRec;
+ s_idx--;
}
-}
-void
-SetValueRecList::callSetValueFn(SetValueRec& aSetValueRec, NdbOperation& oper)
-{
- switch(aSetValueRec.stype) {
- case(SetValueRec::SET_STRING_ATTR1):
- oper.setValue(aSetValueRec.anAttrName, aSetValueRec.stringStruct.aStringValue, aSetValueRec.stringStruct.len);
- break;
- case(SetValueRec::SET_INT32_ATTR1):
- oper.setValue(aSetValueRec.anAttrName, aSetValueRec.anInt32Value);
- break;
- case(SetValueRec::SET_UINT32_ATTR1):
- oper.setValue(aSetValueRec.anAttrName, aSetValueRec.anUint32Value);
- break;
- case(SetValueRec::SET_INT64_ATTR1):
- oper.setValue(aSetValueRec.anAttrName, aSetValueRec.anInt64Value);
- break;
- case(SetValueRec::SET_UINT64_ATTR1):
- oper.setValue(aSetValueRec.anAttrName, aSetValueRec.anUint64Value);
- break;
- case(SetValueRec::SET_FLOAT_ATTR1):
- oper.setValue(aSetValueRec.anAttrName, aSetValueRec.aFloatValue);
- break;
- case(SetValueRec::SET_DOUBLE_ATTR1):
- oper.setValue(aSetValueRec.anAttrName, aSetValueRec.aDoubleValue);
- break;
- case(SetValueRec::SET_STRING_ATTR2):
- oper.setValue(aSetValueRec.anAttrId, aSetValueRec.stringStruct.aStringValue, aSetValueRec.stringStruct.len);
- break;
- case(SetValueRec::SET_INT32_ATTR2):
- oper.setValue(aSetValueRec.anAttrId, aSetValueRec.anInt32Value);
- break;
- case(SetValueRec::SET_UINT32_ATTR2):
- oper.setValue(aSetValueRec.anAttrId, aSetValueRec.anUint32Value);
- break;
- case(SetValueRec::SET_INT64_ATTR2):
- oper.setValue(aSetValueRec.anAttrId, aSetValueRec.anInt64Value);
- break;
- case(SetValueRec::SET_UINT64_ATTR2):
- oper.setValue(aSetValueRec.anAttrId, aSetValueRec.anUint64Value);
- break;
- case(SetValueRec::SET_FLOAT_ATTR2):
- oper.setValue(aSetValueRec.anAttrId, aSetValueRec.aFloatValue);
- break;
- case(SetValueRec::SET_DOUBLE_ATTR2):
- oper.setValue(aSetValueRec.anAttrId, aSetValueRec.aDoubleValue);
- break;
+ if(DEBUG_NEXT_RESULT) ndbout_c("u=[%d %d] s=[%d %d]",
+ u_idx, u_last,
+ s_idx, s_last);
+
+ m_current_api_receiver = s_idx;
+
+ if(DEBUG_NEXT_RESULT)
+ for(Uint32 i = s_idx; i<s_last; i++)
+ ndbout_c("%p", arr[i]);
+
+ tRec = m_api_receivers[s_idx];
+ if(s_idx < s_last && tRec->nextResult()){
+ tRec->copyout(theReceiver);
+ if(DEBUG_NEXT_RESULT) ndbout_c("return 0");
+ return 0;
}
-}
-SetValueRec::~SetValueRec()
-{
- if ((stype == SET_STRING_ATTR1) ||
- (stype == SET_INT32_ATTR1) ||
- (stype == SET_UINT32_ATTR1) ||
- (stype == SET_INT64_ATTR1) ||
- (stype == SET_UINT64_ATTR1) ||
- (stype == SET_FLOAT_ATTR1) ||
- (stype == SET_DOUBLE_ATTR1))
- free(anAttrName);
-
- if ((stype == SET_STRING_ATTR1) ||
- (stype == SET_STRING_ATTR2))
- free(stringStruct.aStringValue);
- if (next) delete next;
- next = 0;
+ TransporterFacade* tp = TransporterFacade::instance();
+ Guard guard(tp->theMutexPtr);
+ Uint32 seq = theNdbCon->theNodeSequence;
+ Uint32 nodeId = theNdbCon->theDBnode;
+ if(seq == tp->getNodeSequence(nodeId) &&
+ send_next_scan(0, true) == 0 &&
+ theError.code == 0){
+ if(DEBUG_NEXT_RESULT) ndbout_c("return 1");
+ return 1;
+ }
+ setErrorCode(theError.code);
+ if(DEBUG_NEXT_RESULT) ndbout_c("return -1");
+ return -1;
}
int
-NdbScanOperation::equal_impl(const NdbColumnImpl* anAttrObject,
- const char* aValue,
- Uint32 len){
- return setBound(anAttrObject, BoundEQ, aValue, len);
+NdbIndexScanOperation::send_next_scan_ordered(Uint32 idx){
+ if(idx == theParallelism)
+ return 0;
+
+ NdbApiSignal tSignal(theNdb->theMyRef);
+ tSignal.setSignal(GSN_SCAN_NEXTREQ);
+
+ Uint32* theData = tSignal.getDataPtrSend();
+ theData[0] = theNdbCon->theTCConPtr;
+ theData[1] = 0;
+ Uint64 transId = theNdbCon->theTransactionId;
+ theData[2] = transId;
+ theData[3] = (Uint32) (transId >> 32);
+
+ /**
+ * Prepare ops
+ */
+ Uint32 last = m_sent_receivers_count;
+ Uint32 * prep_array = theData + 4;
+
+ NdbReceiver * tRec = m_api_receivers[idx];
+ m_sent_receivers[last] = tRec;
+ tRec->m_list_index = last;
+ prep_array[0] = tRec->m_tcPtrI;
+ tRec->prepareSend();
+
+ m_sent_receivers_count = last + 1;
+ m_current_api_receiver = idx + 1;
+
+ Uint32 nodeId = theNdbCon->theDBnode;
+ TransporterFacade * tp = TransporterFacade::instance();
+ tSignal.setLength(4+1);
+ return tp->sendSignal(&tSignal, nodeId);
}
+int
+NdbScanOperation::restart(){
+ TransporterFacade* tp = TransporterFacade::instance();
+ Guard guard(tp->theMutexPtr);
+
+ Uint32 seq = theNdbCon->theNodeSequence;
+ Uint32 nodeId = theNdbCon->theDBnode;
+
+ if(seq != tp->getNodeSequence(nodeId)){
+ theNdbCon->theReleaseOnClose = true;
+ return -1;
+ }
+
+ while(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;
+ return -1;
+ }
+ }
+
+ if(m_api_receivers_count+m_conf_receivers_count){
+ // Send close scan
+ if(send_next_scan(0, true) == -1) // Close scan
+ return -1;
+ }
+
+ /**
+ * 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;
+ return -1;
+ }
+ }
+ /**
+ * Reset receivers
+ */
+ const Uint32 parallell = theParallelism;
+
+ for(Uint32 i = 0; i<parallell; 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_receivers[i]->prepareSend();
+ }
+
+ m_api_receivers_count = 0;
+ m_current_api_receiver = 0;
+ m_sent_receivers_count = parallell;
+ m_conf_receivers_count = 0;
+
+ if(m_ordered){
+ m_current_api_receiver = parallell;
+ m_api_receivers_count = parallell;
+ }
+
+ if (doSendScan(nodeId) == -1)
+ return -1;
+
+ return 0;
+}
diff --git a/ndb/src/ndbapi/Ndbif.cpp b/ndb/src/ndbapi/Ndbif.cpp
index a05eb4c54c3..7ad37401b9a 100644
--- a/ndb/src/ndbapi/Ndbif.cpp
+++ b/ndb/src/ndbapi/Ndbif.cpp
@@ -17,11 +17,9 @@
#include "NdbApiSignal.hpp"
#include "NdbImpl.hpp"
-//#include "NdbSchemaOp.hpp"
-//#include "NdbSchemaCon.hpp"
#include "NdbOperation.hpp"
#include "NdbIndexOperation.hpp"
-#include "NdbScanReceiver.hpp"
+#include "NdbScanOperation.hpp"
#include "NdbConnection.hpp"
#include "NdbRecAttr.hpp"
#include "NdbReceiver.hpp"
@@ -34,6 +32,9 @@
#include <signaldata/CreateIndx.hpp>
#include <signaldata/DropIndx.hpp>
#include <signaldata/TcIndx.hpp>
+#include <signaldata/TransIdAI.hpp>
+#include <signaldata/ScanFrag.hpp>
+#include <signaldata/ScanTab.hpp>
#include <ndb_limits.h>
#include <NdbOut.hpp>
@@ -41,12 +42,13 @@
/******************************************************************************
- * int init( int aMaxNoOfTransactions );
+ * int init( int aNrOfCon, int aNrOfOp );
*
* Return Value: Return 0 : init was successful.
* Return -1: In all other case.
- * Parameters: aMaxNoOfTransactions : Max number of simultaneous transations
- * Remark: Create pointers and idle list Synchronous.
+ * Parameters: aNrOfCon : Number of connections offered to the application.
+ * aNrOfOp : Number of operations offered to the application.
+ * Remark: Create pointers and idle list Synchronous.
****************************************************************************/
int
Ndb::init(int aMaxNoOfTransactions)
@@ -75,7 +77,7 @@ Ndb::init(int aMaxNoOfTransactions)
executeMessage,
statusMessage);
-
+
if ( tBlockNo == -1 ) {
theError.code = 4105;
theFacade->unlock_mutex();
@@ -95,6 +97,7 @@ Ndb::init(int aMaxNoOfTransactions)
}
theFirstTransId = ((Uint64)theNdbBlockNumber << 52)+((Uint64)theNode << 40);
+ theFirstTransId += theFacade->m_open_count;
theFacade->unlock_mutex();
@@ -253,8 +256,7 @@ Ndb::abortTransactionsAfterNodeFailure(Uint16 aNodeId)
NdbConnection* localCon = theSentTransactionsArray[i];
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
@@ -300,26 +302,28 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3])
NdbOperation* tOp;
NdbIndexOperation* tIndexOp;
NdbConnection* tCon;
- int tReturnCode;
+ int tReturnCode = -1;
const Uint32* tDataPtr = aSignal->getDataPtr();
const Uint32 tWaitState = theWaiter.m_state;
const Uint32 tSignalNumber = aSignal->readSignalNumber();
const Uint32 tFirstData = *tDataPtr;
+ const Uint32 tLen = aSignal->getLength();
+ void * tFirstDataPtr;
/*
- In order to support 64 bit processes in the application we need to use
- id's rather than a direct pointer to the object used. It is also a good
- idea that one cannot corrupt the application code by sending a corrupt
- memory pointer.
-
- All signals received by the API requires the first data word to be such
- an id to the receiving object.
+ In order to support 64 bit processes in the application we need to use
+ id's rather than a direct pointer to the object used. It is also a good
+ idea that one cannot corrupt the application code by sending a corrupt
+ memory pointer.
+
+ All signals received by the API requires the first data word to be such
+ an id to the receiving object.
*/
-
+
switch (tSignalNumber){
case GSN_TCKEYCONF:
{
- void* tFirstDataPtr = int2void(tFirstData);
+ tFirstDataPtr = int2void(tFirstData);
if (tFirstDataPtr == 0) goto InvalidSignal;
const TcKeyConf * const keyConf = (TcKeyConf *)tDataPtr;
@@ -328,7 +332,7 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3])
tCon = void2con(tFirstDataPtr);
if ((tCon->checkMagicNumber() == 0) &&
(tCon->theSendStatus == NdbConnection::sendTC_OP)) {
- tReturnCode = tCon->receiveTCKEYCONF(keyConf, aSignal->getLength());
+ tReturnCode = tCon->receiveTCKEYCONF(keyConf, tLen);
if (tReturnCode != -1) {
completedTransaction(tCon);
}//if
@@ -346,111 +350,71 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3])
return;
}
- case GSN_READCONF:
- {
- void* tFirstDataPtr = int2void(tFirstData);
- if (tFirstDataPtr == 0) goto InvalidSignal;
-
- tOp = void2rec_op(tFirstDataPtr);
- if (tOp->checkMagicNumber() == 0) {
- tCon = tOp->theNdbCon;
- if (tCon != NULL) {
- if (tCon->theSendStatus == NdbConnection::sendTC_OP) {
- tReturnCode = tOp->receiveREAD_CONF(tDataPtr,
- aSignal->getLength());
- if (tReturnCode != -1) {
- completedTransaction(tCon);
- }//if
- }//if
- }//if
- }//if
+ case GSN_TRANSID_AI:{
+ tFirstDataPtr = int2void(tFirstData);
+ NdbReceiver* tRec;
+ if (tFirstDataPtr && (tRec = void2rec(tFirstDataPtr)) &&
+ tRec->checkMagicNumber() && (tCon = tRec->getTransaction()) &&
+ tCon->checkState_TransId(((const TransIdAI*)tDataPtr)->transId)){
+ Uint32 com;
+ if(aSignal->m_noOfSections > 0){
+ com = tRec->execTRANSID_AI(ptr[0].p, ptr[0].sz);
+ } else {
+ com = tRec->execTRANSID_AI(tDataPtr + TransIdAI::HeaderLength,
+ tLen - TransIdAI::HeaderLength);
+ }
+
+ if(com == 1){
+ switch(tRec->getType()){
+ case NdbReceiver::NDB_OPERATION:
+ case NdbReceiver::NDB_INDEX_OPERATION:
+ if(tCon->OpCompleteSuccess() != -1){
+ completedTransaction(tCon);
+ return;
+ }
+ break;
+ case NdbReceiver::NDB_SCANRECEIVER:
+ tCon->theScanningOp->receiver_delivered(tRec);
+ theWaiter.m_state = (tWaitState == WAIT_SCAN ? NO_WAIT : tWaitState);
+ break;
+ default:
+ goto InvalidSignal;
+ }
+ }
+ break;
+ } else {
+ /**
+ * This is ok as transaction can have been aborted before TRANSID_AI
+ * arrives (if TUP on other node than TC)
+ */
return;
}
- case GSN_TRANSID_AI:
+ }
+ case GSN_TCKEY_FAILCONF:
{
- void* tFirstDataPtr = int2void(tFirstData);
- if (tFirstDataPtr == 0) goto InvalidSignal;
-
- // ndbout << "*** GSN_TRANSID_AI ***" << endl;
- NdbReceiver* tRec = void2rec(tFirstDataPtr);
- if (tRec->getType() == NdbReceiver::NDB_OPERATION){
- // tOp = (NdbOperation*)tRec->getOwner();
+ tFirstDataPtr = int2void(tFirstData);
+ const TcKeyFailConf * failConf = (TcKeyFailConf *)tDataPtr;
+ const BlockReference aTCRef = aSignal->theSendersBlockRef;
+ if (tFirstDataPtr != 0){
tOp = void2rec_op(tFirstDataPtr);
- // ndbout << "NDB_OPERATION" << endl;
- if (tOp->checkMagicNumber() == 0) {
- tCon = tOp->theNdbCon;
- if (tCon != NULL) {
- if (tCon->theSendStatus == NdbConnection::sendTC_OP) {
- tReturnCode = tOp->receiveTRANSID_AI(tDataPtr,
- aSignal->getLength());
- if (tReturnCode != -1) {
- completedTransaction(tCon);
- break;
- }
- }
- }
- }
- } else if (tRec->getType() == NdbReceiver::NDB_INDEX_OPERATION){
- // tOp = (NdbIndexOperation*)tRec->getOwner();
- tOp = void2rec_iop(tFirstDataPtr);
- // ndbout << "NDB_INDEX_OPERATION" << endl;
- if (tOp->checkMagicNumber() == 0) {
+
+ if (tOp->checkMagicNumber(false) == 0) {
tCon = tOp->theNdbCon;
if (tCon != NULL) {
- if (tCon->theSendStatus == NdbConnection::sendTC_OP) {
- tReturnCode = tOp->receiveTRANSID_AI(tDataPtr,
- aSignal->getLength());
+ if ((tCon->theSendStatus == NdbConnection::sendTC_OP) ||
+ (tCon->theSendStatus == NdbConnection::sendTC_COMMIT)) {
+ tReturnCode = tCon->receiveTCKEY_FAILCONF(failConf);
if (tReturnCode != -1) {
completedTransaction(tCon);
- break;
- }
- }
- }
- }
- } else if (tRec->getType() == NdbReceiver::NDB_SCANRECEIVER) {
- // NdbScanReceiver* tScanRec = (NdbScanReceiver*)tRec->getOwner();
- // NdbScanReceiver* tScanRec =
- // (NdbScanReceiver*)(void2rec(tFirstDataPtr)->getOwner());
- NdbScanReceiver* tScanRec = void2rec_srec(tFirstDataPtr);
- // ndbout << "NDB_SCANRECEIVER" << endl;
- if(tScanRec->checkMagicNumber() == 0){
- tReturnCode = tScanRec->receiveTRANSID_AI_SCAN(aSignal);
- if (tReturnCode != -1) {
- theWaiter.m_state = NO_WAIT;
- break;
+ }//if
+ }//if
}
}
} else {
-#ifdef NDB_NO_DROPPED_SIGNAL
- abort();
+#ifdef VM_TRACE
+ ndbout_c("Recevied TCKEY_FAILCONF wo/ operation");
#endif
- goto InvalidSignal;
}
- return;
- }
- case GSN_TCKEY_FAILCONF:
- {
- void* tFirstDataPtr = int2void(tFirstData);
- if (tFirstDataPtr == 0) goto InvalidSignal;
-
- const TcKeyFailConf * const failConf = (TcKeyFailConf *)tDataPtr;
- const BlockReference aTCRef = aSignal->theSendersBlockRef;
-
- tOp = void2rec_op(tFirstDataPtr);
-
- if (tOp->checkMagicNumber() == 0) {
- tCon = tOp->theNdbCon;
- if (tCon != NULL) {
- if ((tCon->theSendStatus == NdbConnection::sendTC_OP) ||
- (tCon->theSendStatus == NdbConnection::sendTC_COMMIT)) {
- tReturnCode = tCon->receiveTCKEY_FAILCONF(failConf);
- if (tReturnCode != -1) {
- completedTransaction(tCon);
- }//if
- }//if
- }//if
- }//if
-
if(tFirstData & 1){
NdbConnection::sendTC_COMMIT_ACK(theCommitAckSignal,
failConf->transId1,
@@ -461,28 +425,32 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3])
}
case GSN_TCKEY_FAILREF:
{
- void* tFirstDataPtr = int2void(tFirstData);
- if (tFirstDataPtr == 0) goto InvalidSignal;
-
- tOp = void2rec_op(tFirstDataPtr);
- if (tOp->checkMagicNumber() == 0) {
- tCon = tOp->theNdbCon;
- if (tCon != NULL) {
- if ((tCon->theSendStatus == NdbConnection::sendTC_OP) ||
- (tCon->theSendStatus == NdbConnection::sendTC_ROLLBACK)) {
- tReturnCode = tCon->receiveTCKEY_FAILREF(aSignal);
- if (tReturnCode != -1) {
- completedTransaction(tCon);
- return;
- }//if
- }//if
- }//if
- }//if
- return;
+ tFirstDataPtr = int2void(tFirstData);
+ if(tFirstDataPtr != 0){
+ tOp = void2rec_op(tFirstDataPtr);
+ if (tOp->checkMagicNumber() == 0) {
+ tCon = tOp->theNdbCon;
+ if (tCon != NULL) {
+ if ((tCon->theSendStatus == NdbConnection::sendTC_OP) ||
+ (tCon->theSendStatus == NdbConnection::sendTC_ROLLBACK)) {
+ tReturnCode = tCon->receiveTCKEY_FAILREF(aSignal);
+ if (tReturnCode != -1) {
+ completedTransaction(tCon);
+ return;
+ }//if
+ }//if
+ }//if
+ }//if
+ } else {
+#ifdef VM_TRACE
+ ndbout_c("Recevied TCKEY_FAILREF wo/ operation");
+#endif
+ }
+ break;
}
case GSN_TCKEYREF:
{
- void* tFirstDataPtr = int2void(tFirstData);
+ tFirstDataPtr = int2void(tFirstData);
if (tFirstDataPtr == 0) goto InvalidSignal;
tOp = void2rec_op(tFirstDataPtr);
@@ -493,8 +461,9 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3])
tReturnCode = tOp->receiveTCKEYREF(aSignal);
if (tReturnCode != -1) {
completedTransaction(tCon);
+ return;
}//if
- return;
+ break;
}//if
}//if
} //if
@@ -503,7 +472,7 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3])
}
case GSN_TC_COMMITCONF:
{
- void* tFirstDataPtr = int2void(tFirstData);
+ tFirstDataPtr = int2void(tFirstData);
if (tFirstDataPtr == 0) goto InvalidSignal;
const TcCommitConf * const commitConf = (TcCommitConf *)tDataPtr;
@@ -531,7 +500,7 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3])
case GSN_TC_COMMITREF:
{
- void* tFirstDataPtr = int2void(tFirstData);
+ tFirstDataPtr = int2void(tFirstData);
if (tFirstDataPtr == 0) goto InvalidSignal;
tCon = void2con(tFirstDataPtr);
@@ -540,14 +509,13 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3])
tReturnCode = tCon->receiveTC_COMMITREF(aSignal);
if (tReturnCode != -1) {
completedTransaction(tCon);
- return;
}//if
}//if
return;
}
case GSN_TCROLLBACKCONF:
{
- void* tFirstDataPtr = int2void(tFirstData);
+ tFirstDataPtr = int2void(tFirstData);
if (tFirstDataPtr == 0) goto InvalidSignal;
tCon = void2con(tFirstDataPtr);
@@ -562,7 +530,7 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3])
}
case GSN_TCROLLBACKREF:
{
- void* tFirstDataPtr = int2void(tFirstData);
+ tFirstDataPtr = int2void(tFirstData);
if (tFirstDataPtr == 0) goto InvalidSignal;
tCon = void2con(tFirstDataPtr);
@@ -571,14 +539,13 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3])
tReturnCode = tCon->receiveTCROLLBACKREF(aSignal);
if (tReturnCode != -1) {
completedTransaction(tCon);
- return;
}//if
}//if
return;
}
case GSN_TCROLLBACKREP:
{
- void* tFirstDataPtr = int2void(tFirstData);
+ tFirstDataPtr = int2void(tFirstData);
if (tFirstDataPtr == 0) goto InvalidSignal;
tCon = void2con(tFirstDataPtr);
@@ -592,27 +559,27 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3])
}
case GSN_TCSEIZECONF:
{
- void* tFirstDataPtr = int2void(tFirstData);
+ tFirstDataPtr = int2void(tFirstData);
if (tFirstDataPtr == 0) goto InvalidSignal;
if (tWaitState != WAIT_TC_SEIZE) {
- return;
+ goto InvalidSignal;
}//if
tCon = void2con(tFirstDataPtr);
if (tCon->checkMagicNumber() != 0) {
- return;
+ goto InvalidSignal;
}//if
tReturnCode = tCon->receiveTCSEIZECONF(aSignal);
if (tReturnCode != -1) {
theWaiter.m_state = NO_WAIT;
} else {
- return;
+ goto InvalidSignal;
}//if
break;
}
case GSN_TCSEIZEREF:
{
- void* tFirstDataPtr = int2void(tFirstData);
+ tFirstDataPtr = int2void(tFirstData);
if (tFirstDataPtr == 0) goto InvalidSignal;
if (tWaitState != WAIT_TC_SEIZE) {
@@ -632,7 +599,7 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3])
}
case GSN_TCRELEASECONF:
{
- void* tFirstDataPtr = int2void(tFirstData);
+ tFirstDataPtr = int2void(tFirstData);
if (tFirstDataPtr == 0) goto InvalidSignal;
if (tWaitState != WAIT_TC_RELEASE) {
@@ -650,7 +617,7 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3])
}
case GSN_TCRELEASEREF:
{
- void* tFirstDataPtr = int2void(tFirstData);
+ tFirstDataPtr = int2void(tFirstData);
if (tFirstDataPtr == 0) goto InvalidSignal;
if (tWaitState != WAIT_TC_RELEASE) {
@@ -704,84 +671,100 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3])
case GSN_DIHNDBTAMPER:
{
- void* tFirstDataPtr = int2void(tFirstData);
- if (tFirstDataPtr == 0) goto InvalidSignal;
-
- if (tWaitState != WAIT_NDB_TAMPER)
- return;
- tCon = void2con(tFirstDataPtr);
- if (tCon->checkMagicNumber() != 0)
- return;
- tReturnCode = tCon->receiveDIHNDBTAMPER(aSignal);
- if (tReturnCode != -1)
- theWaiter.m_state = NO_WAIT;
- break;
+ tFirstDataPtr = int2void(tFirstData);
+ if (tFirstDataPtr == 0) goto InvalidSignal;
+
+ if (tWaitState != WAIT_NDB_TAMPER)
+ return;
+ tCon = void2con(tFirstDataPtr);
+ if (tCon->checkMagicNumber() != 0)
+ return;
+ tReturnCode = tCon->receiveDIHNDBTAMPER(aSignal);
+ if (tReturnCode != -1)
+ theWaiter.m_state = NO_WAIT;
+ break;
}
case GSN_SCAN_TABCONF:
{
- void* tFirstDataPtr = int2void(tFirstData);
- if (tFirstDataPtr == 0) goto InvalidSignal;
-
- //ndbout << "*** GSN_SCAN_TABCONF *** " << endl;
- if (tWaitState != WAIT_SCAN){
- return;
- }
- tCon = void2con(tFirstDataPtr);
- if (tCon->checkMagicNumber() != 0)
- return;
- tReturnCode = tCon->receiveSCAN_TABCONF(aSignal);
- if (tReturnCode != -1)
- theWaiter.m_state = NO_WAIT;
- break;
+ tFirstDataPtr = int2void(tFirstData);
+ assert(tFirstDataPtr);
+ assert(void2con(tFirstDataPtr));
+ assert(void2con(tFirstDataPtr)->checkMagicNumber() == 0);
+ if(tFirstDataPtr &&
+ (tCon = void2con(tFirstDataPtr)) && (tCon->checkMagicNumber() == 0)){
+
+ if(aSignal->m_noOfSections > 0){
+ tReturnCode = tCon->receiveSCAN_TABCONF(aSignal,
+ ptr[0].p, ptr[0].sz);
+ } else {
+ tReturnCode =
+ tCon->receiveSCAN_TABCONF(aSignal,
+ tDataPtr + ScanTabConf::SignalLength,
+ tLen - ScanTabConf::SignalLength);
+ }
+ if (tReturnCode != -1 && tWaitState == WAIT_SCAN)
+ theWaiter.m_state = NO_WAIT;
+ break;
+ } else {
+ goto InvalidSignal;
+ }
}
case GSN_SCAN_TABREF:
{
- void* tFirstDataPtr = int2void(tFirstData);
- if (tFirstDataPtr == 0) goto InvalidSignal;
-
- if (tWaitState == WAIT_SCAN){
+ tFirstDataPtr = int2void(tFirstData);
+ if (tFirstDataPtr == 0) goto InvalidSignal;
+
tCon = void2con(tFirstDataPtr);
+
+ assert(tFirstDataPtr != 0 &&
+ void2con(tFirstDataPtr)->checkMagicNumber() == 0);
+
if (tCon->checkMagicNumber() == 0){
tReturnCode = tCon->receiveSCAN_TABREF(aSignal);
- if (tReturnCode != -1){
+ if (tReturnCode != -1 && tWaitState == WAIT_SCAN){
theWaiter.m_state = NO_WAIT;
}
break;
}
- }
- goto InvalidSignal;
- }
- case GSN_SCAN_TABINFO:
- {
- void* tFirstDataPtr = int2void(tFirstData);
- if (tFirstDataPtr == 0) goto InvalidSignal;
-
- //ndbout << "*** GSN_SCAN_TABINFO ***" << endl;
- if (tWaitState != WAIT_SCAN)
- return;
- tCon = void2con(tFirstDataPtr);
- if (tCon->checkMagicNumber() != 0)
- return;
- tReturnCode = tCon->receiveSCAN_TABINFO(aSignal);
- if (tReturnCode != -1)
- theWaiter.m_state = NO_WAIT;
- break;
+ goto InvalidSignal;
}
case GSN_KEYINFO20: {
- void* tFirstDataPtr = int2void(tFirstData);
- if (tFirstDataPtr == 0) goto InvalidSignal;
-
- //ndbout << "*** GSN_KEYINFO20 ***" << endl;
- NdbScanReceiver* tScanRec = void2rec_srec(tFirstDataPtr);
- if (tScanRec->checkMagicNumber() != 0)
+ tFirstDataPtr = int2void(tFirstData);
+ NdbReceiver* tRec;
+ if (tFirstDataPtr && (tRec = void2rec(tFirstDataPtr)) &&
+ tRec->checkMagicNumber() && (tCon = tRec->getTransaction()) &&
+ tCon->checkState_TransId(&((const KeyInfo20*)tDataPtr)->transId1)){
+
+ Uint32 len = ((const KeyInfo20*)tDataPtr)->keyLen;
+ Uint32 info = ((const KeyInfo20*)tDataPtr)->scanInfo_Node;
+ int com = -1;
+ if(aSignal->m_noOfSections > 0 && len == ptr[0].sz){
+ com = tRec->execKEYINFO20(info, ptr[0].p, len);
+ } else if(len == tLen - KeyInfo20::HeaderLength){
+ com = tRec->execKEYINFO20(info, tDataPtr+KeyInfo20::HeaderLength, len);
+ }
+
+ switch(com){
+ case 1:
+ tCon->theScanningOp->receiver_delivered(tRec);
+ theWaiter.m_state = (tWaitState == WAIT_SCAN ? NO_WAIT : tWaitState);
+ break;
+ case 0:
+ break;
+ case -1:
+ goto InvalidSignal;
+ }
+ break;
+ } else {
+ /**
+ * This is ok as transaction can have been aborted before KEYINFO20
+ * arrives (if TUP on other node than TC)
+ */
return;
- tReturnCode = tScanRec->receiveKEYINFO20(aSignal);
- if (tReturnCode != -1)
- theWaiter.m_state = NO_WAIT;
- break;
+ }
}
case GSN_TCINDXCONF:{
- void* tFirstDataPtr = int2void(tFirstData);
+ tFirstDataPtr = int2void(tFirstData);
if (tFirstDataPtr == 0) goto InvalidSignal;
const TcIndxConf * const indxConf = (TcIndxConf *)tDataPtr;
@@ -789,7 +772,7 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3])
tCon = void2con(tFirstDataPtr);
if ((tCon->checkMagicNumber() == 0) &&
(tCon->theSendStatus == NdbConnection::sendTC_OP)) {
- tReturnCode = tCon->receiveTCINDXCONF(indxConf, aSignal->getLength());
+ tReturnCode = tCon->receiveTCINDXCONF(indxConf, tLen);
if (tReturnCode != -1) {
completedTransaction(tCon);
}//if
@@ -801,10 +784,10 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3])
indxConf->transId2,
aTCRef);
}
- break;
+ return;
}
case GSN_TCINDXREF:{
- void* tFirstDataPtr = int2void(tFirstData);
+ tFirstDataPtr = int2void(tFirstData);
if (tFirstDataPtr == 0) goto InvalidSignal;
tIndexOp = void2rec_iop(tFirstDataPtr);
@@ -865,8 +848,7 @@ Ndb::completedTransaction(NdbConnection* aCon)
Uint32 tTransArrayIndex = aCon->theTransArrayIndex;
Uint32 tNoSentTransactions = theNoOfSentTransactions;
Uint32 tNoCompletedTransactions = theNoOfCompletedTransactions;
- if ((tNoSentTransactions > 0) &&
- (aCon->theListState == NdbConnection::InSendList) &&
+ if ((tNoSentTransactions > 0) && (aCon->theListState == NdbConnection::InSendList) &&
(tTransArrayIndex < tNoSentTransactions)) {
NdbConnection* tMoveCon = theSentTransactionsArray[tNoSentTransactions - 1];
@@ -895,8 +877,8 @@ Ndb::completedTransaction(NdbConnection* aCon)
ndbout << endl << flush;
#ifdef VM_TRACE
printState("completedTransaction abort");
-#endif
abort();
+#endif
}//if
}//Ndb::completedTransaction()
@@ -965,6 +947,10 @@ Ndb::check_send_timeout()
WAITFOR_RESPONSE_TIMEOUT) {
#ifdef VM_TRACE
a_con->printState();
+ Uint32 t1 = a_con->theTransactionId;
+ Uint32 t2 = a_con->theTransactionId >> 32;
+ ndbout_c("[%.8x %.8x]", t1, t2);
+ abort();
#endif
a_con->setOperationErrorCodeAbort(4012);
a_con->theCommitStatus = NdbConnection::Aborted;
@@ -1255,8 +1241,7 @@ Return: 0 - Response received
******************************************************************************/
int
-Ndb::receiveResponse(int waitTime)
-{
+Ndb::receiveResponse(int waitTime){
int tResultCode;
TransporterFacade::instance()->checkForceSend(theNdbBlockNumber);
@@ -1310,10 +1295,10 @@ Ndb::sendRecSignal(Uint16 node_id,
if (return_code != -1) {
theWaiter.m_node = node_id;
theWaiter.m_state = aWaitState;
- return receiveResponse();
- // End of protected area
- }//if
- return_code = -3;
+ return_code = receiveResponse();
+ } else {
+ return_code = -3;
+ }
} else {
return_code = -4;
}//if
@@ -1335,8 +1320,8 @@ void
NdbConnection::sendTC_COMMIT_ACK(NdbApiSignal * aSignal,
Uint32 transId1, Uint32 transId2,
Uint32 aTCRef){
-#if 0
- ndbout_c("Sending TC_COMMIT_ACK(0x%x, 0x%x) to -> %d",
+#ifdef MARKER_TRACE
+ ndbout_c("Sending TC_COMMIT_ACK(0x%.8x, 0x%.8x) to -> %d",
transId1,
transId2,
refToNode(aTCRef));
diff --git a/ndb/src/ndbapi/Ndbinit.cpp b/ndb/src/ndbapi/Ndbinit.cpp
index f451ba885d4..be168ddffbe 100644
--- a/ndb/src/ndbapi/Ndbinit.cpp
+++ b/ndb/src/ndbapi/Ndbinit.cpp
@@ -43,7 +43,7 @@ static int theNoOfNdbObjects = 0;
static char *ndbConnectString = 0;
-#ifdef NDB_WIN32
+#if defined NDB_WIN32 || defined SCO
static NdbMutex & createNdbMutex = * NdbMutex_Create();
#else
static NdbMutex createNdbMutex = NDB_MUTEX_INITIALIZER;
@@ -111,12 +111,13 @@ Ndb::Ndb( const char* aDataBase , const char* aSchema) :
theCurrentConnectCounter = 1;
theCurrentConnectIndex = 0;
- for (int i = 0; i < MAX_NDB_NODES ; i++) {
+ int i;
+ for (i = 0; i < MAX_NDB_NODES ; i++) {
theConnectionArray[i] = NULL;
the_release_ind[i] = 0;
theDBnodes[i] = 0;
}//forg
- for (int i = 0; i < 2048 ; i++) {
+ for (i = 0; i < 2048 ; i++) {
theFirstTupleId[i] = 0;
theLastTupleId[i] = 0;
}//for
diff --git a/ndb/src/ndbapi/Ndblist.cpp b/ndb/src/ndbapi/Ndblist.cpp
index e557fdc0a5f..1e1cb5e4b40 100644
--- a/ndb/src/ndbapi/Ndblist.cpp
+++ b/ndb/src/ndbapi/Ndblist.cpp
@@ -15,16 +15,13 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include <NdbOut.hpp>
-#include "Ndb.hpp"
-//#include "NdbSchemaOp.hpp"
-//#include "NdbSchemaCon.hpp"
-#include "NdbOperation.hpp"
-#include "NdbScanOperation.hpp"
-#include "NdbIndexOperation.hpp"
-#include "NdbConnection.hpp"
+#include <Ndb.hpp>
+#include <NdbOperation.hpp>
+#include <NdbIndexOperation.hpp>
+#include <NdbIndexScanOperation.hpp>
+#include <NdbConnection.hpp>
#include "NdbApiSignal.hpp"
-#include "NdbRecAttr.hpp"
-#include "NdbScanReceiver.hpp"
+#include <NdbRecAttr.hpp>
#include "NdbUtil.hpp"
#include "API.hpp"
#include "NdbBlob.hpp"
@@ -264,13 +261,13 @@ Ndb::getNdbLabel()
* Remark: Get a NdbScanReceiver from theScanRecList and return the
* object .
****************************************************************************/
-NdbScanReceiver*
+NdbReceiver*
Ndb::getNdbScanRec()
{
- NdbScanReceiver* tNdbScanRec;
+ NdbReceiver* tNdbScanRec;
if ( theScanList == NULL )
{
- tNdbScanRec = new NdbScanReceiver(this);
+ tNdbScanRec = new NdbReceiver(this);
if (tNdbScanRec == NULL)
{
return NULL;
@@ -345,17 +342,17 @@ Return Value: Return theOpList : if the getScanOperation was succesful.
Return NULL : In all other case.
Remark: Get an operation from theScanOpIdleList and return the object .
***************************************************************************/
-NdbScanOperation*
+NdbIndexScanOperation*
Ndb::getScanOperation()
{
- NdbScanOperation* tOp = theScanOpIdleList;
+ NdbIndexScanOperation* tOp = theScanOpIdleList;
if (tOp != NULL ) {
- NdbScanOperation* tOpNext = (NdbScanOperation*) tOp->next();
+ NdbIndexScanOperation* tOpNext = (NdbIndexScanOperation*)tOp->next();
tOp->next(NULL);
theScanOpIdleList = tOpNext;
return tOp;
} else {
- tOp = new NdbScanOperation(this);
+ tOp = new NdbIndexScanOperation(this);
if (tOp != NULL)
tOp->next(NULL);
}
@@ -509,7 +506,7 @@ Parameters: aNdbScanRec: The NdbScanReceiver object.
Remark: Add a NdbScanReceiver object into the Scan idlelist.
***************************************************************************/
void
-Ndb::releaseNdbScanRec(NdbScanReceiver* aNdbScanRec)
+Ndb::releaseNdbScanRec(NdbReceiver* aNdbScanRec)
{
aNdbScanRec->next(theScanList);
theScanList = aNdbScanRec;
@@ -558,12 +555,12 @@ Parameters: aScanOperation : The released NdbScanOperation object.
Remark: Add a NdbScanOperation object into the signal idlelist.
***************************************************************************/
void
-Ndb::releaseScanOperation(NdbScanOperation* aScanOperation)
+Ndb::releaseScanOperation(NdbIndexScanOperation* aScanOperation)
{
aScanOperation->next(theScanOpIdleList);
aScanOperation->theNdbCon = NULL;
aScanOperation->theMagicNumber = 0xFE11D2;
- theScanOpIdleList = (NdbScanOperation*)aScanOperation;
+ theScanOpIdleList = aScanOperation;
}
/***************************************************************************
@@ -592,7 +589,7 @@ Ndb::releaseSignal(NdbApiSignal* aSignal)
#if defined VM_TRACE
// Check that signal is not null
assert(aSignal != NULL);
-
+#if 0
// Check that signal is not already in list
NdbApiSignal* tmp = theSignalIdleList;
while (tmp != NULL){
@@ -600,6 +597,7 @@ Ndb::releaseSignal(NdbApiSignal* aSignal)
tmp = tmp->next();
}
#endif
+#endif
creleaseSignals++;
aSignal->next(theSignalIdleList);
theSignalIdleList = aSignal;
@@ -645,7 +643,7 @@ void
Ndb::freeScanOperation()
{
NdbScanOperation* tOp = theScanOpIdleList;
- theScanOpIdleList = (NdbScanOperation *) theScanOpIdleList->next();
+ theScanOpIdleList = (NdbIndexScanOperation *) theScanOpIdleList->next();
delete tOp;
}
@@ -696,7 +694,7 @@ Remark: Always release the first item in the free list
void
Ndb::freeNdbScanRec()
{
- NdbScanReceiver* tNdbScanRec = theScanList;
+ NdbReceiver* tNdbScanRec = theScanList;
theScanList = theScanList->next();
delete tNdbScanRec;
}
diff --git a/ndb/src/ndbapi/ObjectMap.hpp b/ndb/src/ndbapi/ObjectMap.hpp
index 4abb54b5081..f67774bb413 100644
--- a/ndb/src/ndbapi/ObjectMap.hpp
+++ b/ndb/src/ndbapi/ObjectMap.hpp
@@ -93,26 +93,28 @@ inline
void *
NdbObjectIdMap::unmap(Uint32 id, void *object){
- int i = id>>2;
+ Uint32 i = id>>2;
// lock();
-
- void * obj = m_map[i].m_obj;
- if (object == obj) {
- m_map[i].m_next = m_firstFree;
- m_firstFree = i;
- } else {
- ndbout_c("Error: NdbObjectIdMap::::unmap(%u, 0x%x) obj=0x%x", id, object, obj);
- return 0;
- }
-
- // unlock();
-
+ if(i < m_size){
+ void * obj = m_map[i].m_obj;
+ if (object == obj) {
+ m_map[i].m_next = m_firstFree;
+ m_firstFree = i;
+ } else {
+ ndbout_c("Error: NdbObjectIdMap::::unmap(%u, 0x%x) obj=0x%x", id, object, obj);
+ return 0;
+ }
+
+ // unlock();
+
#ifdef DEBUG_OBJECTMAP
- ndbout_c("NdbObjectIdMap::unmap(%u) obj=0x%x", id, obj);
+ ndbout_c("NdbObjectIdMap::unmap(%u) obj=0x%x", id, obj);
#endif
-
- return obj;
+
+ return obj;
+ }
+ return 0;
}
inline void *
@@ -120,7 +122,11 @@ NdbObjectIdMap::getObject(Uint32 id){
#ifdef DEBUG_OBJECTMAP
ndbout_c("NdbObjectIdMap::getObject(%u) obj=0x%x", id, m_map[id>>2].m_obj);
#endif
- return m_map[id>>2].m_obj;
+ id >>= 2;
+ if(id < m_size){
+ return m_map[id].m_obj;
+ }
+ return 0;
}
inline void
@@ -129,7 +135,6 @@ NdbObjectIdMap::expand(Uint32 incSize){
MapEntry * tmp = (MapEntry*)malloc(newSize * sizeof(MapEntry));
memcpy(tmp, m_map, m_size * sizeof(MapEntry));
- free(m_map);
m_map = tmp;
for(Uint32 i = m_size; i<newSize; i++){
diff --git a/ndb/src/ndbapi/ScanOperation.txt b/ndb/src/ndbapi/ScanOperation.txt
index 7197cf66f7e..27e4e8c1755 100644
--- a/ndb/src/ndbapi/ScanOperation.txt
+++ b/ndb/src/ndbapi/ScanOperation.txt
@@ -8,3 +8,49 @@ theNdbCon -> z
z) NdbConnection (scan)
theScanningOp -> y
theFirstOpInList -> y (until after openScan)
+
+# SU
+
+ScanOpLen: includes KeyInfo
+New protocol
+
+# -- Impl.
+
+1) Scan uses one NdbReceiver per "parallelism"
+2) Each NdbReceiver can handle up to "batch size" rows
+3) API send one "pointer" per parallelism (prev. was one per row)
+4) API handles each receiver independently.
+ It can "nextResult"-one, receive one and close-one
+5) When a recevier has been "nextResult"-ed, the API can fetch from it again
+6) After doing "openScan"-req, no wait is performed
+ (only possible to block on nextResult(true) or closeScan)
+
+7) Instead of "ack"-ing each row with length,
+* Each row is sent in one lonw signal (unless to short)
+* Each NdbReceiver is ack-ed with #rows and sum(#length)
+* KeyInfo20 is one signal and included in sum(#length)
+
+8) The API receive(s) the data into NdbRecAttr-objects
+ (prev. it copied signals using new/delete)
+9) KeyInfo20 is also received into a NdbRecAttr-object
+10)
+
+# -- Close of scan
+
+1) Each NdbReciver gets a signal when it's complete
+ (0 rows is ack-ed)
+2) The API then "closes" this receiver
+3) The API can at any time close then scan for other reason(s)
+ (example dying)
+4) This is signal:ed via a NEXT_SCANREQ (close = 1)
+5) TC responds with a SCAN_TABCONF (close = 1)
+
+
+# -- Sorted
+
+1) The sorted scan is transparent to TC
+ It's a API only impl.
+2) The API makes the following adjustements:
+* Scan all fragments simultaniously (max parallelism)
+* Never return a row to the API if a NdbReciver is "outstanding"
+* Sort Receivers (only top row as they already are sorted within)
diff --git a/ndb/src/ndbapi/TransporterFacade.cpp b/ndb/src/ndbapi/TransporterFacade.cpp
index e725144a8f8..7ec9a6a55a3 100644
--- a/ndb/src/ndbapi/TransporterFacade.cpp
+++ b/ndb/src/ndbapi/TransporterFacade.cpp
@@ -34,11 +34,8 @@
#include <ndb_version.h>
#include <SignalLoggerManager.hpp>
-#if !defined NDB_OSE && !defined NDB_SOFTOSE
-#include <signal.h>
-#endif
-
//#define REPORT_TRANSPORTER
+//#define API_TRACE;
#if defined DEBUG_TRANSPORTER
#define TRP_DEBUG(t) ndbout << __FILE__ << ":" << __LINE__ << ":" << t << endl;
@@ -47,7 +44,7 @@
#endif
TransporterFacade* TransporterFacade::theFacadeInstance = NULL;
-
+ConfigRetriever *TransporterFacade::s_config_retriever= 0;
/*****************************************************************************
@@ -160,14 +157,12 @@ setSignalLog(){
}
return false;
}
+#ifdef TRACE_APIREGREQ
+#define TRACE_GSN(gsn) true
+#else
+#define TRACE_GSN(gsn) (gsn != GSN_API_REGREQ && gsn != GSN_API_REGCONF)
+#endif
#endif
-
-// These symbols are needed, but not used in the API
-int g_sectionSegmentPool;
-struct ErrorReporter {
- void handleAssert(const char*, const char*, int);
-};
-void ErrorReporter::handleAssert(const char* message, const char* file, int line) {}
/**
* The execute function : Handle received signal
@@ -182,9 +177,7 @@ execute(void * callbackObj, SignalHeader * const header,
Uint32 tRecBlockNo = header->theReceiversBlockNumber;
#ifdef API_TRACE
- if(setSignalLog()){
- // header->theVerId_signalNumber != GSN_API_REGREQ &&
- // header->theVerId_signalNumber != GSN_API_REGCONF){
+ if(setSignalLog() && TRACE_GSN(header->theVerId_signalNumber)){
signalLogger.executeSignal(* header,
prio,
theData,
@@ -314,6 +307,14 @@ execute(void * callbackObj, SignalHeader * const header,
}
}
+// These symbols are needed, but not used in the API
+void
+SignalLoggerManager::printSegmentedSection(FILE *, const SignalHeader &,
+ const SegmentedSectionPtr ptr[3],
+ unsigned i){
+ abort();
+}
+
void
copy(Uint32 * & insertPtr,
class SectionSegmentPool & thePool, const SegmentedSectionPtr & _ptr){
@@ -332,29 +333,48 @@ atexit_stop_instance(){
*
* Which is protected by a mutex
*/
+
+
TransporterFacade*
TransporterFacade::start_instance(const char * connectString){
// TransporterFacade used from API get config from mgmt srvr
- ConfigRetriever configRetriever;
- configRetriever.setConnectString(connectString);
- ndb_mgm_configuration * props = configRetriever.getConfig(NDB_VERSION,
- NODE_TYPE_API);
- if (props == 0) {
- ndbout << "Configuration error: ";
- const char* erString = configRetriever.getErrorString();
- if (erString == 0) {
- erString = "No error specified!";
+ s_config_retriever= new ConfigRetriever(NDB_VERSION, NODE_TYPE_API);
+
+ s_config_retriever->setConnectString(connectString);
+ const char* error = 0;
+ do {
+ if(s_config_retriever->init() == -1)
+ break;
+
+ if(s_config_retriever->do_connect() == -1)
+ break;
+
+ Uint32 nodeId = s_config_retriever->allocNodeId();
+ for(Uint32 i = 0; nodeId == 0 && i<5; i++){
+ NdbSleep_SecSleep(3);
+ nodeId = s_config_retriever->allocNodeId();
}
- ndbout << erString << endl;
- return 0;
- }
- const int nodeId = configRetriever.getOwnNodeId();
-
- TransporterFacade * tf = start_instance(nodeId, props);
+ if(nodeId == 0)
+ break;
+
+ ndb_mgm_configuration * props = s_config_retriever->getConfig();
+ if(props == 0)
+ break;
+
+ TransporterFacade * tf = start_instance(nodeId, props);
+
+ free(props);
+ return tf;
+ } while(0);
- free(props);
- return tf;
+ ndbout << "Configuration error: ";
+ const char* erString = s_config_retriever->getErrorString();
+ if (erString == 0) {
+ erString = "No error specified!";
+ }
+ ndbout << erString << endl;
+ return 0;
}
TransporterFacade*
@@ -389,6 +409,14 @@ TransporterFacade::start_instance(int nodeId,
return tf;
}
+void
+TransporterFacade::close_configuration(){
+ if (s_config_retriever) {
+ delete s_config_retriever;
+ s_config_retriever= 0;
+ }
+}
+
/**
* Note that this function need no locking since its
* only called from the destructor of Ndb (the NdbObject)
@@ -397,6 +425,9 @@ TransporterFacade::start_instance(int nodeId,
*/
void
TransporterFacade::stop_instance(){
+
+ close_configuration();
+
if(theFacadeInstance == NULL){
/**
* We are called from atexit function
@@ -440,7 +471,21 @@ runSendRequest_C(void * me)
void TransporterFacade::threadMainSend(void)
{
+ SocketServer socket_server;
+
theTransporterRegistry->startSending();
+ if (!theTransporterRegistry->start_service(socket_server)){
+ ndbout_c("Unable to start theTransporterRegistry->start_service");
+ exit(0);
+ }
+
+ if (!theTransporterRegistry->start_clients()){
+ ndbout_c("Unable to start theTransporterRegistry->start_clients");
+ exit(0);
+ }
+
+ socket_server.startServer();
+
while(!theStopReceive) {
NdbSleep_MilliSleep(10);
NdbMutex_Lock(theMutexPtr);
@@ -451,6 +496,11 @@ void TransporterFacade::threadMainSend(void)
NdbMutex_Unlock(theMutexPtr);
}
theTransporterRegistry->stopSending();
+
+ socket_server.stopServer();
+ socket_server.stopSessions();
+
+ theTransporterRegistry->stop_clients();
}
extern "C"
@@ -466,7 +516,7 @@ void TransporterFacade::threadMainReceive(void)
{
theTransporterRegistry->startReceiving();
NdbMutex_Lock(theMutexPtr);
- theTransporterRegistry->checkConnections();
+ theTransporterRegistry->update_connections();
NdbMutex_Unlock(theMutexPtr);
while(!theStopReceive) {
for(int i = 0; i<10; i++){
@@ -478,7 +528,7 @@ void TransporterFacade::threadMainReceive(void)
}
}
NdbMutex_Lock(theMutexPtr);
- theTransporterRegistry->checkConnections();
+ theTransporterRegistry->update_connections();
NdbMutex_Unlock(theMutexPtr);
}//while
theTransporterRegistry->stopReceiving();
@@ -498,6 +548,7 @@ TransporterFacade::TransporterFacade() :
theClusterMgr = NULL;
theArbitMgr = NULL;
theStartNodeId = 1;
+ m_open_count = 0;
}
bool
@@ -652,6 +703,7 @@ TransporterFacade::open(void* objRef,
ExecuteFunction fun,
NodeStatusFunction statusFun)
{
+ m_open_count++;
return m_threads.open(objRef, fun, statusFun);
}
@@ -732,8 +784,7 @@ TransporterFacade::checkForceSend(Uint32 block_number) {
/******************************************************************************
* SEND SIGNAL METHODS
- ******************************************************************************/
-
+ *****************************************************************************/
int
TransporterFacade::sendSignal(NdbApiSignal * aSignal, NodeId aNode){
Uint32* tDataPtr = aSignal->getDataPtrSend();
@@ -741,9 +792,7 @@ TransporterFacade::sendSignal(NdbApiSignal * aSignal, NodeId aNode){
Uint32 TBno = aSignal->theReceiversBlockNumber;
if(getIsNodeSendable(aNode) == true){
#ifdef API_TRACE
- if(setSignalLog()){
- // aSignal->theVerId_signalNumber != GSN_API_REGREQ &&
- // aSignal->theVerId_signalNumber != GSN_API_REGCONF){
+ if(setSignalLog() && TRACE_GSN(aSignal->theVerId_signalNumber)){
Uint32 tmp = aSignal->theSendersBlockRef;
aSignal->theSendersBlockRef = numberToRef(tmp, theOwnId);
LinearSectionPtr ptr[3];
@@ -777,9 +826,7 @@ TransporterFacade::sendSignal(NdbApiSignal * aSignal, NodeId aNode){
int
TransporterFacade::sendSignalUnCond(NdbApiSignal * aSignal, NodeId aNode){
#ifdef API_TRACE
- if(setSignalLog()){
- //aSignal->theVerId_signalNumber != GSN_API_REGREQ &&
- //aSignal->theVerId_signalNumber != GSN_API_REGCONF
+ if(setSignalLog() && TRACE_GSN(aSignal->theVerId_signalNumber)){
Uint32 tmp = aSignal->theSendersBlockRef;
aSignal->theSendersBlockRef = numberToRef(tmp, theOwnId);
LinearSectionPtr ptr[3];
@@ -809,7 +856,7 @@ TransporterFacade::sendFragmentedSignal(NdbApiSignal* aSignal, NodeId aNode,
aSignal->m_noOfSections = secs;
if(getIsNodeSendable(aNode) == true){
#ifdef API_TRACE
- if(setSignalLog()){
+ if(setSignalLog() && TRACE_GSN(aSignal->theVerId_signalNumber)){
Uint32 tmp = aSignal->theSendersBlockRef;
aSignal->theSendersBlockRef = numberToRef(tmp, theOwnId);
signalLogger.sendSignal(* aSignal,
@@ -845,7 +892,7 @@ TransporterFacade::sendFragmentedSignalUnCond(NdbApiSignal* aSignal,
aSignal->m_noOfSections = secs;
#ifdef API_TRACE
- if(setSignalLog()){
+ if(setSignalLog() && TRACE_GSN(aSignal->theVerId_signalNumber)){
Uint32 tmp = aSignal->theSendersBlockRef;
aSignal->theSendersBlockRef = numberToRef(tmp, theOwnId);
signalLogger.sendSignal(* aSignal,
@@ -875,13 +922,13 @@ TransporterFacade::sendFragmentedSignalUnCond(NdbApiSignal* aSignal,
void
TransporterFacade::doConnect(int aNodeId){
theTransporterRegistry->setIOState(aNodeId, NoHalt);
- theTransporterRegistry->setPerformState(aNodeId, PerformConnect);
+ theTransporterRegistry->do_connect(aNodeId);
}
void
TransporterFacade::doDisconnect(int aNodeId)
{
- theTransporterRegistry->setPerformState(aNodeId, PerformDisconnect);
+ theTransporterRegistry->do_disconnect(aNodeId);
}
void
@@ -906,7 +953,7 @@ TransporterFacade::ownId() const
bool
TransporterFacade::isConnected(NodeId aNodeId){
- return theTransporterRegistry->performState(aNodeId) == PerformIO;
+ return theTransporterRegistry->is_connected(aNodeId);
}
NodeId
@@ -992,3 +1039,6 @@ TransporterFacade::ThreadData::close(int number){
m_statusFunction[number] = 0;
return 0;
}
+
+template class Vector<NodeStatusFunction>;
+template class Vector<TransporterFacade::ThreadData::Object_Execute>;
diff --git a/ndb/src/ndbapi/TransporterFacade.hpp b/ndb/src/ndbapi/TransporterFacade.hpp
index 4b76cbe864a..14da4b11aa1 100644
--- a/ndb/src/ndbapi/TransporterFacade.hpp
+++ b/ndb/src/ndbapi/TransporterFacade.hpp
@@ -29,6 +29,7 @@ class ClusterMgr;
class ArbitMgr;
class IPCConfig;
struct ndb_mgm_configuration;
+class ConfigRetriever;
class Ndb;
class NdbApiSignal;
@@ -56,6 +57,7 @@ public:
static TransporterFacade* instance();
static TransporterFacade* start_instance(int, const ndb_mgm_configuration*);
static TransporterFacade* start_instance(const char *connectString);
+ static void close_configuration();
static void stop_instance();
/**
@@ -110,7 +112,6 @@ public:
// Close this block number
int close_local(BlockNumber blockNumber);
- void setState(Uint32 aNodeId, PerformState aState);
private:
/**
@@ -160,7 +161,9 @@ private:
/**
* Block number handling
*/
+public:
static const unsigned MAX_NO_THREADS = 4711;
+private:
struct ThreadData {
static const Uint32 ACTIVE = (1 << 16) | 1;
@@ -208,6 +211,8 @@ private:
}
} m_threads;
+ Uint32 m_open_count;
+
/**
* execute function
*/
@@ -219,6 +224,7 @@ public:
NdbMutex* theMutexPtr;
private:
static TransporterFacade* theFacadeInstance;
+ static ConfigRetriever *s_config_retriever;
public:
GlobalDictCache m_globalDictCache;
@@ -312,6 +318,7 @@ TransporterFacade::getIsNodeSendable(NodeId n) const {
"%d of node: %d",
node.m_info.m_type, n);
abort();
+ return false; // to remove compiler warning
}
}
diff --git a/ndb/src/ndbapi/ndberror.c b/ndb/src/ndbapi/ndberror.c
index 760322d669d..66a89326a66 100644
--- a/ndb/src/ndbapi/ndberror.c
+++ b/ndb/src/ndbapi/ndberror.c
@@ -91,6 +91,9 @@ ErrorBundle ErrorCodes[] = {
{ 4029, NR, "Node failure caused abort of transaction" },
{ 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" },
/**
* Node shutdown
@@ -114,9 +117,6 @@ ErrorBundle ErrorCodes[] = {
"Time-out, most likely caused by simple read or cluster failure" },
{ 4024, UR,
"Time-out, most likely caused by simple read or cluster failure" },
- { 4115, UR,
- "Transaction was committed but all read information was not "
- "received due to node crash" },
/**
* TemporaryResourceError
@@ -404,7 +404,6 @@ ErrorBundle ErrorCodes[] = {
{ 4243, AE, "Index not found" },
{ 4244, AE, "Index or table with given name already exists" },
{ 4245, AE, "Index attribute must be defined as stored, i.e. the StorageAttributeType must be defined as NormalStorageAttribute"},
- { 4246, AE, "Combined index attributes are not allowed to be NULL attributes" },
{ 4247, AE, "Illegal index/trigger create/drop/alter request" },
{ 4248, AE, "Trigger/index name invalid" },
{ 4249, AE, "Invalid table" },
diff --git a/ndb/test/include/HugoOperations.hpp b/ndb/test/include/HugoOperations.hpp
index 7295b72b18f..6bd8f7204b2 100644
--- a/ndb/test/include/HugoOperations.hpp
+++ b/ndb/test/include/HugoOperations.hpp
@@ -57,10 +57,6 @@ public:
int pkDeleteRecord(Ndb*,
int recordNo,
int numRecords = 1);
-
- int scanReadRecords(Ndb* pNdb,
- Uint32 parallelism = 240, ScanLock lock = SL_Read);
- int executeScanRead(Ndb*);
int execute_Commit(Ndb*,
AbortOption ao = AbortOnError);
@@ -93,7 +89,11 @@ public:
int recordNo,
int numRecords = 1,
int updatesValue = 0);
-
+
+ int scanReadRecords(Ndb*, NdbScanOperation::LockMode =
+ NdbScanOperation::LM_CommittedRead,
+ int numRecords = 1);
+
protected:
void allocRows(int rows);
void deallocRows();
@@ -102,48 +102,12 @@ protected:
HugoCalculator calc;
Vector<BaseString> savedRecords;
+
+ struct RsPair { NdbResultSet* m_result_set; int records; };
+ Vector<RsPair> m_result_sets;
+ Vector<RsPair> m_executed_result_sets;
private:
NdbConnection* pTrans;
-
- struct ScanTmp {
- ScanTmp() {
- pTrans = 0;
- m_tmpRow = 0;
- m_delete = true;
- m_op = DONE;
- }
- ScanTmp(NdbConnection* a, NDBT_ResultRow* b){
- pTrans = a;
- m_tmpRow = b;
- m_delete = true;
- m_op = DONE;
- }
- ScanTmp(const ScanTmp& org){
- * this = org;
- }
- ScanTmp& operator=(const ScanTmp& org){
- pTrans = org.pTrans;
- m_tmpRow = org.m_tmpRow;
- m_delete = org.m_delete;
- m_op = org.m_op;
- return * this;
- }
-
- ~ScanTmp() {
- if(m_delete && pTrans)
- pTrans->close();
- if(m_delete && m_tmpRow)
- delete m_tmpRow;
- }
-
- NdbConnection * pTrans;
- NDBT_ResultRow * m_tmpRow;
- bool m_delete;
- enum { DONE, READ, UPDATE, DELETE } m_op;
- };
- Vector<ScanTmp> m_scans;
- int run(ScanTmp & tmp);
-
};
#endif
diff --git a/ndb/test/include/HugoTransactions.hpp b/ndb/test/include/HugoTransactions.hpp
index 5ff1fef16bc..280d9490f15 100644
--- a/ndb/test/include/HugoTransactions.hpp
+++ b/ndb/test/include/HugoTransactions.hpp
@@ -34,16 +34,17 @@ public:
int records,
int batch = 512,
bool allowConstraintViolation = true,
- int doSleep = 0);
+ int doSleep = 0,
+ bool oneTrans = false);
int scanReadRecords(Ndb*,
int records,
int abort = 0,
- int parallelism = 1,
+ int parallelism = 0,
bool committed = false);
int scanReadCommittedRecords(Ndb*,
int records,
int abort = 0,
- int parallelism = 1);
+ int parallelism = 0);
int pkReadRecords(Ndb*,
int records,
int batchsize = 1,
@@ -52,20 +53,20 @@ public:
int scanUpdateRecords(Ndb*,
int records,
int abort = 0,
- int parallelism = 1);
+ int parallelism = 0);
int scanUpdateRecords1(Ndb*,
int records,
int abort = 0,
- int parallelism = 1);
+ int parallelism = 0);
int scanUpdateRecords2(Ndb*,
int records,
int abort = 0,
- int parallelism = 1);
+ int parallelism = 0);
int scanUpdateRecords3(Ndb*,
int records,
int abort = 0,
- int parallelism = 1);
+ int parallelism = 0);
int pkUpdateRecords(Ndb*,
int records,
@@ -100,24 +101,6 @@ public:
int batchsize = 1);
protected:
- int takeOverAndUpdateRecord(Ndb*,
- NdbOperation*);
-#if 0
- int setValueForAttr(NdbOperation*,
- int attrId,
- int rowId,
- int updateId);
-public:
- int equalForAttr(NdbOperation*,
- int attrId,
- int rowId);
-#endif
-
- int addRowToUpdate(Ndb* pNdb,
- NdbConnection* pUpdTrans,
- NdbOperation* pOrgOp);
-
-
NDBT_ResultRow row;
int m_defaultScanUpdateMethod;
};
diff --git a/ndb/test/include/NDBT_Table.hpp b/ndb/test/include/NDBT_Table.hpp
index eee76773106..59db3ed1092 100644
--- a/ndb/test/include/NDBT_Table.hpp
+++ b/ndb/test/include/NDBT_Table.hpp
@@ -23,10 +23,9 @@
#include <NdbOut.hpp>
class NDBT_Attribute : public NdbDictionary::Column {
- friend class NdbOut& operator <<(class NdbOut&, const NDBT_Attribute &);
public:
NDBT_Attribute(const char* _name,
- Column::Type _type,
+ NdbDictionary::Column::Type _type,
int _length = 1,
bool _pk = false,
bool _nullable = false):
@@ -51,13 +50,12 @@ public:
NDBT_Table(const char* name,
int noOfAttributes,
- const NdbDictionary::Column attributes[],
- bool stored = true)
+ const NdbDictionary::Column attributes[])
: NdbDictionary::Table(name)
{
assert(name != 0);
- setStoredTable(stored);
+ //setStoredTable(stored);
for(int i = 0; i<noOfAttributes; i++)
addColumn(attributes[i]);
}
diff --git a/ndb/test/include/NDBT_Tables.hpp b/ndb/test/include/NDBT_Tables.hpp
index 1da9818ee70..aa78f7d4e2c 100644
--- a/ndb/test/include/NDBT_Tables.hpp
+++ b/ndb/test/include/NDBT_Tables.hpp
@@ -26,7 +26,8 @@
class NDBT_Tables {
public:
- static int createTable(Ndb* pNdb, const char* _name, bool _temp = false);
+ static int createTable(Ndb* pNdb, const char* _name, bool _temp = false,
+ bool existsOK = false);
static int createAllTables(Ndb* pNdb, bool _temp, bool existsOK = false);
static int createAllTables(Ndb* pNdb);
diff --git a/ndb/test/include/NDBT_Test.hpp b/ndb/test/include/NDBT_Test.hpp
index 7a5d14689bc..6a968c491ae 100644
--- a/ndb/test/include/NDBT_Test.hpp
+++ b/ndb/test/include/NDBT_Test.hpp
@@ -63,6 +63,8 @@ public:
bool getPropertyWait(const char*, Uint32);
const char* getPropertyWait(const char*, const char* );
+ void decProperty(const char *);
+
// Communicate with other tests
void stopTest();
bool isTestStopped();
@@ -110,6 +112,7 @@ public:
NDBT_Step(NDBT_TestCase* ptest,
const char* pname,
NDBT_TESTFUNC* pfunc);
+ virtual ~NDBT_Step() {}
int execute(NDBT_Context*);
virtual int setUp() = 0;
virtual void tearDown() = 0;
@@ -132,8 +135,9 @@ public:
NDBT_NdbApiStep(NDBT_TestCase* ptest,
const char* pname,
NDBT_TESTFUNC* pfunc);
- int setUp();
- void tearDown();
+ virtual ~NDBT_NdbApiStep() {}
+ virtual int setUp();
+ virtual void tearDown();
Ndb* getNdb();
protected:
@@ -145,6 +149,7 @@ public:
NDBT_ParallelStep(NDBT_TestCase* ptest,
const char* pname,
NDBT_TESTFUNC* pfunc);
+ virtual ~NDBT_ParallelStep() {}
};
class NDBT_Verifier : public NDBT_NdbApiStep {
@@ -152,6 +157,7 @@ public:
NDBT_Verifier(NDBT_TestCase* ptest,
const char* name,
NDBT_TESTFUNC* func);
+ virtual ~NDBT_Verifier() {}
};
class NDBT_Initializer : public NDBT_NdbApiStep {
@@ -159,6 +165,7 @@ public:
NDBT_Initializer(NDBT_TestCase* ptest,
const char* name,
NDBT_TESTFUNC* func);
+ virtual ~NDBT_Initializer() {}
};
class NDBT_Finalizer : public NDBT_NdbApiStep {
@@ -166,6 +173,7 @@ public:
NDBT_Finalizer(NDBT_TestCase* ptest,
const char* name,
NDBT_TESTFUNC* func);
+ virtual ~NDBT_Finalizer() {}
};
@@ -174,7 +182,8 @@ public:
NDBT_TestCase(NDBT_TestSuite* psuite,
const char* name,
const char* comment);
- virtual ~NDBT_TestCase(){};
+ virtual ~NDBT_TestCase(){}
+
// This is the default executor of a test case
// When a test case is executed it will need to be suplied with a number of
// different parameters and settings, these are passed to the test in the
diff --git a/ndb/test/include/NdbRestarter.hpp b/ndb/test/include/NdbRestarter.hpp
index b4c29a87eff..114726f6a2b 100644
--- a/ndb/test/include/NdbRestarter.hpp
+++ b/ndb/test/include/NdbRestarter.hpp
@@ -19,6 +19,7 @@
#include <mgmapi.h>
#include <Vector.hpp>
+#include <BaseString.hpp>
class NdbRestarter {
public:
@@ -85,8 +86,8 @@ protected:
Vector<ndb_mgm_node_state> apiNodes;
bool connected;
- const char* addr;
- const char* host;
+ BaseString addr;
+ BaseString host;
int port;
NdbMgmHandle handle;
ndb_mgm_configuration * m_config;
diff --git a/ndb/test/include/UtilTransactions.hpp b/ndb/test/include/UtilTransactions.hpp
index b16ab74455e..1298028d591 100644
--- a/ndb/test/include/UtilTransactions.hpp
+++ b/ndb/test/include/UtilTransactions.hpp
@@ -34,24 +34,24 @@ public:
int clearTable(Ndb*,
int records = 0,
- int parallelism = 240);
+ int parallelism = 0);
// Delete all records from the table using a scan
int clearTable1(Ndb*,
int records = 0,
- int parallelism = 16);
+ int parallelism = 0);
// Delete all records from the table using a scan
// Using batching
int clearTable2(Ndb*,
int records = 0,
- int parallelism = 240);
+ int parallelism = 0);
int clearTable3(Ndb*,
int records = 0,
- int parallelism = 240);
+ int parallelism = 0);
int selectCount(Ndb*,
- int parallelism = 16,
+ int parallelism = 0,
int* count_rows = NULL,
ScanLock lock = SL_Read,
NdbConnection* pTrans = NULL);
@@ -64,7 +64,7 @@ public:
ReadCallBackFn* fn = NULL);
int verifyIndex(Ndb*,
const char* indexName,
- int parallelism = 240,
+ int parallelism = 0,
bool transactional = false);
int copyTableData(Ndb*,
@@ -88,7 +88,7 @@ private:
int verifyUniqueIndex(Ndb*,
const char* indexName,
- int parallelism = 240,
+ int parallelism = 0,
bool transactional = false);
int scanAndCompareUniqueIndex(Ndb* pNdb,
diff --git a/ndb/test/ndbapi/Makefile.am b/ndb/test/ndbapi/Makefile.am
index 7b3648bdc45..51bc11f8a25 100644
--- a/ndb/test/ndbapi/Makefile.am
+++ b/ndb/test/ndbapi/Makefile.am
@@ -9,7 +9,6 @@ create_tab \
flexAsynch \
flexBench \
flexHammer \
-flexScan \
flexTT \
testBackup \
testBasic \
@@ -26,9 +25,11 @@ testOperations \
testRestartGci \
testScan \
testScanInterpreter \
+testScanPerf \
testSystemRestart \
testTimeout \
testTransactions \
+testDeadlock \
test_event
#flexTimedAsynch
@@ -41,7 +42,6 @@ drop_all_tabs_SOURCES = drop_all_tabs.cpp
flexAsynch_SOURCES = flexAsynch.cpp
flexBench_SOURCES = flexBench.cpp
flexHammer_SOURCES = flexHammer.cpp
-flexScan_SOURCES = flexScan.cpp
flexTT_SOURCES = flexTT.cpp
#flexTimedAsynch_SOURCES = flexTimedAsynch.cpp
#flex_bench_mysql_SOURCES = flex_bench_mysql.cpp
@@ -60,9 +60,11 @@ testOperations_SOURCES = testOperations.cpp
testRestartGci_SOURCES = testRestartGci.cpp
testScan_SOURCES = testScan.cpp ScanFunctions.hpp
testScanInterpreter_SOURCES = testScanInterpreter.cpp ScanFilter.hpp ScanInterpretTest.hpp
+testScanPerf_SOURCES = testScanPerf.cpp
testSystemRestart_SOURCES = testSystemRestart.cpp
testTimeout_SOURCES = testTimeout.cpp
testTransactions_SOURCES = testTransactions.cpp
+testDeadlock_SOURCES = testDeadlock.cpp
test_event_SOURCES = test_event.cpp
INCLUDES_LOC = -I$(top_srcdir)/ndb/include/kernel
@@ -79,3 +81,4 @@ testBackup_LDADD = $(LDADD) bank/libbank.a
# Don't update the files from bitkeeper
%::SCCS/s.%
+
diff --git a/ndb/test/ndbapi/Makefile_old b/ndb/test/ndbapi/Makefile_old
index 34761e1eb9c..c3198096ec0 100644
--- a/ndb/test/ndbapi/Makefile_old
+++ b/ndb/test/ndbapi/Makefile_old
@@ -4,12 +4,11 @@ include .defs.mk
ifeq ($(NDB_OS), OSE)
DIRS = basic flexBench flexAsynch
else
-DIRS = lmc-bench bank ronja
+DIRS = lmc-bench ronja
BIN_DIRS = \
flexAsynch \
flexBench \
flexHammer \
- flexScan \
flexTT \
create_tab \
create_all_tabs \
@@ -32,7 +31,6 @@ BIN_DIRS = \
testDataBuffers \
testDict \
acid \
- interpreterInTup \
telco \
indexTest \
test_event \
diff --git a/ndb/test/ndbapi/ScanFunctions.hpp b/ndb/test/ndbapi/ScanFunctions.hpp
index 36d01909861..2ff4b751c33 100644
--- a/ndb/test/ndbapi/ScanFunctions.hpp
+++ b/ndb/test/ndbapi/ScanFunctions.hpp
@@ -79,8 +79,9 @@ ScanFunctions::scanReadFunctions(Ndb* pNdb,
const int retryMax = 100;
int sleepTime = 10;
int check;
- NdbConnection *pTrans;
- NdbOperation *pOp;
+ NdbConnection *pTrans = 0;
+ NdbScanOperation *pOp = 0;
+ NdbResultSet *rs = 0;
while (true){
if (retryAttempt >= retryMax){
@@ -103,117 +104,81 @@ ScanFunctions::scanReadFunctions(Ndb* pNdb,
}
// Execute the scan without defining a scan operation
- if(action != ExecuteScanWithOutOpenScan){
-
- if (action == OnlyOneOpBeforeOpenScan){
- // There can only be one operation defined when calling openScan
- NdbOperation* pOp3;
- pOp3 = pTrans->getNdbOperation(tab.getName());
- if (pOp3 == NULL) {
- ERR(pTrans->getNdbError());
- pNdb->closeTransaction(pTrans);
- return NDBT_FAILED;
- }
- }
-
- pOp = pTrans->getNdbOperation(tab.getName());
- if (pOp == NULL) {
+ pOp = pTrans->getNdbScanOperation(tab.getName());
+ if (pOp == NULL) {
+ ERR(pTrans->getNdbError());
+ pNdb->closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+
+ rs = pOp->readTuples(exclusive ?
+ NdbScanOperation::LM_Exclusive :
+ NdbScanOperation::LM_Read);
+
+ if( rs == 0 ) {
+ ERR(pTrans->getNdbError());
+ pNdb->closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+
+ if (action == OnlyOpenScanOnce){
+ // Call openScan one more time when it's already defined
+ NdbResultSet* rs2 = pOp->readTuples(NdbScanOperation::LM_Read);
+ if( rs2 == 0 ) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
return NDBT_FAILED;
}
-
- if (exclusive == true)
- check = pOp->openScanExclusive(parallelism);
- else
- check = pOp->openScanRead(parallelism);
+ }
+
+ if (action==EqualAfterOpenScan){
+ check = pOp->equal(tab.getColumn(0)->getName(), 10);
if( check == -1 ) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
return NDBT_FAILED;
- }
-
-
- if (action == OnlyOneScanPerTrans){
- // There can only be one operation in a scan transaction
- NdbOperation* pOp4;
- pOp4 = pTrans->getNdbOperation(tab.getName());
- if (pOp4 == NULL) {
- ERR(pTrans->getNdbError());
- pNdb->closeTransaction(pTrans);
- return NDBT_FAILED;
- }
- }
-
- if (action == OnlyOpenScanOnce){
- // Call openScan one more time when it's already defined
- check = pOp->openScanRead(parallelism);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- pNdb->closeTransaction(pTrans);
- return NDBT_FAILED;
- }
- }
-
- if (action == OnlyOneOpInScanTrans){
- // Try to add another op to this scanTransaction
- NdbOperation* pOp2;
- pOp2 = pTrans->getNdbOperation(tab.getName());
- if (pOp2 == NULL) {
- ERR(pTrans->getNdbError());
- pNdb->closeTransaction(pTrans);
- return NDBT_FAILED;
- }
- }
-
-
- if (action==EqualAfterOpenScan){
- check = pOp->equal(tab.getColumn(0)->getName(), 10);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- pNdb->closeTransaction(pTrans);
- return NDBT_FAILED;
- }
- }
-
- check = pOp->interpret_exit_ok();
- if( check == -1 ) {
+ }
+ }
+
+ check = pOp->interpret_exit_ok();
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ pNdb->closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ for(int a = 0; a<tab.getNoOfColumns(); a++){
+ if(pOp->getValue(tab.getColumn(a)->getName()) == NULL) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
return NDBT_FAILED;
}
-
- for(int a = 0; a<tab.getNoOfColumns(); a++){
- if(pOp->getValue(tab.getColumn(a)->getName()) == NULL) {
- ERR(pTrans->getNdbError());
- pNdb->closeTransaction(pTrans);
- return NDBT_FAILED;
- }
- }
- }
- check = pTrans->executeScan();
+ }
+
+ check = pTrans->execute(NoCommit);
if( check == -1 ) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
return NDBT_FAILED;
}
-
-
+
int abortCount = records / 10;
bool abortTrans = (action==CloseWithoutStop);
int eof;
int rows = 0;
- eof = pTrans->nextScanResult();
-
+ eof = rs->nextResult();
+
while(eof == 0){
rows++;
-
+
if (abortCount == rows && abortTrans == true){
g_info << "Scan is aborted after "<<abortCount<<" rows" << endl;
if (action != CloseWithoutStop){
// Test that we can closeTrans without stopScan
- check = pTrans->stopScan();
+ rs->close();
if( check == -1 ) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
@@ -236,7 +201,7 @@ ScanFunctions::scanReadFunctions(Ndb* pNdb,
}
}
- eof = pTrans->nextScanResult();
+ eof = rs->nextResult();
}
if (eof == -1) {
const NdbError err = pTrans->getNdbError();
@@ -246,7 +211,7 @@ ScanFunctions::scanReadFunctions(Ndb* pNdb,
// Be cruel, call nextScanResult after error
for(int i=0; i<10; i++){
- eof =pTrans->nextScanResult();
+ eof = rs->nextResult();
if(eof == 0){
g_err << "nextScanResult returned eof = " << eof << endl
<< " That is an error when there are no more records" << endl;
@@ -276,7 +241,7 @@ ScanFunctions::scanReadFunctions(Ndb* pNdb,
if (action == NextScanWhenNoMore){
g_info << "Calling nextScanresult when there are no more records" << endl;
for(int i=0; i<10; i++){
- eof =pTrans->nextScanResult();
+ eof = rs->nextResult();
if(eof == 0){
g_err << "nextScanResult returned eof = " << eof << endl
<< " That is an error when there are no more records" << endl;
@@ -285,7 +250,7 @@ ScanFunctions::scanReadFunctions(Ndb* pNdb,
}
}
- if(action ==CheckInactivityBeforeClose){
+ if(action == CheckInactivityBeforeClose){
// Sleep for a long time before calling close
g_info << "NdbSleep_SecSleep(5) before close transaction" << endl;
NdbSleep_SecSleep(5);
diff --git a/ndb/test/ndbapi/ScanInterpretTest.hpp b/ndb/test/ndbapi/ScanInterpretTest.hpp
index 3862de34111..e8a0d4b6dca 100644
--- a/ndb/test/ndbapi/ScanInterpretTest.hpp
+++ b/ndb/test/ndbapi/ScanInterpretTest.hpp
@@ -197,7 +197,7 @@ ScanInterpretTest::scanRead(Ndb* pNdb,
int retryMax = 100;
int check;
NdbConnection *pTrans;
- NdbOperation *pOp;
+ NdbScanOperation *pOp;
while (true){
@@ -220,16 +220,17 @@ ScanInterpretTest::scanRead(Ndb* pNdb,
return NDBT_FAILED;
}
- pOp = pTrans->getNdbOperation(tab.getName());
+ pOp = pTrans->getNdbScanOperation(tab.getName());
if (pOp == NULL) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
return NDBT_FAILED;
}
-
- check = pOp->openScanRead(parallelism);
- //check = pOp->openScanExclusive(parallelism);
- if( check == -1 ) {
+
+ NdbResultSet * rs = pOp->readTuples(NdbScanOperation::LM_Read,
+ 0, parallelism);
+
+ if( rs == 0 ) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
return NDBT_FAILED;
@@ -250,7 +251,7 @@ ScanInterpretTest::scanRead(Ndb* pNdb,
return NDBT_FAILED;
}
}
- check = pTrans->executeScan();
+ check = pTrans->execute(NoCommit);
if( check == -1 ) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
@@ -261,32 +262,22 @@ ScanInterpretTest::scanRead(Ndb* pNdb,
int rows = 0;
NdbConnection* pInsTrans;
- while((eof = pTrans->nextScanResult(true)) == 0){
- pInsTrans = pNdb->startTransaction();
- if (pInsTrans == NULL) {
- const NdbError err = pNdb->getNdbError();
- ERR(err);
- return NDBT_FAILED;
- }
+ while((eof = rs->nextResult(true)) == 0){
do {
rows++;
- if (addRowToInsert(pNdb, pInsTrans) != 0){
+ if (addRowToInsert(pNdb, pTrans) != 0){
pNdb->closeTransaction(pTrans);
- pNdb->closeTransaction(pInsTrans);
return NDBT_FAILED;
}
- } while((eof = pTrans->nextScanResult(false)) == 0);
+ } while((eof = rs->nextResult(false)) == 0);
- check = pInsTrans->execute(Commit);
+ check = pTrans->execute(Commit);
if( check == -1 ) {
- const NdbError err = pInsTrans->getNdbError();
+ const NdbError err = pTrans->getNdbError();
ERR(err);
- pNdb->closeTransaction(pInsTrans);
pNdb->closeTransaction(pTrans);
return NDBT_FAILED;
}
- pNdb->closeTransaction(pInsTrans);
-
}
if (eof == -1) {
const NdbError err = pTrans->getNdbError();
@@ -322,7 +313,7 @@ ScanInterpretTest::scanReadVerify(Ndb* pNdb,
const int retryMax = 100;
int check;
NdbConnection *pTrans;
- NdbOperation *pOp;
+ NdbScanOperation *pOp;
while (true){
@@ -346,7 +337,7 @@ ScanInterpretTest::scanReadVerify(Ndb* pNdb,
}
- pOp = pTrans->getNdbOperation(tab.getName());
+ pOp = pTrans->getNdbScanOperation(tab.getName());
if (pOp == NULL) { if (pOp->getValue("KOL2") == 0){
ERR(pNdb->getNdbError());
return NDBT_FAILED;
@@ -357,9 +348,10 @@ ScanInterpretTest::scanReadVerify(Ndb* pNdb,
pNdb->closeTransaction(pTrans);
return NDBT_FAILED;
}
-
- check = pOp->openScanRead(parallelism);
- if( check == -1 ) {
+
+ NdbResultSet * rs = pOp->readTuples(NdbScanOperation::LM_Read,
+ 0, parallelism);
+ if( rs == 0 ) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
return NDBT_FAILED;
@@ -382,7 +374,7 @@ ScanInterpretTest::scanReadVerify(Ndb* pNdb,
return NDBT_FAILED;
}
}
- check = pTrans->executeScan();
+ check = pTrans->execute(NoCommit);
if( check == -1 ) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
@@ -400,7 +392,7 @@ ScanInterpretTest::scanReadVerify(Ndb* pNdb,
NdbConnection* pExistTrans;
NdbConnection* pNoExistTrans;
- while((eof = pTrans->nextScanResult(true)) == 0){
+ while((eof = rs->nextResult(true)) == 0){
pExistTrans = pNdb->startTransaction();
if (pExistTrans == NULL) {
const NdbError err = pNdb->getNdbError();
@@ -432,7 +424,7 @@ ScanInterpretTest::scanReadVerify(Ndb* pNdb,
return NDBT_FAILED;
}
}
- } while((eof = pTrans->nextScanResult(false)) == 0);
+ } while((eof = rs->nextResult(false)) == 0);
// Execute the transaction containing reads of
diff --git a/ndb/test/ndbapi/bank/Bank.cpp b/ndb/test/ndbapi/bank/Bank.cpp
index 14883205693..7a2c5b057a1 100644
--- a/ndb/test/ndbapi/bank/Bank.cpp
+++ b/ndb/test/ndbapi/bank/Bank.cpp
@@ -670,15 +670,15 @@ int Bank::findLastGL(Uint64 &lastTime){
return NDBT_FAILED;
}
- NdbOperation* pOp = pScanTrans->getNdbOperation("GL");
+ NdbScanOperation* pOp = pScanTrans->getNdbScanOperation("GL");
if (pOp == NULL) {
ERR(pScanTrans->getNdbError());
m_ndb.closeTransaction(pScanTrans);
return NDBT_FAILED;
}
- check = pOp->openScanRead(64);
- if( check == -1 ) {
+ NdbResultSet * rs = pOp->readTuples();
+ if( rs == 0 ) {
ERR(pScanTrans->getNdbError());
m_ndb.closeTransaction(pScanTrans);
return NDBT_FAILED;
@@ -698,7 +698,7 @@ int Bank::findLastGL(Uint64 &lastTime){
return NDBT_FAILED;
}
- check = pScanTrans->executeScan();
+ check = pScanTrans->execute(NoCommit);
if( check == -1 ) {
ERR(pScanTrans->getNdbError());
m_ndb.closeTransaction(pScanTrans);
@@ -707,7 +707,7 @@ int Bank::findLastGL(Uint64 &lastTime){
int eof;
int rows = 0;
- eof = pScanTrans->nextScanResult();
+ eof = rs->nextResult();
lastTime = 0;
while(eof == 0){
@@ -717,7 +717,7 @@ int Bank::findLastGL(Uint64 &lastTime){
if (t > lastTime)
lastTime = t;
- eof = pScanTrans->nextScanResult();
+ eof = rs->nextResult();
}
if (eof == -1) {
ERR(pScanTrans->getNdbError());
@@ -1002,15 +1002,15 @@ int Bank::sumTransactionsForGL(const Uint64 glTime,
return NDBT_FAILED;
}
- NdbOperation* pOp = pScanTrans->getNdbOperation("TRANSACTION");
+ NdbScanOperation* pOp = pScanTrans->getNdbScanOperation("TRANSACTION");
if (pOp == NULL) {
ERR(pScanTrans->getNdbError());
m_ndb.closeTransaction(pScanTrans);
return NDBT_FAILED;
}
- check = pOp->openScanExclusive(64);
- if( check == -1 ) {
+ NdbResultSet * rs = pOp->readTuplesExclusive();
+ if( rs == 0 ) {
ERR(pScanTrans->getNdbError());
m_ndb.closeTransaction(pScanTrans);
return NDBT_FAILED;
@@ -1051,7 +1051,7 @@ int Bank::sumTransactionsForGL(const Uint64 glTime,
return NDBT_FAILED;
}
- check = pScanTrans->executeScan();
+ check = pScanTrans->execute(NoCommit);
if( check == -1 ) {
ERR(pScanTrans->getNdbError());
m_ndb.closeTransaction(pScanTrans);
@@ -1061,7 +1061,7 @@ int Bank::sumTransactionsForGL(const Uint64 glTime,
int eof;
int rows = 0;
int rowsFound = 0;
- eof = pScanTrans->nextScanResult();
+ eof = rs->nextResult();
while(eof == 0){
rows++;
@@ -1085,7 +1085,7 @@ int Bank::sumTransactionsForGL(const Uint64 glTime,
}
}
- eof = pScanTrans->nextScanResult();
+ eof = rs->nextResult();
if ((rows % 100) == 0){
// "refresh" ownner transaction every 100th row
@@ -1162,15 +1162,15 @@ int Bank::performValidateGL(Uint64 glTime){
return NDBT_FAILED;
}
- NdbOperation* pOp = pScanTrans->getNdbOperation("GL");
+ NdbScanOperation* pOp = pScanTrans->getNdbScanOperation("GL");
if (pOp == NULL) {
ERR(pScanTrans->getNdbError());
m_ndb.closeTransaction(pScanTrans);
return NDBT_FAILED;
}
- check = pOp->openScanRead(64);
- if( check == -1 ) {
+ NdbResultSet * rs = pOp->readTuples();
+ if( rs == 0 ) {
ERR(pScanTrans->getNdbError());
m_ndb.closeTransaction(pScanTrans);
return NDBT_FAILED;
@@ -1238,7 +1238,7 @@ int Bank::performValidateGL(Uint64 glTime){
return NDBT_FAILED;
}
- check = pScanTrans->executeScan();
+ check = pScanTrans->execute(NoCommit);
if( check == -1 ) {
ERR(pScanTrans->getNdbError());
m_ndb.closeTransaction(pScanTrans);
@@ -1249,7 +1249,7 @@ int Bank::performValidateGL(Uint64 glTime){
int rows = 0;
int countGlRecords = 0;
int result = NDBT_OK;
- eof = pScanTrans->nextScanResult();
+ eof = rs->nextResult();
while(eof == 0){
rows++;
@@ -1336,7 +1336,7 @@ int Bank::performValidateGL(Uint64 glTime){
}
}
- eof = pScanTrans->nextScanResult();
+ eof = rs->nextResult();
}
if (eof == -1) {
ERR(pScanTrans->getNdbError());
@@ -1426,15 +1426,15 @@ int Bank::getOldestPurgedGL(const Uint32 accountType,
return NDBT_FAILED;
}
- NdbOperation* pOp = pScanTrans->getNdbOperation("GL");
+ NdbScanOperation* pOp = pScanTrans->getNdbScanOperation("GL");
if (pOp == NULL) {
ERR(pScanTrans->getNdbError());
m_ndb.closeTransaction(pScanTrans);
return NDBT_FAILED;
}
- check = pOp->openScanRead(64);
- if( check == -1 ) {
+ NdbResultSet * rs = pOp->readTuples();
+ if( rs == 0 ) {
ERR(pScanTrans->getNdbError());
m_ndb.closeTransaction(pScanTrans);
return NDBT_FAILED;
@@ -1468,7 +1468,7 @@ int Bank::getOldestPurgedGL(const Uint32 accountType,
return NDBT_FAILED;
}
- check = pScanTrans->executeScan();
+ check = pScanTrans->execute(NoCommit);
if( check == -1 ) {
ERR(pScanTrans->getNdbError());
m_ndb.closeTransaction(pScanTrans);
@@ -1477,7 +1477,7 @@ int Bank::getOldestPurgedGL(const Uint32 accountType,
int eof;
int rows = 0;
- eof = pScanTrans->nextScanResult();
+ eof = rs->nextResult();
oldest = 0;
while(eof == 0){
@@ -1491,7 +1491,7 @@ int Bank::getOldestPurgedGL(const Uint32 accountType,
if (t > oldest)
oldest = t;
}
- eof = pScanTrans->nextScanResult();
+ eof = rs->nextResult();
}
if (eof == -1) {
ERR(pScanTrans->getNdbError());
@@ -1518,15 +1518,15 @@ int Bank::getOldestNotPurgedGL(Uint64 &oldest,
return NDBT_FAILED;
}
- NdbOperation* pOp = pScanTrans->getNdbOperation("GL");
+ NdbScanOperation* pOp = pScanTrans->getNdbScanOperation("GL");
if (pOp == NULL) {
ERR(pScanTrans->getNdbError());
m_ndb.closeTransaction(pScanTrans);
return NDBT_FAILED;
}
- check = pOp->openScanRead(64);
- if( check == -1 ) {
+ NdbResultSet * rs = pOp->readTuples();
+ if( rs == 0 ) {
ERR(pScanTrans->getNdbError());
m_ndb.closeTransaction(pScanTrans);
return NDBT_FAILED;
@@ -1560,7 +1560,7 @@ int Bank::getOldestNotPurgedGL(Uint64 &oldest,
return NDBT_FAILED;
}
- check = pScanTrans->executeScan();
+ check = pScanTrans->execute(NoCommit);
if( check == -1 ) {
ERR(pScanTrans->getNdbError());
m_ndb.closeTransaction(pScanTrans);
@@ -1569,7 +1569,7 @@ int Bank::getOldestNotPurgedGL(Uint64 &oldest,
int eof;
int rows = 0;
- eof = pScanTrans->nextScanResult();
+ eof = rs->nextResult();
oldest = (Uint64)-1;
found = false;
@@ -1586,7 +1586,7 @@ int Bank::getOldestNotPurgedGL(Uint64 &oldest,
accountTypeId = a;
}
}
- eof = pScanTrans->nextScanResult();
+ eof = rs->nextResult();
}
if (eof == -1) {
ERR(pScanTrans->getNdbError());
@@ -1615,15 +1615,15 @@ int Bank::checkNoTransactionsOlderThan(const Uint32 accountType,
return NDBT_FAILED;
}
- NdbOperation* pOp = pScanTrans->getNdbOperation("TRANSACTION");
+ NdbScanOperation* pOp = pScanTrans->getNdbScanOperation("TRANSACTION");
if (pOp == NULL) {
ERR(pScanTrans->getNdbError());
m_ndb.closeTransaction(pScanTrans);
return NDBT_FAILED;
}
- check = pOp->openScanRead(64);
- if( check == -1 ) {
+ NdbResultSet * rs = pOp->readTuples();
+ if( rs == 0 ) {
ERR(pScanTrans->getNdbError());
m_ndb.closeTransaction(pScanTrans);
return NDBT_FAILED;
@@ -1657,7 +1657,7 @@ int Bank::checkNoTransactionsOlderThan(const Uint32 accountType,
return NDBT_FAILED;
}
- check = pScanTrans->executeScan();
+ check = pScanTrans->execute(NoCommit);
if( check == -1 ) {
ERR(pScanTrans->getNdbError());
m_ndb.closeTransaction(pScanTrans);
@@ -1667,7 +1667,7 @@ int Bank::checkNoTransactionsOlderThan(const Uint32 accountType,
int eof;
int rows = 0;
int found = 0;
- eof = pScanTrans->nextScanResult();
+ eof = rs->nextResult();
while(eof == 0){
rows++;
@@ -1683,7 +1683,7 @@ int Bank::checkNoTransactionsOlderThan(const Uint32 accountType,
<< " ti = " << ti << endl;
found++;
}
- eof = pScanTrans->nextScanResult();
+ eof = rs->nextResult();
}
if (eof == -1) {
ERR(pScanTrans->getNdbError());
@@ -1859,15 +1859,15 @@ int Bank::findTransactionsToPurge(const Uint64 glTime,
return NDBT_FAILED;
}
- NdbOperation* pOp = pScanTrans->getNdbOperation("TRANSACTION");
+ NdbScanOperation* pOp = pScanTrans->getNdbScanOperation("TRANSACTION");
if (pOp == NULL) {
ERR(pScanTrans->getNdbError());
m_ndb.closeTransaction(pScanTrans);
return NDBT_FAILED;
}
- check = pOp->openScanExclusive(64);
- if( check == -1 ) {
+ NdbResultSet * rs = pOp->readTuplesExclusive();
+ if( rs == 0 ) {
ERR(pScanTrans->getNdbError());
m_ndb.closeTransaction(pScanTrans);
return NDBT_FAILED;
@@ -1894,7 +1894,7 @@ int Bank::findTransactionsToPurge(const Uint64 glTime,
return NDBT_FAILED;
}
- check = pScanTrans->executeScan();
+ check = pScanTrans->execute(NoCommit);
if( check == -1 ) {
ERR(pScanTrans->getNdbError());
m_ndb.closeTransaction(pScanTrans);
@@ -1904,7 +1904,7 @@ int Bank::findTransactionsToPurge(const Uint64 glTime,
int eof;
int rows = 0;
int rowsFound = 0;
- eof = pScanTrans->nextScanResult();
+ eof = rs->nextResult();
while(eof == 0){
rows++;
@@ -1914,8 +1914,8 @@ int Bank::findTransactionsToPurge(const Uint64 glTime,
if (a == accountType && t == glTime){
rowsFound++;
// One record found
- NdbOperation* pDelOp = pOp->takeOverForDelete(pTrans);
- if (pDelOp == NULL){
+ check = rs->deleteTuple(pTrans);
+ if (check == -1){
ERR(m_ndb.getNdbError());
m_ndb.closeTransaction(pScanTrans);
return NDBT_FAILED;
@@ -1929,7 +1929,7 @@ int Bank::findTransactionsToPurge(const Uint64 glTime,
return NDBT_FAILED;
}
}
- eof = pScanTrans->nextScanResult();
+ eof = rs->nextResult();
}
if (eof == -1) {
ERR(pScanTrans->getNdbError());
@@ -2348,15 +2348,15 @@ int Bank::getSumAccounts(Uint32 &sumAccounts,
return NDBT_FAILED;
}
- NdbOperation* pOp = pScanTrans->getNdbOperation("ACCOUNT");
+ NdbScanOperation* pOp = pScanTrans->getNdbScanOperation("ACCOUNT");
if (pOp == NULL) {
ERR(pScanTrans->getNdbError());
m_ndb.closeTransaction(pScanTrans);
return NDBT_FAILED;
}
- check = pOp->openScanExclusive(64);
- if( check == -1 ) {
+ NdbResultSet * rs = pOp->readTuplesExclusive();
+ if( rs == 0 ) {
ERR(pScanTrans->getNdbError());
m_ndb.closeTransaction(pScanTrans);
return NDBT_FAILED;
@@ -2376,7 +2376,7 @@ int Bank::getSumAccounts(Uint32 &sumAccounts,
return NDBT_FAILED;
}
- check = pScanTrans->executeScan();
+ check = pScanTrans->execute(NoCommit);
if( check == -1 ) {
ERR(pScanTrans->getNdbError());
m_ndb.closeTransaction(pScanTrans);
@@ -2391,7 +2391,7 @@ int Bank::getSumAccounts(Uint32 &sumAccounts,
}
int eof;
- eof = pScanTrans->nextScanResult();
+ eof = rs->nextResult();
while(eof == 0){
Uint32 b = balanceRec->u_32_value();
@@ -2403,7 +2403,7 @@ int Bank::getSumAccounts(Uint32 &sumAccounts,
// << ", sum="<< sumAccounts << endl;
// Take over the operation so that the lock is kept in db
- NdbOperation* pLockOp = pOp->takeOverForUpdate(pTrans);
+ NdbOperation* pLockOp = rs->updateTuple(pTrans);
if (pLockOp == NULL){
ERR(m_ndb.getNdbError());
m_ndb.closeTransaction(pScanTrans);
@@ -2429,7 +2429,7 @@ int Bank::getSumAccounts(Uint32 &sumAccounts,
return NDBT_FAILED;
}
- eof = pScanTrans->nextScanResult();
+ eof = rs->nextResult();
}
if (eof == -1) {
ERR(pScanTrans->getNdbError());
diff --git a/ndb/test/ndbapi/bank/BankLoad.cpp b/ndb/test/ndbapi/bank/BankLoad.cpp
index 76261b664a6..bbaac27735b 100644
--- a/ndb/test/ndbapi/bank/BankLoad.cpp
+++ b/ndb/test/ndbapi/bank/BankLoad.cpp
@@ -335,15 +335,15 @@ int Bank::getBalanceForAccountType(const Uint32 accountType,
return NDBT_FAILED;
}
- NdbOperation* pOp = pScanTrans->getNdbOperation("ACCOUNT");
+ NdbScanOperation* pOp = pScanTrans->getNdbScanOperation("ACCOUNT");
if (pOp == NULL) {
ERR(pScanTrans->getNdbError());
m_ndb.closeTransaction(pScanTrans);
return NDBT_FAILED;
}
- check = pOp->openScanRead(64);
- if( check == -1 ) {
+ NdbResultSet* rs = pOp->readTuples();
+ if( rs == 0 ) {
ERR(pScanTrans->getNdbError());
m_ndb.closeTransaction(pScanTrans);
return NDBT_FAILED;
@@ -370,7 +370,7 @@ int Bank::getBalanceForAccountType(const Uint32 accountType,
return NDBT_FAILED;
}
- check = pScanTrans->executeScan();
+ check = pScanTrans->execute(NoCommit);
if( check == -1 ) {
ERR(pScanTrans->getNdbError());
m_ndb.closeTransaction(pScanTrans);
@@ -379,7 +379,7 @@ int Bank::getBalanceForAccountType(const Uint32 accountType,
int eof;
int rows = 0;
- eof = pScanTrans->nextScanResult();
+ eof = rs->nextResult();
while(eof == 0){
rows++;
@@ -391,7 +391,7 @@ int Bank::getBalanceForAccountType(const Uint32 accountType,
balance += b;
}
- eof = pScanTrans->nextScanResult();
+ eof = rs->nextResult();
}
if (eof == -1) {
ERR(pScanTrans->getNdbError());
diff --git a/ndb/test/ndbapi/create_tab.cpp b/ndb/test/ndbapi/create_tab.cpp
index 8bb1e7a9572..c2e3b7f64ea 100644
--- a/ndb/test/ndbapi/create_tab.cpp
+++ b/ndb/test/ndbapi/create_tab.cpp
@@ -63,9 +63,10 @@ int main(int argc, const char** argv){
/**
* Print instead of creating
*/
- if(argv[optind] != NULL){
- for(int i = optind; i<argc; i++)
+ if(optind < argc){
+ for(int i = optind; i<argc; i++){
NDBT_Tables::print(argv[i]);
+ }
} else {
NDBT_Tables::printAll();
}
diff --git a/ndb/test/ndbapi/flexAsynch.cpp b/ndb/test/ndbapi/flexAsynch.cpp
index 396ac06c87a..9192ec21b93 100644
--- a/ndb/test/ndbapi/flexAsynch.cpp
+++ b/ndb/test/ndbapi/flexAsynch.cpp
@@ -146,7 +146,7 @@ tellThreads(StartType what)
NDB_COMMAND(flexAsynch, "flexAsynch", "flexAsynch", "flexAsynch", 65535)
{
ThreadNdb* pThreadData;
- int tLoops=0;
+ int tLoops=0, i;
int returnValue = NDBT_OK;
flexAsynchErrorData = new ErrorData;
@@ -256,7 +256,7 @@ NDB_COMMAND(flexAsynch, "flexAsynch", "flexAsynch", "flexAsynch", 65535)
PRINT_TIMER("insert", noOfTransacts, tNoOfOpsPerTrans);
if (0 < failed) {
- int i = retry_opt ;
+ i = retry_opt ;
int ci = 1 ;
while (0 < failed && 0 < i){
ndbout << failed << " of the transactions returned errors!"
@@ -293,7 +293,7 @@ NDB_COMMAND(flexAsynch, "flexAsynch", "flexAsynch", "flexAsynch", 65535)
PRINT_TIMER("read", noOfTransacts, tNoOfOpsPerTrans);
if (0 < failed) {
- int i = retry_opt ;
+ i = retry_opt ;
int cr = 1;
while (0 < failed && 0 < i){
ndbout << failed << " of the transactions returned errors!"<<endl ;
@@ -330,7 +330,7 @@ NDB_COMMAND(flexAsynch, "flexAsynch", "flexAsynch", "flexAsynch", 65535)
PRINT_TIMER("update", noOfTransacts, tNoOfOpsPerTrans) ;
if (0 < failed) {
- int i = retry_opt ;
+ i = retry_opt ;
int cu = 1 ;
while (0 < failed && 0 < i){
ndbout << failed << " of the transactions returned errors!"<<endl ;
@@ -366,7 +366,7 @@ NDB_COMMAND(flexAsynch, "flexAsynch", "flexAsynch", "flexAsynch", 65535)
PRINT_TIMER("read", noOfTransacts, tNoOfOpsPerTrans);
if (0 < failed) {
- int i = retry_opt ;
+ i = retry_opt ;
int cr2 = 1 ;
while (0 < failed && 0 < i){
ndbout << failed << " of the transactions returned errors!"<<endl ;
@@ -403,7 +403,7 @@ NDB_COMMAND(flexAsynch, "flexAsynch", "flexAsynch", "flexAsynch", 65535)
PRINT_TIMER("delete", noOfTransacts, tNoOfOpsPerTrans);
if (0 < failed) {
- int i = retry_opt ;
+ i = retry_opt ;
int cd = 1 ;
while (0 < failed && 0 < i){
ndbout << failed << " of the transactions returned errors!"<< endl ;
@@ -438,7 +438,7 @@ NDB_COMMAND(flexAsynch, "flexAsynch", "flexAsynch", "flexAsynch", 65535)
execute(stStop);
void * tmp;
- for(int i = 0; i<tNoOfThreads; i++){
+ for(i = 0; i<tNoOfThreads; i++){
NdbThread_WaitFor(threadLife[i], &tmp);
NdbThread_Destroy(&threadLife[i]);
}
diff --git a/ndb/test/ndbapi/flexBench.cpp b/ndb/test/ndbapi/flexBench.cpp
index 809d11086bf..38c8f6e280f 100644
--- a/ndb/test/ndbapi/flexBench.cpp
+++ b/ndb/test/ndbapi/flexBench.cpp
@@ -282,7 +282,7 @@ tellThreads(ThreadData* pt, StartType what)
NDB_COMMAND(flexBench, "flexBench", "flexBench", "flexbench", 65535)
{
ThreadData* pThreadsData;
- int tLoops = 0;
+ int tLoops = 0, i;
int returnValue = NDBT_OK;
if (readArguments(argc, argv) != 0){
@@ -355,7 +355,7 @@ NDB_COMMAND(flexBench, "flexBench", "flexBench", "flexbench", 65535)
****************************************************************/
resetThreads(pThreadsData);
- for (unsigned int i = 0; i < tNoOfThreads; i++){
+ for (i = 0; i < tNoOfThreads; i++){
pThreadsData[i].threadNo = i;
pThreadsData[i].threadLife = NdbThread_Create(flexBenchThread,
(void**)&pThreadsData[i],
@@ -531,7 +531,7 @@ NDB_COMMAND(flexBench, "flexBench", "flexBench", "flexbench", 65535)
waitForThreads(pThreadsData);
void * tmp;
- for(Uint32 i = 0; i<tNoOfThreads; i++){
+ for(i = 0; i<tNoOfThreads; i++){
NdbThread_WaitFor(pThreadsData[i].threadLife, &tmp);
NdbThread_Destroy(&pThreadsData[i].threadLife);
}
@@ -540,7 +540,7 @@ NDB_COMMAND(flexBench, "flexBench", "flexBench", "flexbench", 65535)
if (useLongKeys == true) {
// Only free these areas if they have been allocated
// Otherwise cores will happen
- for (Uint32 i = 0; i < tNoOfLongPK; i++)
+ for (i = 0; i < tNoOfLongPK; i++)
free(longKeyAttrName[i]);
free(longKeyAttrName);
} // if
@@ -629,9 +629,10 @@ static void* flexBenchThread(void* pArg)
if(useLongKeys){
// Allocate and populate the longkey array.
longKeyAttrValue = (unsigned ***) malloc(sizeof(unsigned**) * tNoOfOperations );
- for (Uint32 n = 0; n < tNoOfOperations; n++)
+ Uint32 n;
+ for (n = 0; n < tNoOfOperations; n++)
longKeyAttrValue[n] = (unsigned **) malloc(sizeof(unsigned*) * tNoOfLongPK );
- for (Uint32 n = 0; n < tNoOfOperations; n++){
+ for (n = 0; n < tNoOfOperations; n++){
for (Uint32 i = 0; i < tNoOfLongPK ; i++) {
longKeyAttrValue[n][i] = (unsigned *) malloc(sizeof(unsigned) * tSizeOfLongPK);
memset(longKeyAttrValue[n][i], 0, sizeof(unsigned) * tSizeOfLongPK);
@@ -1064,13 +1065,14 @@ static void sleepBeforeStartingTest(int seconds){
static int
createTables(Ndb* pMyNdb){
- for (Uint32 i = 0; i < tNoOfAttributes; i++){
+ int i;
+ for (i = 0; i < tNoOfAttributes; i++){
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++){
+ for (i = 0; i < tNoOfTables; i++){
if (theStdTableNameFlag == 0){
snprintf(tableName[i], MAXSTRLEN, "TAB%d_%d", i,
(int)(NdbTick_CurrentMillisecond() / 1000));
@@ -1079,7 +1081,7 @@ createTables(Ndb* pMyNdb){
}
}
- for(unsigned i = 0; i < tNoOfTables; i++){
+ for(i = 0; i < tNoOfTables; i++){
ndbout << "Creating " << tableName[i] << "... ";
NdbDictionary::Table tmpTable(tableName[i]);
diff --git a/ndb/test/ndbapi/flexTT.cpp b/ndb/test/ndbapi/flexTT.cpp
index a82875de5c2..c0ff31d1677 100644
--- a/ndb/test/ndbapi/flexTT.cpp
+++ b/ndb/test/ndbapi/flexTT.cpp
@@ -173,7 +173,7 @@ NDB_COMMAND(flexTT, "flexTT", "flexTT", "flexTT", 65535)
{
ThreadNdb* pThreadData;
int returnValue = NDBT_OK;
-
+ int i;
flexTTErrorData = new ErrorData;
flexTTErrorData->resetErrorCounters();
@@ -250,7 +250,7 @@ NDB_COMMAND(flexTT, "flexTT", "flexTT", "flexTT", 65535)
* Create NDB objects. *
****************************************************************/
resetThreads();
- for (int i = 0; i < tNoOfThreads ; i++) {
+ for (i = 0; i < tNoOfThreads ; i++) {
pThreadData[i].threadNo = i;
threadLife[i] = NdbThread_Create(threadLoop,
(void**)&pThreadData[i],
@@ -301,7 +301,7 @@ NDB_COMMAND(flexTT, "flexTT", "flexTT", "flexTT", 65535)
execute(stStop);
void * tmp;
- for(int i = 0; i<tNoOfThreads; i++){
+ for(i = 0; i<tNoOfThreads; i++){
NdbThread_WaitFor(threadLife[i], &tmp);
NdbThread_Destroy(&threadLife[i]);
}
diff --git a/ndb/test/ndbapi/old_dirs/testBackup/Makefile b/ndb/test/ndbapi/old_dirs/testBackup/Makefile
index ce0e404803c..abf47dcfb2d 100644
--- a/ndb/test/ndbapi/old_dirs/testBackup/Makefile
+++ b/ndb/test/ndbapi/old_dirs/testBackup/Makefile
@@ -3,7 +3,6 @@ include .defs.mk
TYPE = ndbapitest
BIN_TARGET = testBackup
-BIN_TARGET_LIBS += bank
SOURCES = testBackup.cpp
include $(NDB_TOP)/Epilogue.mk
diff --git a/ndb/test/ndbapi/old_dirs/testGrep/Makefile b/ndb/test/ndbapi/old_dirs/testGrep/Makefile
index 34fdd7113d0..6bad3d56a00 100644
--- a/ndb/test/ndbapi/old_dirs/testGrep/Makefile
+++ b/ndb/test/ndbapi/old_dirs/testGrep/Makefile
@@ -3,7 +3,6 @@ include .defs.mk
TYPE = ndbapitest
DIRS = verify
BIN_TARGET = testGrep
-BIN_TARGET_LIBS += bank
SOURCES = testGrep.cpp
include $(NDB_TOP)/Epilogue.mk
diff --git a/ndb/test/ndbapi/old_dirs/testGrep/verify/Makefile b/ndb/test/ndbapi/old_dirs/testGrep/verify/Makefile
index 4e6182de6b2..256e3c98f36 100644
--- a/ndb/test/ndbapi/old_dirs/testGrep/verify/Makefile
+++ b/ndb/test/ndbapi/old_dirs/testGrep/verify/Makefile
@@ -3,7 +3,6 @@ include .defs.mk
TYPE = ndbapitest
BIN_TARGET = testGrepVerify
-BIN_TARGET_LIBS += bank
SOURCES = testGrepVerify.cpp
CFLAGS_testGrepVerify.cpp += -I$(call fixpath,$(NDB_TOP)/include/kernel) -I$(call fixpath,$(NDB_TOP)/include/mgmcommon)
diff --git a/ndb/test/ndbapi/testBackup.cpp b/ndb/test/ndbapi/testBackup.cpp
index 129eced54b0..d328a7db292 100644
--- a/ndb/test/ndbapi/testBackup.cpp
+++ b/ndb/test/ndbapi/testBackup.cpp
@@ -205,6 +205,11 @@ int runClearTable(NDBT_Context* ctx, NDBT_Step* step){
return NDBT_OK;
}
+int runDropTable(NDBT_Context* ctx, NDBT_Step* step){
+ GETNDB(step)->getDictionary()->dropTable(ctx->getTab()->getName());
+ return NDBT_OK;
+}
+
#include "bank/Bank.hpp"
int runCreateBank(NDBT_Context* ctx, NDBT_Step* step){
@@ -408,7 +413,7 @@ TESTCASE("BackupOne",
INITIALIZER(runRestoreOne);
VERIFIER(runVerifyOne);
FINALIZER(runClearTable);
-
+ FINALIZER(runDropTable);
}
TESTCASE("BackupBank",
"Test that backup and restore works during transaction load\n"
@@ -428,7 +433,6 @@ TESTCASE("BackupBank",
STEP(runBackupBank);
VERIFIER(runRestoreBankAndVerify);
// FINALIZER(runDropBank);
-
}
TESTCASE("NFMaster",
"Test that backup behaves during node failiure\n"){
diff --git a/ndb/test/ndbapi/testBasic.cpp b/ndb/test/ndbapi/testBasic.cpp
index 64dfe492c2c..26622f9b066 100644
--- a/ndb/test/ndbapi/testBasic.cpp
+++ b/ndb/test/ndbapi/testBasic.cpp
@@ -29,9 +29,18 @@
* delete should be visible to same transaction
*
*/
+int runLoadTable2(NDBT_Context* ctx, NDBT_Step* step)
+{
+ int records = ctx->getNumRecords();
+ HugoTransactions hugoTrans(*ctx->getTab());
+ if (hugoTrans.loadTable(GETNDB(step), records, 512, false, 0, true) != 0){
+ return NDBT_FAILED;
+ }
+ return NDBT_OK;
+}
-int runLoadTable(NDBT_Context* ctx, NDBT_Step* step){
-
+int runLoadTable(NDBT_Context* ctx, NDBT_Step* step)
+{
int records = ctx->getNumRecords();
HugoTransactions hugoTrans(*ctx->getTab());
if (hugoTrans.loadTable(GETNDB(step), records) != 0){
@@ -255,7 +264,7 @@ static
int
readOneNoCommit(Ndb* pNdb, NdbConnection* pTrans,
const NdbDictionary::Table* tab,NDBT_ResultRow * row){
-
+ int a;
NdbOperation * pOp = pTrans->getNdbOperation(tab->getName());
if (pOp == NULL){
ERR(pTrans->getNdbError());
@@ -271,7 +280,7 @@ readOneNoCommit(Ndb* pNdb, NdbConnection* pTrans,
}
// Define primary keys
- for(int a = 0; a<tab->getNoOfColumns(); a++){
+ for(a = 0; a<tab->getNoOfColumns(); a++){
if (tab->getColumn(a)->getPrimaryKey() == true){
if(tmp.equalForAttr(pOp, a, 0) != 0){
ERR(pTrans->getNdbError());
@@ -281,7 +290,7 @@ readOneNoCommit(Ndb* pNdb, NdbConnection* pTrans,
}
// Define attributes to read
- for(int a = 0; a<tab->getNoOfColumns(); a++){
+ for(a = 0; a<tab->getNoOfColumns(); a++){
if((row->attributeStore(a) =
pOp->getValue(tab->getColumn(a)->getName())) == 0) {
ERR(pTrans->getNdbError());
@@ -630,35 +639,35 @@ int runNoCommitRollback630(NDBT_Context* ctx, NDBT_Step* step){
int runNoCommitAndClose(NDBT_Context* ctx, NDBT_Step* step){
- int result = NDBT_OK;
+ int i, result = NDBT_OK;
HugoOperations hugoOps(*ctx->getTab());
Ndb* pNdb = GETNDB(step);
do{
// Read
CHECK(hugoOps.startTransaction(pNdb) == 0);
- for (int i = 0; i < 10; i++)
+ for (i = 0; i < 10; i++)
CHECK(hugoOps.pkReadRecord(pNdb, i, true) == 0);
CHECK(hugoOps.execute_NoCommit(pNdb) == 0);
CHECK(hugoOps.closeTransaction(pNdb) == 0);
// Update
CHECK(hugoOps.startTransaction(pNdb) == 0);
- for (int i = 0; i < 10; i++)
+ for (i = 0; i < 10; i++)
CHECK(hugoOps.pkUpdateRecord(pNdb, i) == 0);
CHECK(hugoOps.execute_NoCommit(pNdb) == 0);
CHECK(hugoOps.closeTransaction(pNdb) == 0);
// Delete
CHECK(hugoOps.startTransaction(pNdb) == 0);
- for (int i = 0; i < 10; i++)
+ for (i = 0; i < 10; i++)
CHECK(hugoOps.pkDeleteRecord(pNdb, i) == 0);
CHECK(hugoOps.execute_NoCommit(pNdb) == 0);
CHECK(hugoOps.closeTransaction(pNdb) == 0);
// Try to insert, record should already exist
CHECK(hugoOps.startTransaction(pNdb) == 0);
- for (int i = 0; i < 10; i++)
+ for (i = 0; i < 10; i++)
CHECK(hugoOps.pkInsertRecord(pNdb, i) == 0);
CHECK(hugoOps.execute_Commit(pNdb) == 630);
CHECK(hugoOps.closeTransaction(pNdb) == 0);
@@ -772,14 +781,14 @@ int runCheckRollbackDeleteMultiple(NDBT_Context* ctx, NDBT_Step* step){
CHECK(hugoOps.closeTransaction(pNdb) == 0);
Uint32 updatesValue = 0;
-
+ Uint32 j;
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.execute_NoCommit(pNdb) == 0);
- for(Uint32 j = 0; j<10; j++){
+ for(j = 0; j<10; j++){
// Update record 5 - 10
updatesValue++;
CHECK(hugoOps.pkUpdateRecord(pNdb, 5, 10, updatesValue) == 0);
@@ -790,7 +799,7 @@ int runCheckRollbackDeleteMultiple(NDBT_Context* ctx, NDBT_Step* step){
CHECK(hugoOps.verifyUpdatesValue(updatesValue) == 0);
}
- for(Uint32 j = 0; j<10; j++){
+ for(j = 0; j<10; j++){
// Delete record 5 - 10 times
CHECK(hugoOps.pkDeleteRecord(pNdb, 5, 10) == 0);
CHECK(hugoOps.execute_NoCommit(pNdb) == 0);
@@ -953,6 +962,7 @@ int runMassiveRollback(NDBT_Context* ctx, NDBT_Step* step){
const Uint32 OPS_TOTAL = 4096;
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++){
@@ -963,7 +973,12 @@ int runMassiveRollback(NDBT_Context* ctx, NDBT_Step* step){
if(result != NDBT_OK){
break;
}
- CHECK(hugoOps.execute_NoCommit(pNdb) == 0);
+ res = hugoOps.execute_NoCommit(pNdb);
+ if(res != 0){
+ NdbError err = pNdb->getNdbError(res);
+ CHECK(err.classification == NdbError::TimeoutExpired);
+ break;
+ }
}
if(result != NDBT_OK){
break;
@@ -1255,6 +1270,11 @@ TESTCASE("MassiveRollback2",
INITIALIZER(runMassiveRollback2);
FINALIZER(runClearTable2);
}
+TESTCASE("MassiveTransaction",
+ "Test very large insert transaction"){
+ INITIALIZER(runLoadTable2);
+ FINALIZER(runClearTable2);
+}
NDBT_TESTSUITE_END(testBasic);
int main(int argc, const char** argv){
diff --git a/ndb/test/ndbapi/testBlobs.cpp b/ndb/test/ndbapi/testBlobs.cpp
index 001ec83630a..64881ca39ab 100644
--- a/ndb/test/ndbapi/testBlobs.cpp
+++ b/ndb/test/ndbapi/testBlobs.cpp
@@ -38,6 +38,7 @@ struct Bcol {
};
struct Opt {
+ unsigned m_batch;
bool m_core;
bool m_dbg;
bool m_dbgall;
@@ -46,7 +47,8 @@ struct Opt {
unsigned m_parts;
unsigned m_rows;
unsigned m_seed;
- char m_skip[255];
+ const char* m_skip;
+ const char* m_style;
// metadata
const char* m_tname;
const char* m_x1name; // hash index
@@ -60,6 +62,7 @@ struct Opt {
int m_bug;
int (*m_bugtest)();
Opt() :
+ m_batch(7),
m_core(false),
m_dbg(false),
m_dbgall(false),
@@ -68,6 +71,8 @@ struct Opt {
m_parts(10),
m_rows(100),
m_seed(0),
+ m_skip(""),
+ m_style("012"),
// metadata
m_tname("TBLOB1"),
m_x1name("TBLOB1X1"),
@@ -80,7 +85,6 @@ struct Opt {
// bugs
m_bug(0),
m_bugtest(0) {
- memset(m_skip, false, sizeof(m_skip));
}
};
@@ -92,6 +96,7 @@ printusage()
Opt d;
ndbout
<< "usage: testBlobs options [default/max]" << endl
+ << " -batch N number of pk ops in batch [" << d.m_batch << "]" << endl
<< " -core dump core on error" << endl
<< " -dbg print debug" << endl
<< " -dbgall print also NDB API debug (if compiled in)" << endl
@@ -101,7 +106,8 @@ printusage()
<< " -parts N max parts in blob value [" << d.m_parts << "]" << endl
<< " -rows N number of rows [" << d.m_rows << "]" << endl
<< " -seed N random seed 0=loop number [" << d.m_seed << "]" << endl
- << " -skip xxx skip these tests (see list)" << endl
+ << " -skip xxx skip these tests (see list) [" << d.m_skip << endl
+ << " -style xxx access styles to test (see list) [" << d.m_style << "]" << endl
<< "metadata" << endl
<< " -pk2len N length of PK2 [" << d.m_pk2len << "/" << g_max_pk2len <<"]" << endl
<< " -oneblob only 1 blob attribute [default 2]" << endl
@@ -111,8 +117,10 @@ printusage()
<< " s table scans" << endl
<< " r ordered index scans" << endl
<< " u update blob value" << endl
- << " v getValue / setValue" << endl
- << " w readData / writeData" << endl
+ << "access styles for -style" << endl
+ << " 0 getValue / setValue" << endl
+ << " 1 setActiveHook" << endl
+ << " 2 readData / writeData" << endl
<< "bug tests (no blob test)" << endl
<< " -bug 4088 ndb api hang with mixed ops on index table" << endl
<< " -bug 2222 delete + write gives 626" << endl
@@ -122,11 +130,16 @@ printusage()
static Opt g_opt;
-static char&
-skip(unsigned x)
+static bool
+skipcase(int x)
{
- assert(x < sizeof(g_opt.m_skip));
- return g_opt.m_skip[x];
+ return strchr(g_opt.m_skip, x) != 0;
+}
+
+static bool
+skipstyle(int x)
+{
+ return strchr(g_opt.m_style, '0' + x) == 0;
}
static Ndb* g_ndb = 0;
@@ -138,11 +151,12 @@ static NdbScanOperation* g_ops = 0;
static NdbBlob* g_bh1 = 0;
static NdbBlob* g_bh2 = 0;
static bool g_printerror = true;
+static unsigned g_loop = 0;
static void
printerror(int line, const char* msg)
{
- ndbout << "line " << line << ": " << msg << " failed" << endl;
+ ndbout << "line " << line << " FAIL " << msg << endl;
if (! g_printerror) {
return;
}
@@ -205,6 +219,7 @@ static int
createTable()
{
NdbDictionary::Table tab(g_opt.m_tname);
+ tab.setLogging(false);
// col PK1 - Uint32
{ NdbDictionary::Column col("PK1");
col.setType(NdbDictionary::Column::Unsigned);
@@ -228,11 +243,11 @@ createTable()
col.setPrimaryKey(true);
tab.addColumn(col);
}
- // col BL2 - Clob nullable
+ // col BL2 - Text nullable
if (! g_opt.m_oneblob)
{ NdbDictionary::Column col("BL2");
const Bcol& b = g_opt.m_blob2;
- col.setType(NdbDictionary::Column::Clob);
+ col.setType(NdbDictionary::Column::Text);
col.setNullable(true);
col.setInlineSize(b.m_inline);
col.setPartSize(b.m_partsize);
@@ -245,6 +260,7 @@ createTable()
if (g_opt.m_pk2len != 0)
{ NdbDictionary::Index idx(g_opt.m_x1name);
idx.setType(NdbDictionary::Index::UniqueHashIndex);
+ idx.setLogging(false);
idx.setTable(g_opt.m_tname);
idx.addColumnName("PK2");
CHK(g_dic->createIndex(idx) == 0);
@@ -281,7 +297,7 @@ struct Bval {
m_buf = new char [m_buflen];
trash();
}
- void copy(const Bval& v) {
+ void copyfrom(const Bval& v) {
m_len = v.m_len;
delete [] m_val;
if (v.m_val == 0)
@@ -313,10 +329,10 @@ struct Tup {
m_blob1.alloc(g_opt.m_blob1.m_inline + g_opt.m_blob1.m_partsize * g_opt.m_parts);
m_blob2.alloc(g_opt.m_blob2.m_inline + g_opt.m_blob2.m_partsize * g_opt.m_parts);
}
- void copy(const Tup& tup) {
+ void copyfrom(const Tup& tup) {
assert(m_pk1 == tup.m_pk1);
- m_blob1.copy(tup.m_blob1);
- m_blob2.copy(tup.m_blob2);
+ m_blob1.copyfrom(tup.m_blob1);
+ m_blob2.copyfrom(tup.m_blob2);
}
private:
Tup(const Tup&);
@@ -358,6 +374,14 @@ calcBval(const Bcol& b, Bval& v, bool keepsize)
}
static void
+calcBval(Tup& tup, bool keepsize)
+{
+ calcBval(g_opt.m_blob1, tup.m_blob1, keepsize);
+ if (! g_opt.m_oneblob)
+ calcBval(g_opt.m_blob2, tup.m_blob2, keepsize);
+}
+
+static void
calcTups(bool keepsize)
{
for (unsigned k = 0; k < g_opt.m_rows; k++) {
@@ -371,31 +395,59 @@ calcTups(bool keepsize)
tup.m_pk2[i] = 'a' + i % 26;
}
}
- calcBval(g_opt.m_blob1, tup.m_blob1, keepsize);
- if (! g_opt.m_oneblob)
- calcBval(g_opt.m_blob2, tup.m_blob2, keepsize);
+ calcBval(tup, keepsize);
}
}
// blob handle ops
static int
+getBlobHandles(NdbOperation* opr)
+{
+ CHK((g_bh1 = opr->getBlobHandle("BL1")) != 0);
+ if (! g_opt.m_oneblob)
+ CHK((g_bh2 = opr->getBlobHandle("BL2")) != 0);
+ return 0;
+}
+
+static int
+getBlobHandles(NdbIndexOperation* opx)
+{
+ CHK((g_bh1 = opx->getBlobHandle("BL1")) != 0);
+ if (! g_opt.m_oneblob)
+ CHK((g_bh2 = opx->getBlobHandle("BL2")) != 0);
+ return 0;
+}
+
+static int
+getBlobHandles(NdbScanOperation* ops)
+{
+ CHK((g_bh1 = ops->getBlobHandle("BL1")) != 0);
+ if (! g_opt.m_oneblob)
+ CHK((g_bh2 = ops->getBlobHandle("BL2")) != 0);
+ return 0;
+}
+
+static int
getBlobLength(NdbBlob* h, unsigned& len)
{
Uint64 len2 = (unsigned)-1;
CHK(h->getLength(len2) == 0);
len = (unsigned)len2;
assert(len == len2);
+ DBG("getBlobLength " << h->getColumn()->getName() << " len=" << len);
return 0;
}
+// setValue / getValue
+
static int
setBlobValue(NdbBlob* h, const Bval& v)
{
bool null = (v.m_val == 0);
bool isNull;
unsigned len;
- DBG("set " << h->getColumn()->getName() << " len=" << v.m_len << " null=" << null);
+ DBG("setValue " << h->getColumn()->getName() << " len=" << v.m_len << " null=" << null);
if (null) {
CHK(h->setNull() == 0);
isNull = false;
@@ -410,10 +462,19 @@ setBlobValue(NdbBlob* h, const Bval& v)
}
static int
+setBlobValue(const Tup& tup)
+{
+ CHK(setBlobValue(g_bh1, tup.m_blob1) == 0);
+ if (! g_opt.m_oneblob)
+ CHK(setBlobValue(g_bh2, tup.m_blob2) == 0);
+ return 0;
+}
+
+static int
getBlobValue(NdbBlob* h, const Bval& v)
{
bool null = (v.m_val == 0);
- DBG("get " << h->getColumn()->getName() << " len=" << v.m_len << " null=" << null);
+ DBG("getValue " << h->getColumn()->getName() << " buflen=" << v.m_buflen);
CHK(h->getValue(v.m_buf, v.m_buflen) == 0);
return 0;
}
@@ -456,6 +517,8 @@ verifyBlobValue(const Tup& tup)
return 0;
}
+// readData / writeData
+
static int
writeBlobData(NdbBlob* h, const Bval& v)
{
@@ -469,6 +532,7 @@ writeBlobData(NdbBlob* h, const Bval& v)
CHK(h->getNull(isNull) == 0 && isNull == true);
CHK(getBlobLength(h, len) == 0 && len == 0);
} else {
+ CHK(h->truncate(v.m_len) == 0);
unsigned n = 0;
do {
unsigned m = g_opt.m_full ? v.m_len : urandom(v.m_len + 1);
@@ -487,6 +551,15 @@ writeBlobData(NdbBlob* h, const Bval& v)
}
static int
+writeBlobData(const Tup& tup)
+{
+ CHK(writeBlobData(g_bh1, tup.m_blob1) == 0);
+ if (! g_opt.m_oneblob)
+ CHK(writeBlobData(g_bh2, tup.m_blob2) == 0);
+ return 0;
+}
+
+static int
readBlobData(NdbBlob* h, const Bval& v)
{
bool null = (v.m_val == 0);
@@ -531,6 +604,71 @@ readBlobData(const Tup& tup)
return 0;
}
+// hooks
+
+static NdbBlob::ActiveHook blobWriteHook;
+
+static int
+blobWriteHook(NdbBlob* h, void* arg)
+{
+ DBG("blobWriteHook");
+ Bval& v = *(Bval*)arg;
+ CHK(writeBlobData(h, v) == 0);
+ return 0;
+}
+
+static int
+setBlobWriteHook(NdbBlob* h, Bval& v)
+{
+ DBG("setBlobWriteHook");
+ CHK(h->setActiveHook(blobWriteHook, &v) == 0);
+ return 0;
+}
+
+static int
+setBlobWriteHook(Tup& tup)
+{
+ CHK(setBlobWriteHook(g_bh1, tup.m_blob1) == 0);
+ if (! g_opt.m_oneblob)
+ CHK(setBlobWriteHook(g_bh2, tup.m_blob2) == 0);
+ return 0;
+}
+
+static NdbBlob::ActiveHook blobReadHook;
+
+// no PK yet to identify tuple so just read the value
+static int
+blobReadHook(NdbBlob* h, void* arg)
+{
+ DBG("blobReadHook");
+ Bval& v = *(Bval*)arg;
+ unsigned len;
+ CHK(getBlobLength(h, len) == 0);
+ v.alloc(len);
+ Uint32 maxlen = 0xffffffff;
+ CHK(h->readData(v.m_buf, maxlen) == 0);
+ DBG("read " << maxlen << " bytes");
+ CHK(len == maxlen);
+ return 0;
+}
+
+static int
+setBlobReadHook(NdbBlob* h, Bval& v)
+{
+ DBG("setBlobReadHook");
+ CHK(h->setActiveHook(blobReadHook, &v) == 0);
+ return 0;
+}
+
+static int
+setBlobReadHook(Tup& tup)
+{
+ CHK(setBlobReadHook(g_bh1, tup.m_blob1) == 0);
+ if (! g_opt.m_oneblob)
+ CHK(setBlobReadHook(g_bh2, tup.m_blob2) == 0);
+ return 0;
+}
+
// verify blob data
static int
@@ -540,7 +678,11 @@ verifyHeadInline(const Bcol& c, const Bval& v, NdbRecAttr* ra)
CHK(ra->isNULL() == 1);
} else {
CHK(ra->isNULL() == 0);
- CHK(ra->u_64_value() == v.m_len);
+ const NdbBlob::Head* head = (const NdbBlob::Head*)ra->aRef();
+ CHK(head->length == v.m_len);
+ const char* data = (const char*)(head + 1);
+ for (unsigned i = 0; i < head->length && i < c.m_inline; i++)
+ CHK(data[i] == v.m_val[i]);
}
return 0;
}
@@ -548,7 +690,7 @@ verifyHeadInline(const Bcol& c, const Bval& v, NdbRecAttr* ra)
static int
verifyHeadInline(const Tup& tup)
{
- DBG("verifyHeadInline pk1=" << tup.m_pk1);
+ DBG("verifyHeadInline pk1=" << hex << tup.m_pk1);
CHK((g_con = g_ndb->startTransaction()) != 0);
CHK((g_opr = g_con->getNdbOperation(g_opt.m_tname)) != 0);
CHK(g_opr->readTuple() == 0);
@@ -580,17 +722,18 @@ verifyHeadInline(const Tup& tup)
static int
verifyBlobTable(const Bcol& b, const Bval& v, Uint32 pk1, bool exists)
{
- DBG("verify " << b.m_btname << " pk1=" << pk1);
+ DBG("verify " << b.m_btname << " pk1=" << hex << pk1);
NdbRecAttr* ra_pk;
NdbRecAttr* ra_part;
NdbRecAttr* ra_data;
+ NdbResultSet* rs;
CHK((g_con = g_ndb->startTransaction()) != 0);
- CHK((g_opr = g_con->getNdbOperation(b.m_btname)) != 0);
- CHK(g_opr->openScanRead() == 0);
- CHK((ra_pk = g_opr->getValue("PK")) != 0);
- CHK((ra_part = g_opr->getValue("PART")) != 0);
- CHK((ra_data = g_opr->getValue("DATA")) != 0);
- CHK(g_con->executeScan() == 0);
+ CHK((g_ops = g_con->getNdbScanOperation(b.m_btname)) != 0);
+ CHK((rs = g_ops->readTuples()) != 0);
+ CHK((ra_pk = g_ops->getValue("PK")) != 0);
+ CHK((ra_part = g_ops->getValue("PART")) != 0);
+ CHK((ra_data = g_ops->getValue("DATA")) != 0);
+ CHK(g_con->execute(NoCommit) == 0);
unsigned partcount;
if (! exists || v.m_len <= b.m_inline)
partcount = 0;
@@ -600,7 +743,7 @@ verifyBlobTable(const Bcol& b, const Bval& v, Uint32 pk1, bool exists)
memset(seen, 0, partcount);
while (1) {
int ret;
- CHK((ret = g_con->nextScanResult()) == 0 || ret == 1);
+ CHK((ret = rs->nextResult()) == 0 || ret == 1);
if (ret == 1)
break;
if (pk1 != ra_pk->u_32_value())
@@ -620,7 +763,7 @@ verifyBlobTable(const Bcol& b, const Bval& v, Uint32 pk1, bool exists)
for (unsigned i = 0; i < partcount; i++)
CHK(seen[i] == 1);
g_ndb->closeTransaction(g_con);
- g_opr = 0;
+ g_ops = 0;
g_con = 0;
return 0;
}
@@ -639,7 +782,7 @@ verifyBlob()
{
for (unsigned k = 0; k < g_opt.m_rows; k++) {
const Tup& tup = g_tups[k];
- DBG("verifyBlob pk1=" << tup.m_pk1);
+ DBG("verifyBlob pk1=" << hex << tup.m_pk1);
CHK(verifyHeadInline(tup) == 0);
CHK(verifyBlobTable(tup) == 0);
}
@@ -648,105 +791,120 @@ verifyBlob()
// operations
+static const char* stylename[3] = {
+ "style=getValue/setValue",
+ "style=setActiveHook",
+ "style=readData/writeData"
+};
+
+// pk ops
+
static int
-insertPk(bool rw)
+insertPk(int style)
{
- DBG("--- insertPk ---");
+ DBG("--- insertPk " << stylename[style] << " ---");
+ unsigned n = 0;
+ CHK((g_con = g_ndb->startTransaction()) != 0);
for (unsigned k = 0; k < g_opt.m_rows; k++) {
Tup& tup = g_tups[k];
- DBG("insertPk pk1=" << tup.m_pk1);
- CHK((g_con = g_ndb->startTransaction()) != 0);
+ DBG("insertPk pk1=" << hex << tup.m_pk1);
CHK((g_opr = g_con->getNdbOperation(g_opt.m_tname)) != 0);
CHK(g_opr->insertTuple() == 0);
CHK(g_opr->equal("PK1", tup.m_pk1) == 0);
if (g_opt.m_pk2len != 0)
CHK(g_opr->equal("PK2", tup.m_pk2) == 0);
- CHK((g_bh1 = g_opr->getBlobHandle("BL1")) != 0);
- if (! g_opt.m_oneblob)
- CHK((g_bh2 = g_opr->getBlobHandle("BL2")) != 0);
- if (! rw) {
- CHK(setBlobValue(g_bh1, tup.m_blob1) == 0);
- if (! g_opt.m_oneblob)
- CHK(setBlobValue(g_bh2, tup.m_blob2) == 0);
+ CHK(getBlobHandles(g_opr) == 0);
+ if (style == 0) {
+ CHK(setBlobValue(tup) == 0);
+ } else if (style == 1) {
+ // non-nullable must be set
+ CHK(g_bh1->setValue("", 0) == 0);
+ CHK(setBlobWriteHook(tup) == 0);
} else {
// non-nullable must be set
CHK(g_bh1->setValue("", 0) == 0);
CHK(g_con->execute(NoCommit) == 0);
- CHK(writeBlobData(g_bh1, tup.m_blob1) == 0);
- if (! g_opt.m_oneblob)
- CHK(writeBlobData(g_bh2, tup.m_blob2) == 0);
+ CHK(writeBlobData(tup) == 0);
+ }
+ // just another trap
+ if (urandom(10) == 0)
+ CHK(g_con->execute(NoCommit) == 0);
+ if (++n == g_opt.m_batch) {
+ CHK(g_con->execute(Commit) == 0);
+ g_ndb->closeTransaction(g_con);
+ CHK((g_con = g_ndb->startTransaction()) != 0);
+ n = 0;
}
- CHK(g_con->execute(Commit) == 0);
- g_ndb->closeTransaction(g_con);
g_opr = 0;
- g_con = 0;
tup.m_exists = true;
}
+ if (n != 0) {
+ CHK(g_con->execute(Commit) == 0);
+ n = 0;
+ }
+ g_ndb->closeTransaction(g_con);
+ g_con = 0;
return 0;
}
static int
-updatePk(bool rw)
+readPk(int style)
{
- DBG("--- updatePk ---");
+ DBG("--- readPk " << stylename[style] << " ---");
for (unsigned k = 0; k < g_opt.m_rows; k++) {
Tup& tup = g_tups[k];
- DBG("updatePk pk1=" << tup.m_pk1);
+ DBG("readPk pk1=" << hex << tup.m_pk1);
CHK((g_con = g_ndb->startTransaction()) != 0);
CHK((g_opr = g_con->getNdbOperation(g_opt.m_tname)) != 0);
- CHK(g_opr->updateTuple() == 0);
+ CHK(g_opr->readTuple() == 0);
CHK(g_opr->equal("PK1", tup.m_pk1) == 0);
if (g_opt.m_pk2len != 0)
CHK(g_opr->equal("PK2", tup.m_pk2) == 0);
- CHK((g_bh1 = g_opr->getBlobHandle("BL1")) != 0);
- if (! g_opt.m_oneblob)
- CHK((g_bh2 = g_opr->getBlobHandle("BL2")) != 0);
- if (! rw) {
- CHK(setBlobValue(g_bh1, tup.m_blob1) == 0);
- if (! g_opt.m_oneblob)
- CHK(setBlobValue(g_bh2, tup.m_blob2) == 0);
+ CHK(getBlobHandles(g_opr) == 0);
+ if (style == 0) {
+ CHK(getBlobValue(tup) == 0);
+ } else if (style == 1) {
+ CHK(setBlobReadHook(tup) == 0);
} else {
CHK(g_con->execute(NoCommit) == 0);
- CHK(writeBlobData(g_bh1, tup.m_blob1) == 0);
- if (! g_opt.m_oneblob)
- CHK(writeBlobData(g_bh2, tup.m_blob2) == 0);
+ CHK(readBlobData(tup) == 0);
}
CHK(g_con->execute(Commit) == 0);
+ if (style == 0 || style == 1) {
+ CHK(verifyBlobValue(tup) == 0);
+ }
g_ndb->closeTransaction(g_con);
g_opr = 0;
g_con = 0;
- tup.m_exists = true;
}
return 0;
}
static int
-updateIdx(bool rw)
+updatePk(int style)
{
- DBG("--- updateIdx ---");
+ DBG("--- updatePk " << stylename[style] << " ---");
for (unsigned k = 0; k < g_opt.m_rows; k++) {
Tup& tup = g_tups[k];
- DBG("updateIdx pk1=" << tup.m_pk1);
+ DBG("updatePk pk1=" << hex << tup.m_pk1);
CHK((g_con = g_ndb->startTransaction()) != 0);
- CHK((g_opx = g_con->getNdbIndexOperation(g_opt.m_x1name, g_opt.m_tname)) != 0);
- CHK(g_opx->updateTuple() == 0);
- CHK(g_opx->equal("PK2", tup.m_pk2) == 0);
- CHK((g_bh1 = g_opx->getBlobHandle("BL1")) != 0);
- if (! g_opt.m_oneblob)
- CHK((g_bh2 = g_opx->getBlobHandle("BL2")) != 0);
- if (! rw) {
- CHK(setBlobValue(g_bh1, tup.m_blob1) == 0);
- if (! g_opt.m_oneblob)
- CHK(setBlobValue(g_bh2, tup.m_blob2) == 0);
+ CHK((g_opr = g_con->getNdbOperation(g_opt.m_tname)) != 0);
+ CHK(g_opr->updateTuple() == 0);
+ CHK(g_opr->equal("PK1", tup.m_pk1) == 0);
+ if (g_opt.m_pk2len != 0)
+ CHK(g_opr->equal("PK2", tup.m_pk2) == 0);
+ CHK(getBlobHandles(g_opr) == 0);
+ if (style == 0) {
+ CHK(setBlobValue(tup) == 0);
+ } else if (style == 1) {
+ CHK(setBlobWriteHook(tup) == 0);
} else {
CHK(g_con->execute(NoCommit) == 0);
- CHK(writeBlobData(g_bh1, tup.m_blob1) == 0);
- if (! g_opt.m_oneblob)
- CHK(writeBlobData(g_bh2, tup.m_blob2) == 0);
+ CHK(writeBlobData(tup) == 0);
}
CHK(g_con->execute(Commit) == 0);
g_ndb->closeTransaction(g_con);
- g_opx = 0;
+ g_opr = 0;
g_con = 0;
tup.m_exists = true;
}
@@ -754,74 +912,115 @@ updateIdx(bool rw)
}
static int
-readPk(bool rw)
+deletePk()
{
- DBG("--- readPk ---");
+ DBG("--- deletePk ---");
for (unsigned k = 0; k < g_opt.m_rows; k++) {
Tup& tup = g_tups[k];
- DBG("readPk pk1=" << tup.m_pk1);
+ DBG("deletePk pk1=" << hex << tup.m_pk1);
CHK((g_con = g_ndb->startTransaction()) != 0);
CHK((g_opr = g_con->getNdbOperation(g_opt.m_tname)) != 0);
- CHK(g_opr->readTuple() == 0);
+ CHK(g_opr->deleteTuple() == 0);
CHK(g_opr->equal("PK1", tup.m_pk1) == 0);
if (g_opt.m_pk2len != 0)
CHK(g_opr->equal("PK2", tup.m_pk2) == 0);
- CHK((g_bh1 = g_opr->getBlobHandle("BL1")) != 0);
- if (! g_opt.m_oneblob)
- CHK((g_bh2 = g_opr->getBlobHandle("BL2")) != 0);
- if (! rw) {
+ CHK(g_con->execute(Commit) == 0);
+ g_ndb->closeTransaction(g_con);
+ g_opr = 0;
+ g_con = 0;
+ tup.m_exists = false;
+ }
+ return 0;
+}
+
+// hash index ops
+
+static int
+readIdx(int style)
+{
+ DBG("--- readIdx " << stylename[style] << " ---");
+ for (unsigned k = 0; k < g_opt.m_rows; k++) {
+ Tup& tup = g_tups[k];
+ DBG("readIdx pk1=" << hex << tup.m_pk1);
+ CHK((g_con = g_ndb->startTransaction()) != 0);
+ CHK((g_opx = g_con->getNdbIndexOperation(g_opt.m_x1name, g_opt.m_tname)) != 0);
+ CHK(g_opx->readTuple() == 0);
+ CHK(g_opx->equal("PK2", tup.m_pk2) == 0);
+ CHK(getBlobHandles(g_opx) == 0);
+ if (style == 0) {
CHK(getBlobValue(tup) == 0);
+ } else if (style == 1) {
+ CHK(setBlobReadHook(tup) == 0);
} else {
CHK(g_con->execute(NoCommit) == 0);
CHK(readBlobData(tup) == 0);
}
CHK(g_con->execute(Commit) == 0);
- if (! rw) {
+ if (style == 0 || style == 1) {
CHK(verifyBlobValue(tup) == 0);
}
g_ndb->closeTransaction(g_con);
- g_opr = 0;
+ g_opx = 0;
g_con = 0;
}
return 0;
}
static int
-readIdx(bool rw)
+updateIdx(int style)
{
- DBG("--- readIdx ---");
+ DBG("--- updateIdx " << stylename[style] << " ---");
for (unsigned k = 0; k < g_opt.m_rows; k++) {
Tup& tup = g_tups[k];
- DBG("readIdx pk1=" << tup.m_pk1);
+ DBG("updateIdx pk1=" << hex << tup.m_pk1);
CHK((g_con = g_ndb->startTransaction()) != 0);
CHK((g_opx = g_con->getNdbIndexOperation(g_opt.m_x1name, g_opt.m_tname)) != 0);
- CHK(g_opx->readTuple() == 0);
+ CHK(g_opx->updateTuple() == 0);
CHK(g_opx->equal("PK2", tup.m_pk2) == 0);
- CHK((g_bh1 = g_opx->getBlobHandle("BL1")) != 0);
- if (! g_opt.m_oneblob)
- CHK((g_bh2 = g_opx->getBlobHandle("BL2")) != 0);
- if (! rw) {
- CHK(getBlobValue(tup) == 0);
+ CHK(getBlobHandles(g_opx) == 0);
+ if (style == 0) {
+ CHK(setBlobValue(tup) == 0);
+ } else if (style == 1) {
+ CHK(setBlobWriteHook(tup) == 0);
} else {
CHK(g_con->execute(NoCommit) == 0);
- CHK(readBlobData(tup) == 0);
+ CHK(writeBlobData(tup) == 0);
}
CHK(g_con->execute(Commit) == 0);
- if (! rw) {
- CHK(verifyBlobValue(tup) == 0);
- }
g_ndb->closeTransaction(g_con);
g_opx = 0;
g_con = 0;
+ tup.m_exists = true;
+ }
+ return 0;
+}
+
+static int
+deleteIdx()
+{
+ DBG("--- deleteIdx ---");
+ for (unsigned k = 0; k < g_opt.m_rows; k++) {
+ Tup& tup = g_tups[k];
+ DBG("deleteIdx pk1=" << hex << tup.m_pk1);
+ CHK((g_con = g_ndb->startTransaction()) != 0);
+ CHK((g_opx = g_con->getNdbIndexOperation(g_opt.m_x1name, g_opt.m_tname)) != 0);
+ CHK(g_opx->deleteTuple() == 0);
+ CHK(g_opx->equal("PK2", tup.m_pk2) == 0);
+ CHK(g_con->execute(Commit) == 0);
+ g_ndb->closeTransaction(g_con);
+ g_opx = 0;
+ g_con = 0;
+ tup.m_exists = false;
}
return 0;
}
+// scan ops table and index
+
static int
-readScan(bool rw, bool idx)
+readScan(int style, bool idx)
{
- const char* func = ! idx ? "scan read table" : "scan read index";
- DBG("--- " << func << " ---");
+ DBG("--- " << "readScan" << (idx ? "Idx" : "") << " " << stylename[style] << " ---");
Tup tup;
tup.alloc(); // allocate buffers
NdbResultSet* rs;
@@ -829,17 +1028,17 @@ readScan(bool rw, bool idx)
if (! idx) {
CHK((g_ops = g_con->getNdbScanOperation(g_opt.m_tname)) != 0);
} else {
- CHK((g_ops = g_con->getNdbScanOperation(g_opt.m_x2name, g_opt.m_tname)) != 0);
+ CHK((g_ops = g_con->getNdbIndexScanOperation(g_opt.m_x2name, g_opt.m_tname)) != 0);
}
- CHK((rs = g_ops->readTuples(240, NdbScanOperation::LM_Exclusive)) != 0);
+ CHK((rs = g_ops->readTuples(NdbScanOperation::LM_Exclusive)) != 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);
- CHK((g_bh1 = g_ops->getBlobHandle("BL1")) != 0);
- if (! g_opt.m_oneblob)
- CHK((g_bh2 = g_ops->getBlobHandle("BL2")) != 0);
- if (! rw) {
+ CHK(getBlobHandles(g_ops) == 0);
+ if (style == 0) {
CHK(getBlobValue(tup) == 0);
+ } else if (style == 1) {
+ CHK(setBlobReadHook(tup) == 0);
}
CHK(g_con->execute(NoCommit) == 0);
unsigned rows = 0;
@@ -850,11 +1049,14 @@ readScan(bool rw, bool idx)
CHK((ret = rs->nextResult(true)) == 0 || ret == 1);
if (ret == 1)
break;
- DBG(func << " pk1=" << tup.m_pk1);
+ DBG("readScan" << (idx ? "Idx" : "") << " pk1=" << hex << tup.m_pk1);
Uint32 k = tup.m_pk1 - g_opt.m_pk1off;
CHK(k < g_opt.m_rows && g_tups[k].m_exists);
- tup.copy(g_tups[k]);
- if (! rw) {
+ tup.copyfrom(g_tups[k]);
+ if (style == 0) {
+ CHK(verifyBlobValue(tup) == 0);
+ } else if (style == 1) {
+ // execute ops generated by callbacks, if any
CHK(verifyBlobValue(tup) == 0);
} else {
CHK(readBlobData(tup) == 0);
@@ -869,61 +1071,72 @@ readScan(bool rw, bool idx)
}
static int
-deletePk()
+updateScan(int style, bool idx)
{
- DBG("--- deletePk ---");
- for (unsigned k = 0; k < g_opt.m_rows; k++) {
- Tup& tup = g_tups[k];
- DBG("deletePk pk1=" << tup.m_pk1);
- CHK((g_con = g_ndb->startTransaction()) != 0);
- CHK((g_opr = g_con->getNdbOperation(g_opt.m_tname)) != 0);
- CHK(g_opr->deleteTuple() == 0);
- CHK(g_opr->equal("PK1", tup.m_pk1) == 0);
- if (g_opt.m_pk2len != 0)
- CHK(g_opr->equal("PK2", tup.m_pk2) == 0);
- CHK(g_con->execute(Commit) == 0);
- g_ndb->closeTransaction(g_con);
- g_opr = 0;
- g_con = 0;
- tup.m_exists = false;
+ DBG("--- " << "updateScan" << (idx ? "Idx" : "") << " " << stylename[style] << " ---");
+ Tup tup;
+ tup.alloc(); // allocate buffers
+ NdbResultSet* rs;
+ CHK((g_con = g_ndb->startTransaction()) != 0);
+ if (! idx) {
+ CHK((g_ops = g_con->getNdbScanOperation(g_opt.m_tname)) != 0);
+ } else {
+ CHK((g_ops = g_con->getNdbIndexScanOperation(g_opt.m_x2name, g_opt.m_tname)) != 0);
}
- return 0;
-}
-
-static int
-deleteIdx()
-{
- DBG("--- deleteIdx ---");
- for (unsigned k = 0; k < g_opt.m_rows; k++) {
- Tup& tup = g_tups[k];
- DBG("deleteIdx pk1=" << tup.m_pk1);
- CHK((g_con = g_ndb->startTransaction()) != 0);
- CHK((g_opx = g_con->getNdbIndexOperation(g_opt.m_x1name, g_opt.m_tname)) != 0);
- CHK(g_opx->deleteTuple() == 0);
- CHK(g_opx->equal("PK2", tup.m_pk2) == 0);
- CHK(g_con->execute(Commit) == 0);
- g_ndb->closeTransaction(g_con);
- g_opx = 0;
- g_con = 0;
- tup.m_exists = false;
+ CHK((rs = g_ops->readTuples(NdbScanOperation::LM_Exclusive)) != 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);
+ CHK(g_con->execute(NoCommit) == 0);
+ unsigned rows = 0;
+ while (1) {
+ int ret;
+ tup.m_pk1 = (Uint32)-1;
+ memset(tup.m_pk2, 'x', g_opt.m_pk2len);
+ CHK((ret = rs->nextResult(true)) == 0 || ret == 1);
+ if (ret == 1)
+ break;
+ DBG("updateScan" << (idx ? "Idx" : "") << " pk1=" << hex << tup.m_pk1);
+ Uint32 k = tup.m_pk1 - g_opt.m_pk1off;
+ CHK(k < g_opt.m_rows && g_tups[k].m_exists);
+ // calculate new blob values
+ calcBval(g_tups[k], false);
+ tup.copyfrom(g_tups[k]);
+ CHK((g_opr = rs->updateTuple()) != 0);
+ CHK(getBlobHandles(g_opr) == 0);
+ if (style == 0) {
+ CHK(setBlobValue(tup) == 0);
+ } else if (style == 1) {
+ CHK(setBlobWriteHook(tup) == 0);
+ } else {
+ CHK(g_con->execute(NoCommit) == 0);
+ CHK(writeBlobData(tup) == 0);
+ }
+ CHK(g_con->execute(NoCommit) == 0);
+ g_opr = 0;
+ rows++;
}
+ CHK(g_con->execute(Commit) == 0);
+ g_ndb->closeTransaction(g_con);
+ g_con = 0;
+ g_ops = 0;
+ CHK(g_opt.m_rows == rows);
return 0;
}
static int
deleteScan(bool idx)
{
- const char* func = ! idx ? "scan delete table" : "scan delete index";
- DBG("--- " << func << " ---");
+ DBG("--- " << "deleteScan" << (idx ? "Idx" : "") << " ---");
Tup tup;
NdbResultSet* rs;
CHK((g_con = g_ndb->startTransaction()) != 0);
if (! idx) {
CHK((g_ops = g_con->getNdbScanOperation(g_opt.m_tname)) != 0);
} else {
- CHK((g_ops = g_con->getNdbScanOperation(g_opt.m_x2name, g_opt.m_tname)) != 0);
+ CHK((g_ops = g_con->getNdbIndexScanOperation(g_opt.m_x2name, g_opt.m_tname)) != 0);
}
- CHK((rs = g_ops->readTuples(240, NdbScanOperation::LM_Exclusive)) != 0);
+ CHK((rs = g_ops->readTuples(NdbScanOperation::LM_Exclusive)) != 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);
@@ -936,7 +1149,7 @@ deleteScan(bool idx)
CHK((ret = rs->nextResult()) == 0 || ret == 1);
if (ret == 1)
break;
- DBG(func << " pk1=" << tup.m_pk1);
+ DBG("deleteScan" << (idx ? "Idx" : "") << " pk1=" << hex << tup.m_pk1);
CHK(rs->deleteTuple() == 0);
CHK(g_con->execute(NoCommit) == 0);
Uint32 k = tup.m_pk1 - g_opt.m_pk1off;
@@ -947,7 +1160,6 @@ deleteScan(bool idx)
CHK(g_con->execute(Commit) == 0);
g_ndb->closeTransaction(g_con);
g_con = 0;
- g_opr = 0;
g_ops = 0;
CHK(g_opt.m_rows == rows);
return 0;
@@ -958,6 +1170,7 @@ deleteScan(bool idx)
static int
testmain()
{
+ int style;
g_ndb = new Ndb("TEST_DB");
CHK(g_ndb->init() == 0);
CHK(g_ndb->waitUntilReady() == 0);
@@ -980,69 +1193,75 @@ testmain()
}
if (g_opt.m_seed != 0)
srandom(g_opt.m_seed);
- for (unsigned loop = 0; g_opt.m_loop == 0 || loop < g_opt.m_loop; loop++) {
- DBG("=== loop " << loop << " ===");
+ for (g_loop = 0; g_opt.m_loop == 0 || g_loop < g_opt.m_loop; g_loop++) {
+ DBG("=== loop " << g_loop << " ===");
if (g_opt.m_seed == 0)
- srandom(loop);
- bool llim = skip('v') ? true : false;
- bool ulim = skip('w') ? false : true;
+ srandom(g_loop);
// pk
- for (int rw = llim; rw <= ulim; rw++) {
- if (skip('k'))
+ for (style = 0; style <= 2; style++) {
+ if (skipcase('k') || skipstyle(style))
continue;
- DBG("--- pk ops " << (! rw ? "get/set" : "read/write") << " ---");
+ DBG("--- pk ops " << stylename[style] << " ---");
calcTups(false);
- CHK(insertPk(rw) == 0);
+ CHK(insertPk(style) == 0);
CHK(verifyBlob() == 0);
- CHK(readPk(rw) == 0);
- if (! skip('u')) {
- calcTups(rw);
- CHK(updatePk(rw) == 0);
+ CHK(readPk(style) == 0);
+ if (! skipcase('u')) {
+ calcTups(style);
+ CHK(updatePk(style) == 0);
CHK(verifyBlob() == 0);
}
- CHK(readPk(rw) == 0);
+ CHK(readPk(style) == 0);
CHK(deletePk() == 0);
CHK(verifyBlob() == 0);
}
// hash index
- for (int rw = llim; rw <= ulim; rw++) {
- if (skip('i'))
+ for (style = 0; style <= 2; style++) {
+ if (skipcase('i') || skipstyle(style))
continue;
- DBG("--- idx ops " << (! rw ? "get/set" : "read/write") << " ---");
+ DBG("--- idx ops " << stylename[style] << " ---");
calcTups(false);
- CHK(insertPk(rw) == 0);
+ CHK(insertPk(style) == 0);
CHK(verifyBlob() == 0);
- CHK(readIdx(rw) == 0);
- calcTups(rw);
- if (! skip('u')) {
- CHK(updateIdx(rw) == 0);
+ CHK(readIdx(style) == 0);
+ calcTups(style);
+ if (! skipcase('u')) {
+ CHK(updateIdx(style) == 0);
CHK(verifyBlob() == 0);
- CHK(readIdx(rw) == 0);
+ CHK(readIdx(style) == 0);
}
CHK(deleteIdx() == 0);
CHK(verifyBlob() == 0);
}
// scan table
- for (int rw = llim; rw <= ulim; rw++) {
- if (skip('s'))
+ for (style = 0; style <= 2; style++) {
+ if (skipcase('s') || skipstyle(style))
continue;
- DBG("--- table scan " << (! rw ? "get/set" : "read/write") << " ---");
+ DBG("--- table scan " << stylename[style] << " ---");
calcTups(false);
- CHK(insertPk(rw) == 0);
+ CHK(insertPk(style) == 0);
CHK(verifyBlob() == 0);
- CHK(readScan(rw, false) == 0);
+ CHK(readScan(style, false) == 0);
+ if (! skipcase('u')) {
+ CHK(updateScan(style, false) == 0);
+ CHK(verifyBlob() == 0);
+ }
CHK(deleteScan(false) == 0);
CHK(verifyBlob() == 0);
}
// scan index
- for (int rw = llim; rw <= ulim; rw++) {
- if (skip('r'))
+ for (style = 0; style <= 2; style++) {
+ if (skipcase('r') || skipstyle(style))
continue;
- DBG("--- index scan " << (! rw ? "get/set" : "read/write") << " ---");
+ DBG("--- index scan " << stylename[style] << " ---");
calcTups(false);
- CHK(insertPk(rw) == 0);
+ CHK(insertPk(style) == 0);
CHK(verifyBlob() == 0);
- CHK(readScan(rw, true) == 0);
+ CHK(readScan(style, true) == 0);
+ if (! skipcase('u')) {
+ CHK(updateScan(style, true) == 0);
+ CHK(verifyBlob() == 0);
+ }
CHK(deleteScan(true) == 0);
CHK(verifyBlob() == 0);
}
@@ -1056,6 +1275,7 @@ testmain()
static int
bugtest_4088()
{
+ unsigned i;
DBG("bug test 4088 - ndb api hang with mixed ops on index table");
// insert rows
calcTups(false);
@@ -1067,7 +1287,7 @@ bugtest_4088()
// read table pk via index as a table
const unsigned pkcnt = 2;
Tup pktup[pkcnt];
- for (unsigned i = 0; i < pkcnt; i++) {
+ for (i = 0; i < pkcnt; i++) {
char name[20];
// XXX guess table id
sprintf(name, "%d/%s", 4, g_opt.m_x1name);
@@ -1086,7 +1306,7 @@ bugtest_4088()
// BUG 4088: gets 1 tckeyconf, 1 tcindxconf, then hangs
CHK(g_con->execute(Commit) == 0);
// verify
- for (unsigned i = 0; i < pkcnt; i++) {
+ for (i = 0; i < pkcnt; i++) {
CHK(pktup[i].m_pk1 == tup.m_pk1);
CHK(memcmp(pktup[i].m_pk2, tup.m_pk2, g_opt.m_pk2len) == 0);
}
@@ -1120,6 +1340,12 @@ NDB_COMMAND(testOdbcDriver, "testBlobs", "testBlobs", "testBlobs", 65535)
{
while (++argv, --argc > 0) {
const char* arg = argv[0];
+ if (strcmp(arg, "-batch") == 0) {
+ if (++argv, --argc > 0) {
+ g_opt.m_batch = atoi(argv[0]);
+ continue;
+ }
+ }
if (strcmp(arg, "-core") == 0) {
g_opt.m_core = true;
continue;
@@ -1131,7 +1357,7 @@ NDB_COMMAND(testOdbcDriver, "testBlobs", "testBlobs", "testBlobs", 65535)
if (strcmp(arg, "-dbgall") == 0) {
g_opt.m_dbg = true;
g_opt.m_dbgall = true;
- putenv("NDB_BLOB_DEBUG=1");
+ putenv(strdup("NDB_BLOB_DEBUG=1"));
continue;
}
if (strcmp(arg, "-full") == 0) {
@@ -1164,9 +1390,13 @@ NDB_COMMAND(testOdbcDriver, "testBlobs", "testBlobs", "testBlobs", 65535)
}
if (strcmp(arg, "-skip") == 0) {
if (++argv, --argc > 0) {
- for (const char* p = argv[0]; *p != 0; p++) {
- skip(*p) = true;
- }
+ g_opt.m_skip = strdup(argv[0]);
+ continue;
+ }
+ }
+ if (strcmp(arg, "-style") == 0) {
+ if (++argv, --argc > 0) {
+ g_opt.m_style = strdup(argv[0]);
continue;
}
}
@@ -1174,10 +1404,6 @@ NDB_COMMAND(testOdbcDriver, "testBlobs", "testBlobs", "testBlobs", 65535)
if (strcmp(arg, "-pk2len") == 0) {
if (++argv, --argc > 0) {
g_opt.m_pk2len = atoi(argv[0]);
- if (g_opt.m_pk2len == 0) {
- skip('i') = true;
- skip('r') = true;
- }
if (g_opt.m_pk2len <= g_max_pk2len)
continue;
}
@@ -1204,7 +1430,15 @@ NDB_COMMAND(testOdbcDriver, "testBlobs", "testBlobs", "testBlobs", 65535)
printusage();
return NDBT_ProgramExit(NDBT_WRONGARGS);
}
+ if (g_opt.m_pk2len == 0) {
+ char b[100];
+ strcpy(b, g_opt.m_skip);
+ strcat(b, "i");
+ strcat(b, "r");
+ g_opt.m_skip = strdup(b);
+ }
if (testmain() == -1) {
+ ndbout << "line " << __LINE__ << " FAIL loop=" << g_loop << endl;
return NDBT_ProgramExit(NDBT_FAILED);
}
return NDBT_ProgramExit(NDBT_OK);
diff --git a/ndb/test/ndbapi/testDataBuffers.cpp b/ndb/test/ndbapi/testDataBuffers.cpp
index 75773040113..2e29dbb0d7b 100644
--- a/ndb/test/ndbapi/testDataBuffers.cpp
+++ b/ndb/test/ndbapi/testDataBuffers.cpp
@@ -84,6 +84,8 @@ static NdbSchemaCon* tcon = 0;
static NdbSchemaOp* top = 0;
static NdbConnection* con = 0;
static NdbOperation* op = 0;
+static NdbScanOperation* sop = 0;
+static NdbResultSet* rs = 0;
static int
ndberror(char const* fmt, ...)
@@ -438,9 +440,9 @@ testcase(int flag)
int newkey = 0;
if ((con = ndb->startTransaction()) == 0)
return ndberror("startTransaction key=%d", key);
- if ((op = con->getNdbOperation(tab)) == 0)
+ if ((op = sop = con->getNdbScanOperation(tab)) == 0)
return ndberror("getNdbOperation key=%d", key);
- if (op->openScanRead(1) < 0)
+ if ((rs = sop->readTuples(1)) == 0)
return ndberror("openScanRead key=%d", key);
{
col& c = ccol[0];
@@ -481,10 +483,10 @@ testcase(int flag)
}
}
}
- if (con->executeScan() < 0)
+ if (con->execute(NoCommit) < 0)
return ndberror("executeScan key=%d", key);
int ret, cnt = 0;
- while ((ret = con->nextScanResult()) == 0) {
+ while ((ret = rs->nextResult()) == 0) {
if (key != newkey)
return ndberror("unexpected key=%d newkey=%d", key, newkey);
for (int i = 1; i < attrcnt; i++) {
diff --git a/ndb/test/ndbapi/testDeadlock.cpp b/ndb/test/ndbapi/testDeadlock.cpp
new file mode 100644
index 00000000000..f51b3cea1e5
--- /dev/null
+++ b/ndb/test/ndbapi/testDeadlock.cpp
@@ -0,0 +1,514 @@
+/* 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 <ndb_global.h>
+#include <NdbMain.h>
+#include <NdbApi.hpp>
+#include <NdbOut.hpp>
+#include <NdbMutex.h>
+#include <NdbCondition.h>
+#include <NdbThread.h>
+#include <NdbTest.hpp>
+
+struct Opt {
+ bool m_dbg;
+ const char* m_scan;
+ const char* m_tname;
+ const char* m_xname;
+ Opt() :
+ m_dbg(true),
+ m_scan("tx"),
+ m_tname("T"),
+ m_xname("X")
+ {}
+};
+
+static void
+printusage()
+{
+ Opt d;
+ ndbout
+ << "usage: testDeadlock" << endl
+ << "-scan tx scan table, index [" << d.m_scan << "]" << endl
+ ;
+}
+
+static Opt g_opt;
+
+static NdbMutex ndbout_mutex = NDB_MUTEX_INITIALIZER;
+
+#define DBG(x) \
+ do { \
+ if (! g_opt.m_dbg) break; \
+ NdbMutex_Lock(&ndbout_mutex); \
+ ndbout << "line " << __LINE__ << " " << x << endl; \
+ NdbMutex_Unlock(&ndbout_mutex); \
+ } while (0)
+
+#define CHK(x) \
+ do { \
+ if (x) break; \
+ ndbout << "line " << __LINE__ << ": " << #x << " failed" << endl; \
+ return -1; \
+ } while (0)
+
+#define CHN(p, x) \
+ do { \
+ if (x) break; \
+ ndbout << "line " << __LINE__ << ": " << #x << " failed" << endl; \
+ ndbout << (p)->getNdbError() << endl; \
+ return -1; \
+ } while (0)
+
+// threads
+
+typedef int (*Runstep)(struct Thr& thr);
+
+struct Thr {
+ enum State { Wait, Start, Stop, Stopped, Exit };
+ State m_state;
+ int m_no;
+ Runstep m_runstep;
+ int m_ret;
+ NdbMutex* m_mutex;
+ NdbCondition* m_cond;
+ NdbThread* m_thread;
+ void* m_status;
+ Ndb* m_ndb;
+ NdbConnection* m_con;
+ NdbScanOperation* m_scanop;
+ NdbIndexScanOperation* m_indexscanop;
+ NdbResultSet* m_rs;
+ //
+ Thr(int no);
+ ~Thr();
+ int run();
+ void start(Runstep runstep);
+ void stop();
+ void stopped();
+ void lock() { NdbMutex_Lock(m_mutex); }
+ void unlock() { NdbMutex_Unlock(m_mutex); }
+ void wait() { NdbCondition_Wait(m_cond, m_mutex); }
+ void signal() { NdbCondition_Signal(m_cond); }
+ void exit();
+ void join() { NdbThread_WaitFor(m_thread, &m_status); }
+};
+
+static NdbOut&
+operator<<(NdbOut& out, const Thr& thr) {
+ out << "thr " << thr.m_no;
+ return out;
+}
+
+extern "C" { static void* runthread(void* arg); }
+
+Thr::Thr(int no)
+{
+ m_state = Wait;
+ m_no = no;
+ m_runstep = 0;
+ m_ret = 0;
+ m_mutex = NdbMutex_Create();
+ m_cond = NdbCondition_Create();
+ assert(m_mutex != 0 && m_cond != 0);
+ const unsigned stacksize = 256 * 1024;
+ const NDB_THREAD_PRIO prio = NDB_THREAD_PRIO_LOW;
+ m_thread = NdbThread_Create(runthread, (void**)this, stacksize, "me", prio);
+ if (m_thread == 0) {
+ DBG("create thread failed: errno=" << errno);
+ m_ret = -1;
+ }
+ m_status = 0;
+ m_ndb = 0;
+ m_con = 0;
+ m_scanop = 0;
+ m_indexscanop = 0;
+ m_rs = 0;
+}
+
+Thr::~Thr()
+{
+ if (m_thread != 0)
+ NdbThread_Destroy(&m_thread);
+ if (m_cond != 0)
+ NdbCondition_Destroy(m_cond);
+ if (m_mutex != 0)
+ NdbMutex_Destroy(m_mutex);
+}
+
+static void*
+runthread(void* arg) {
+ Thr& thr = *(Thr*)arg;
+ thr.run();
+ return 0;
+}
+
+int
+Thr::run()
+{
+ DBG(*this << " run");
+ while (true) {
+ lock();
+ while (m_state != Start && m_state != Exit) {
+ wait();
+ }
+ if (m_state == Exit) {
+ DBG(*this << " exit");
+ unlock();
+ break;
+ }
+ m_ret = (*m_runstep)(*this);
+ m_state = Stopped;
+ signal();
+ unlock();
+ if (m_ret != 0) {
+ DBG(*this << " error exit");
+ break;
+ }
+ }
+ delete m_ndb;
+ m_ndb = 0;
+ return 0;
+}
+
+void
+Thr::start(Runstep runstep)
+{
+ lock();
+ m_state = Start;
+ m_runstep = runstep;
+ signal();
+ unlock();
+}
+
+void
+Thr::stopped()
+{
+ lock();
+ while (m_state != Stopped) {
+ wait();
+ }
+ m_state = Wait;
+ unlock();
+}
+
+void
+Thr::exit()
+{
+ lock();
+ m_state = Exit;
+ signal();
+ unlock();
+}
+
+// general
+
+static int
+runstep_connect(Thr& thr)
+{
+ Ndb* ndb = thr.m_ndb = new Ndb("TEST_DB");
+ CHN(ndb, ndb->init() == 0);
+ CHN(ndb, ndb->waitUntilReady() == 0);
+ DBG(thr << " connected");
+ return 0;
+}
+
+static int
+runstep_starttx(Thr& thr)
+{
+ Ndb* ndb = thr.m_ndb;
+ assert(ndb != 0);
+ CHN(ndb, (thr.m_con = ndb->startTransaction()) != 0);
+ DBG("thr " << thr.m_no << " tx started");
+ return 0;
+}
+
+/*
+ * WL1822 flush locks
+ *
+ * Table T with 3 tuples X, Y, Z.
+ * Two transactions (* = lock wait).
+ *
+ * - tx1 reads and locks Z
+ * - tx2 scans X, Y, *Z
+ * - tx2 returns X, Y before lock wait on Z
+ * - tx1 reads and locks *X
+ * - api asks for next tx2 result
+ * - LQH unlocks X via ACC or TUX [*]
+ * - tx1 gets lock on X
+ * - tx1 returns X to api
+ * - api commits tx1
+ * - tx2 gets lock on Z
+ * - tx2 returs Z to api
+ *
+ * The point is deadlock is avoided due to [*].
+ * The test is for 1 db node and 1 fragment table.
+ */
+
+static char wl1822_scantx = 0;
+
+static const Uint32 wl1822_valA[3] = { 0, 1, 2 };
+static const Uint32 wl1822_valB[3] = { 3, 4, 5 };
+
+static Uint32 wl1822_bufA = ~0;
+static Uint32 wl1822_bufB = ~0;
+
+// map scan row to key (A) and reverse
+static unsigned wl1822_r2k[3] = { 0, 0, 0 };
+static unsigned wl1822_k2r[3] = { 0, 0, 0 };
+
+static int
+wl1822_createtable(Thr& thr)
+{
+ Ndb* ndb = thr.m_ndb;
+ assert(ndb != 0);
+ NdbDictionary::Dictionary* dic = ndb->getDictionary();
+ // drop T
+ if (dic->getTable(g_opt.m_tname) != 0)
+ CHN(dic, dic->dropTable(g_opt.m_tname) == 0);
+ // create T
+ NdbDictionary::Table tab(g_opt.m_tname);
+ tab.setFragmentType(NdbDictionary::Object::FragAllSmall);
+ { NdbDictionary::Column col("A");
+ col.setType(NdbDictionary::Column::Unsigned);
+ col.setPrimaryKey(true);
+ tab.addColumn(col);
+ }
+ { NdbDictionary::Column col("B");
+ col.setType(NdbDictionary::Column::Unsigned);
+ col.setPrimaryKey(false);
+ tab.addColumn(col);
+ }
+ CHN(dic, dic->createTable(tab) == 0);
+ // create X
+ NdbDictionary::Index ind(g_opt.m_xname);
+ ind.setTable(g_opt.m_tname);
+ ind.setType(NdbDictionary::Index::OrderedIndex);
+ ind.setLogging(false);
+ ind.addColumn("B");
+ CHN(dic, dic->createIndex(ind) == 0);
+ DBG("created " << g_opt.m_tname << ", " << g_opt.m_xname);
+ return 0;
+}
+
+static int
+wl1822_insertrows(Thr& thr)
+{
+ // insert X, Y, Z
+ Ndb* ndb = thr.m_ndb;
+ assert(ndb != 0);
+ NdbConnection* con;
+ NdbOperation* op;
+ for (unsigned k = 0; k < 3; k++) {
+ CHN(ndb, (con = ndb->startTransaction()) != 0);
+ CHN(con, (op = con->getNdbOperation(g_opt.m_tname)) != 0);
+ CHN(op, op->insertTuple() == 0);
+ CHN(op, op->equal("A", (char*)&wl1822_valA[k]) == 0);
+ CHN(op, op->setValue("B", (char*)&wl1822_valB[k]) == 0);
+ CHN(con, con->execute(Commit) == 0);
+ ndb->closeTransaction(con);
+ }
+ DBG("inserted X, Y, Z");
+ return 0;
+}
+
+static int
+wl1822_getscanorder(Thr& thr)
+{
+ // cheat, table order happens to be key order in my test
+ wl1822_r2k[0] = 0;
+ wl1822_r2k[1] = 1;
+ wl1822_r2k[2] = 2;
+ wl1822_k2r[0] = 0;
+ wl1822_k2r[1] = 1;
+ wl1822_k2r[2] = 2;
+ DBG("scan order determined");
+ return 0;
+}
+
+static int
+wl1822_tx1_readZ(Thr& thr)
+{
+ // tx1 read Z with exclusive lock
+ NdbConnection* con = thr.m_con;
+ assert(con != 0);
+ NdbOperation* op;
+ CHN(con, (op = con->getNdbOperation(g_opt.m_tname)) != 0);
+ CHN(op, op->readTupleExclusive() == 0);
+ CHN(op, op->equal("A", wl1822_valA[wl1822_r2k[2]]) == 0);
+ wl1822_bufB = ~0;
+ CHN(op, op->getValue("B", (char*)&wl1822_bufB) != 0);
+ CHN(con, con->execute(NoCommit) == 0);
+ CHK(wl1822_bufB == wl1822_valB[wl1822_r2k[2]]);
+ DBG("tx1 locked Z");
+ return 0;
+}
+
+static int
+wl1822_tx2_scanXY(Thr& thr)
+{
+ // tx2 scan X, Y with exclusive lock
+ NdbConnection* con = thr.m_con;
+ assert(con != 0);
+ NdbScanOperation* scanop;
+ NdbIndexScanOperation* indexscanop;
+ NdbResultSet* rs;
+ if (wl1822_scantx == 't') {
+ CHN(con, (scanop = thr.m_scanop = con->getNdbScanOperation(g_opt.m_tname)) != 0);
+ DBG("tx2 scan exclusive " << g_opt.m_tname);
+ }
+ if (wl1822_scantx == 'x') {
+ CHN(con, (scanop = thr.m_scanop = indexscanop = thr.m_indexscanop = con->getNdbIndexScanOperation(g_opt.m_xname, g_opt.m_tname)) != 0);
+ DBG("tx2 scan exclusive " << g_opt.m_xname);
+ }
+ CHN(scanop, (rs = thr.m_rs = scanop->readTuplesExclusive(16)) != 0);
+ CHN(scanop, scanop->getValue("A", (char*)&wl1822_bufA) != 0);
+ CHN(scanop, scanop->getValue("B", (char*)&wl1822_bufB) != 0);
+ CHN(con, con->execute(NoCommit) == 0);
+ unsigned row = 0;
+ while (row < 2) {
+ DBG("before row " << row);
+ int ret;
+ wl1822_bufA = wl1822_bufB = ~0;
+ CHN(con, (ret = rs->nextResult(true)) == 0);
+ DBG("got row " << row << " a=" << wl1822_bufA << " b=" << wl1822_bufB);
+ CHK(wl1822_bufA == wl1822_valA[wl1822_r2k[row]]);
+ CHK(wl1822_bufB == wl1822_valB[wl1822_r2k[row]]);
+ row++;
+ }
+ return 0;
+}
+
+static int
+wl1822_tx1_readX_commit(Thr& thr)
+{
+ // tx1 read X with exclusive lock and commit
+ NdbConnection* con = thr.m_con;
+ assert(con != 0);
+ NdbOperation* op;
+ CHN(con, (op = con->getNdbOperation(g_opt.m_tname)) != 0);
+ CHN(op, op->readTupleExclusive() == 0);
+ CHN(op, op->equal("A", wl1822_valA[wl1822_r2k[2]]) == 0);
+ wl1822_bufB = ~0;
+ CHN(op, op->getValue("B", (char*)&wl1822_bufB) != 0);
+ CHN(con, con->execute(NoCommit) == 0);
+ CHK(wl1822_bufB == wl1822_valB[wl1822_r2k[2]]);
+ DBG("tx1 locked X");
+ CHN(con, con->execute(Commit) == 0);
+ DBG("tx1 commit");
+ return 0;
+}
+
+static int
+wl1822_tx2_scanZ_close(Thr& thr)
+{
+ // tx2 scan Z with exclusive lock and close scan
+ Ndb* ndb = thr.m_ndb;
+ NdbConnection* con = thr.m_con;
+ NdbScanOperation* scanop = thr.m_scanop;
+ NdbResultSet* rs = thr.m_rs;
+ assert(ndb != 0 && con != 0 && scanop != 0 && rs != 0);
+ unsigned row = 2;
+ while (true) {
+ DBG("before row " << row);
+ int ret;
+ wl1822_bufA = wl1822_bufB = ~0;
+ CHN(con, (ret = rs->nextResult(true)) == 0 || ret == 1);
+ if (ret == 1)
+ break;
+ DBG("got row " << row << " a=" << wl1822_bufA << " b=" << wl1822_bufB);
+ CHK(wl1822_bufA == wl1822_valA[wl1822_r2k[row]]);
+ CHK(wl1822_bufB == wl1822_valB[wl1822_r2k[row]]);
+ row++;
+ }
+ ndb->closeTransaction(con);
+ CHK(row == 3);
+ return 0;
+}
+
+// threads are synced between each step
+static Runstep wl1822_step[][2] = {
+ { runstep_connect, runstep_connect },
+ { wl1822_createtable, 0 },
+ { wl1822_insertrows, 0 },
+ { wl1822_getscanorder, 0 },
+ { runstep_starttx, runstep_starttx },
+ { wl1822_tx1_readZ, 0 },
+ { 0, wl1822_tx2_scanXY },
+ { wl1822_tx1_readX_commit, wl1822_tx2_scanZ_close }
+};
+const unsigned wl1822_stepcount = sizeof(wl1822_step)/sizeof(wl1822_step[0]);
+
+static int
+wl1822_main(char scantx)
+{
+ wl1822_scantx = scantx;
+ static const unsigned thrcount = 2;
+ // create threads for tx1 and tx2
+ Thr* thrlist[2];
+ for (int n = 0; n < thrcount; n++) {
+ Thr& thr = *(thrlist[n] = new Thr(1 + n));
+ CHK(thr.m_ret == 0);
+ }
+ // run the steps
+ for (unsigned i = 0; i < wl1822_stepcount; i++) {
+ DBG("step " << i << " start");
+ for (int n = 0; n < thrcount; n++) {
+ Thr& thr = *thrlist[n];
+ Runstep runstep = wl1822_step[i][n];
+ if (runstep != 0)
+ thr.start(runstep);
+ }
+ for (int n = 0; n < thrcount; n++) {
+ Thr& thr = *thrlist[n];
+ Runstep runstep = wl1822_step[i][n];
+ if (runstep != 0)
+ thr.stopped();
+ }
+ }
+ // delete threads
+ for (int n = 0; n < thrcount; n++) {
+ Thr& thr = *thrlist[n];
+ thr.exit();
+ thr.join();
+ delete &thr;
+ }
+ return 0;
+}
+
+NDB_COMMAND(testOdbcDriver, "testDeadlock", "testDeadlock", "testDeadlock", 65535)
+{
+ while (++argv, --argc > 0) {
+ const char* arg = argv[0];
+ if (strcmp(arg, "-scan") == 0) {
+ if (++argv, --argc > 0) {
+ g_opt.m_scan = strdup(argv[0]);
+ continue;
+ }
+ }
+ printusage();
+ return NDBT_ProgramExit(NDBT_WRONGARGS);
+ }
+ if (
+ strchr(g_opt.m_scan, 't') != 0 && wl1822_main('t') == -1 ||
+ strchr(g_opt.m_scan, 'x') != 0 && wl1822_main('x') == -1
+ ) {
+ return NDBT_ProgramExit(NDBT_FAILED);
+ }
+ return NDBT_ProgramExit(NDBT_OK);
+}
+
+// vim: set sw=2 et:
diff --git a/ndb/test/ndbapi/testDict.cpp b/ndb/test/ndbapi/testDict.cpp
index 1451c942362..e7597c26960 100644
--- a/ndb/test/ndbapi/testDict.cpp
+++ b/ndb/test/ndbapi/testDict.cpp
@@ -537,6 +537,7 @@ int runTestFragmentTypes(NDBT_Context* ctx, NDBT_Step* step){
}
const NdbDictionary::Table* pTab = ctx->getTab();
+ pNdb->getDictionary()->dropTable(pTab->getName());
NdbDictionary::Table newTab(* pTab);
// Set fragment type for table
diff --git a/ndb/test/ndbapi/testGrep.cpp b/ndb/test/ndbapi/testGrep.cpp
index 4b870f6f9a9..0bf84cb4ec8 100644
--- a/ndb/test/ndbapi/testGrep.cpp
+++ b/ndb/test/ndbapi/testGrep.cpp
@@ -254,8 +254,7 @@ int runClearTable(NDBT_Context* ctx, NDBT_Step* step){
return NDBT_OK;
}
-
-#include "../bank/Bank.hpp"
+#include "bank/Bank.hpp"
int runCreateBank(NDBT_Context* ctx, NDBT_Step* step){
Bank bank;
@@ -444,6 +443,7 @@ int runRestoreBankAndVerify(NDBT_Context* ctx, NDBT_Step* step){
return result;
}
*/
+
NDBT_TESTSUITE(testGrep);
TESTCASE("GrepBasic",
"Test that Global Replication works on one table \n"
@@ -473,8 +473,6 @@ TESTCASE("GrepNodeRestart",
}
-
-
TESTCASE("GrepBank",
"Test that grep and restore works during transaction load\n"
" by backing up the bank"
@@ -495,6 +493,7 @@ TESTCASE("GrepBank",
// FINALIZER(runDropBank);
}
+
TESTCASE("NFMaster",
"Test that grep behaves during node failiure\n"){
INITIALIZER(setMaster);
diff --git a/ndb/test/ndbapi/testIndex.cpp b/ndb/test/ndbapi/testIndex.cpp
index 47db0b3cff7..6ebbfd8b680 100644
--- a/ndb/test/ndbapi/testIndex.cpp
+++ b/ndb/test/ndbapi/testIndex.cpp
@@ -26,7 +26,7 @@
#define CHECK(b) if (!(b)) { \
g_err << "ERR: "<< step->getName() \
<< " failed on line " << __LINE__ << endl; \
- result = NDBT_FAILED; \
+ result = NDBT_FAILED; break;\
}
@@ -381,6 +381,27 @@ 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
@@ -394,10 +415,17 @@ runTransactions1(NDBT_Context* ctx, NDBT_Step* step){
g_err << "Updated table failed" << endl;
return NDBT_FAILED;
}
+
+ sync_down(ctx);
+ if(ctx->isTestStopped())
+ break;
+
if (hugoTrans.scanUpdateRecords(pNdb, rows, batchSize) != 0){
g_err << "Updated table failed" << endl;
return NDBT_FAILED;
}
+
+ sync_down(ctx);
}
return NDBT_OK;
}
@@ -418,7 +446,7 @@ runTransactions2(NDBT_Context* ctx, NDBT_Step* step){
return NDBT_FAILED;
}
#endif
-
+ sync_down(ctx);
if(ctx->isTestStopped())
break;
#if 1
@@ -427,6 +455,7 @@ runTransactions2(NDBT_Context* ctx, NDBT_Step* step){
return NDBT_FAILED;
}
#endif
+ sync_down(ctx);
}
return NDBT_OK;
}
@@ -447,6 +476,7 @@ runTransactions3(NDBT_Context* ctx, NDBT_Step* step){
g_err << "Load table failed" << endl;
return NDBT_FAILED;
}
+ sync_down(ctx);
if(ctx->isTestStopped())
break;
@@ -454,7 +484,8 @@ runTransactions3(NDBT_Context* ctx, NDBT_Step* step){
g_err << "Updated table failed" << endl;
return NDBT_FAILED;
}
-
+
+ sync_down(ctx);
if(ctx->isTestStopped())
break;
@@ -463,6 +494,7 @@ runTransactions3(NDBT_Context* ctx, NDBT_Step* step){
return NDBT_FAILED;
}
+ sync_down(ctx);
if(ctx->isTestStopped())
break;
@@ -471,6 +503,7 @@ runTransactions3(NDBT_Context* ctx, NDBT_Step* step){
return NDBT_FAILED;
}
+ sync_down(ctx);
if(ctx->isTestStopped())
break;
@@ -479,6 +512,7 @@ runTransactions3(NDBT_Context* ctx, NDBT_Step* step){
return NDBT_FAILED;
}
+ sync_down(ctx);
if(ctx->isTestStopped())
break;
@@ -486,12 +520,15 @@ runTransactions3(NDBT_Context* ctx, NDBT_Step* step){
g_err << "Clear table failed" << endl;
return NDBT_FAILED;
}
+
+ sync_down(ctx);
if(ctx->isTestStopped())
break;
-
+
int count = -1;
if(utilTrans.selectCount(pNdb, 64, &count) != 0 || count != 0)
return NDBT_FAILED;
+ sync_down(ctx);
}
return NDBT_OK;
}
@@ -510,6 +547,7 @@ int runRestarts(NDBT_Context* ctx, NDBT_Step* step){
result = NDBT_FAILED;
break;
}
+ sync_up_and_wait(ctx);
i++;
}
ctx->stopTest();
@@ -1130,7 +1168,7 @@ runUniqueNullTransactions(NDBT_Context* ctx, NDBT_Step* step){
if(!pTrans) goto done;
sOp = pTrans->getNdbScanOperation(pTab->getName());
if(!sOp) goto done;
- rs = sOp->readTuples(240, NdbScanOperation::LM_Exclusive);
+ rs = sOp->readTuples(NdbScanOperation::LM_Exclusive);
if(!rs) goto done;
if(pTrans->execute(NoCommit) == -1) goto done;
while((eof = rs->nextResult(true)) == 0){
@@ -1259,6 +1297,7 @@ TESTCASE("CreateLoadDrop_O",
TESTCASE("NFNR1",
"Test that indexes are correctly maintained during node fail and node restart"){
TC_PROPERTY("LoggedIndexes", (unsigned)0);
+ //TC_PROPERTY("Threads", 2);
INITIALIZER(runClearTable);
INITIALIZER(createRandomIndex);
INITIALIZER(runLoadTable);
@@ -1492,4 +1531,4 @@ int main(int argc, const char** argv){
return testIndex.execute(argc, argv);
}
-
+template class Vector<Attrib*>;
diff --git a/ndb/test/ndbapi/testNdbApi.cpp b/ndb/test/ndbapi/testNdbApi.cpp
index 2e08ebbed4e..5b171d42578 100644
--- a/ndb/test/ndbapi/testNdbApi.cpp
+++ b/ndb/test/ndbapi/testNdbApi.cpp
@@ -1010,4 +1010,5 @@ int main(int argc, const char** argv){
return testNdbApi.execute(argc, argv);
}
-
+template class Vector<Ndb*>;
+template class Vector<NdbConnection*>;
diff --git a/ndb/test/ndbapi/testNodeRestart.cpp b/ndb/test/ndbapi/testNodeRestart.cpp
index fd591f04c69..89b38c78e71 100644
--- a/ndb/test/ndbapi/testNodeRestart.cpp
+++ b/ndb/test/ndbapi/testNodeRestart.cpp
@@ -287,8 +287,6 @@ TESTCASE("Terror",
STEP(runPkUpdateUntilStopped);
STEP(runScanReadUntilStopped);
STEP(runScanUpdateUntilStopped);
- STEP(runInsertUntilStopped);
- STEP(runClearTableUntilStopped);
FINALIZER(runClearTable);
}
TESTCASE("FullDb",
diff --git a/ndb/test/ndbapi/testOIBasic.cpp b/ndb/test/ndbapi/testOIBasic.cpp
index 0ca8ce79e2e..c58dd8538e9 100644
--- a/ndb/test/ndbapi/testOIBasic.cpp
+++ b/ndb/test/ndbapi/testOIBasic.cpp
@@ -33,14 +33,18 @@
struct Opt {
// common options
+ unsigned m_batch;
const char* m_case;
bool m_core;
bool m_dups;
NdbDictionary::Object::FragmentType m_fragtype;
+ unsigned m_idxloop;
const char* m_index;
unsigned m_loop;
bool m_nologging;
+ bool m_msglock;
unsigned m_rows;
+ unsigned m_samples;
unsigned m_scanrd;
unsigned m_scanex;
unsigned m_seed;
@@ -49,17 +53,21 @@ struct Opt {
unsigned m_threads;
unsigned m_v;
Opt() :
+ m_batch(32),
m_case(0),
m_core(false),
m_dups(false),
m_fragtype(NdbDictionary::Object::FragUndefined),
+ m_idxloop(4),
m_index(0),
m_loop(1),
m_nologging(false),
+ m_msglock(true),
m_rows(1000),
+ m_samples(0),
m_scanrd(240),
m_scanex(240),
- m_seed(1),
+ m_seed(0),
m_subloop(4),
m_table(0),
m_threads(4),
@@ -78,17 +86,19 @@ printhelp()
Opt d;
ndbout
<< "usage: testOIbasic [options]" << endl
+ << " -batch N pk operations in batch [" << d.m_batch << "]" << endl
<< " -case abc only given test cases (letters a-z)" << endl
<< " -core core dump on error [" << d.m_core << "]" << 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 forever=0 [" << d.m_loop << "]" << endl
+ << " -loop N loop count full suite 0=forever [" << d.m_loop << "]" << endl
<< " -nologging create tables in no-logging mode" << 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
- << " -seed N srandom seed [" << d.m_seed << "]" << 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
<< " -threads N number of threads [" << d.m_threads << "]" << endl
@@ -99,6 +109,12 @@ printhelp()
printtables();
}
+// not yet configurable
+static const bool g_store_null_key = true;
+
+// compare NULL like normal value (NULL < not NULL, NULL == NULL)
+static const bool g_compare_null = true;
+
// log and error macros
static NdbMutex ndbout_mutex = NDB_MUTEX_INITIALIZER;
@@ -124,9 +140,9 @@ getthrstr()
#define LLN(n, s) \
do { \
if ((n) > g_opt.m_v) break; \
- NdbMutex_Lock(&ndbout_mutex); \
+ if (g_opt.m_msglock) NdbMutex_Lock(&ndbout_mutex); \
ndbout << getthrstr() << s << endl; \
- NdbMutex_Unlock(&ndbout_mutex); \
+ if (g_opt.m_msglock) NdbMutex_Unlock(&ndbout_mutex); \
} while(0)
#define LL0(s) LLN(0, s)
@@ -139,11 +155,10 @@ getthrstr()
// following check a condition and return -1 on failure
#undef CHK // simple check
-#undef CHKTRY // execute action (try-catch) on failure
-#undef CHKMSG // print extra message on failure
+#undef CHKTRY // check with action on fail
#undef CHKCON // print NDB API errors on failure
-#define CHK(x) CHKTRY(x, ;)
+#define CHK(x) CHKTRY(x, ;)
#define CHKTRY(x, act) \
do { \
@@ -154,14 +169,6 @@ getthrstr()
return -1; \
} while (0)
-#define CHKMSG(x, msg) \
- do { \
- if (x) break; \
- LL0("line " << __LINE__ << ": " << #x << " failed: " << msg); \
- if (g_opt.m_core) abort(); \
- return -1; \
- } while (0)
-
#define CHKCON(x, con) \
do { \
if (x) break; \
@@ -177,6 +184,7 @@ class Thr;
class Con;
class Tab;
class Set;
+class Tmr;
struct Par : public Opt {
unsigned m_no;
@@ -186,14 +194,17 @@ struct Par : public Opt {
const Tab& tab() const { assert(m_tab != 0); return *m_tab; }
Set* m_set;
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_totrows;
- unsigned m_batch;
// value calculation
unsigned m_pctnull;
unsigned m_range;
unsigned m_pctrange;
// do verify after read
bool m_verify;
+ // deadlock possible
+ bool m_deadlock;
// timer location
Par(const Opt& opt) :
Opt(opt),
@@ -201,12 +212,13 @@ struct Par : public Opt {
m_con(0),
m_tab(0),
m_set(0),
+ m_tmr(0),
m_totrows(m_threads * m_rows),
- m_batch(32),
m_pctnull(10),
m_range(m_rows),
m_pctrange(0),
- m_verify(false) {
+ m_verify(false),
+ m_deadlock(false) {
}
};
@@ -241,19 +253,20 @@ struct Tmr {
void on();
void off(unsigned cnt = 0);
const char* time();
+ const char* pct(const Tmr& t1);
const char* over(const Tmr& t1);
NDB_TICKS m_on;
unsigned m_ms;
unsigned m_cnt;
char m_time[100];
- char m_over[100];
+ char m_text[100];
Tmr() { clr(); }
};
void
Tmr::clr()
{
- m_on = m_ms = m_cnt = m_time[0] = m_over[0] = 0;
+ m_on = m_ms = m_cnt = m_time[0] = m_text[0] = 0;
}
void
@@ -285,14 +298,63 @@ Tmr::time()
}
const char*
+Tmr::pct(const Tmr& t1)
+{
+ if (0 < t1.m_ms) {
+ sprintf(m_text, "%u pct", (100 * m_ms) / t1.m_ms);
+ } else {
+ sprintf(m_text, "[cannot measure]");
+ }
+ return m_text;
+}
+
+const char*
Tmr::over(const Tmr& t1)
{
- if (0 < t1.m_ms && t1.m_ms < m_ms) {
- sprintf(m_over, "%u pct", (100 * (m_ms - t1.m_ms)) / t1.m_ms);
+ if (0 < t1.m_ms) {
+ if (t1.m_ms <= m_ms)
+ sprintf(m_text, "%u pct", (100 * (m_ms - t1.m_ms)) / t1.m_ms);
+ else
+ sprintf(m_text, "-%u pct", (100 * (t1.m_ms - m_ms)) / t1.m_ms);
} else {
- sprintf(m_over, "[cannot measure]");
+ sprintf(m_text, "[cannot measure]");
}
- return m_over;
+ return m_text;
+}
+
+// list of ints
+
+struct Lst {
+ Lst();
+ unsigned m_arr[1000];
+ unsigned m_cnt;
+ void push(unsigned i);
+ unsigned cnt() const;
+ void reset();
+};
+
+Lst::Lst() :
+ m_cnt(0)
+{
+}
+
+void
+Lst::push(unsigned i)
+{
+ assert(m_cnt < sizeof(m_arr)/sizeof(m_arr[0]));
+ m_arr[m_cnt++] = i;
+}
+
+unsigned
+Lst::cnt() const
+{
+ return m_cnt;
+}
+
+void
+Lst::reset()
+{
+ m_cnt = 0;
}
// tables and indexes
@@ -409,7 +471,7 @@ operator<<(NdbOut& out, const Tab& tab)
return out;
}
-// tt1 + tt1x1 tt1x2 tt1x3 tt1x4
+// tt1 + tt1x1 tt1x2 tt1x3 tt1x4 tt1x5
static const Col
tt1col[] = {
@@ -422,24 +484,29 @@ tt1col[] = {
static const ICol
tt1x1col[] = {
- { 0, tt1col[1] }
+ { 0, tt1col[0] }
};
static const ICol
tt1x2col[] = {
+ { 0, tt1col[1] }
+};
+
+static const ICol
+tt1x3col[] = {
{ 0, tt1col[1] },
{ 1, tt1col[2] }
};
static const ICol
-tt1x3col[] = {
+tt1x4col[] = {
{ 0, tt1col[3] },
{ 1, tt1col[2] },
{ 2, tt1col[1] }
};
static const ICol
-tt1x4col[] = {
+tt1x5col[] = {
{ 0, tt1col[1] },
{ 1, tt1col[4] },
{ 2, tt1col[2] },
@@ -453,17 +520,22 @@ tt1x1 = {
static const ITab
tt1x2 = {
- "TT1X2", 2, tt1x2col
+ "TT1X2", 1, tt1x2col
};
static const ITab
tt1x3 = {
- "TT1X3", 3, tt1x3col
+ "TT1X3", 2, tt1x3col
};
static const ITab
tt1x4 = {
- "TT1X4", 4, tt1x4col
+ "TT1X4", 3, tt1x4col
+};
+
+static const ITab
+tt1x5 = {
+ "TT1X5", 4, tt1x5col
};
static const ITab
@@ -471,15 +543,16 @@ tt1itab[] = {
tt1x1,
tt1x2,
tt1x3,
- tt1x4
+ tt1x4,
+ tt1x5
};
static const Tab
tt1 = {
- "TT1", 5, tt1col, 4, tt1itab
+ "TT1", 5, tt1col, 5, tt1itab
};
-// tt2 + tt2x1 tt2x2 tt2x3 tt2x4
+// tt2 + tt2x1 tt2x2 tt2x3 tt2x4 tt2x5
static const Col
tt2col[] = {
@@ -492,24 +565,29 @@ tt2col[] = {
static const ICol
tt2x1col[] = {
+ { 0, tt2col[0] }
+};
+
+static const ICol
+tt2x2col[] = {
{ 0, tt2col[1] },
{ 1, tt2col[2] }
};
static const ICol
-tt2x2col[] = {
+tt2x3col[] = {
{ 0, tt2col[2] },
{ 1, tt2col[1] }
};
static const ICol
-tt2x3col[] = {
+tt2x4col[] = {
{ 0, tt2col[3] },
{ 1, tt2col[4] }
};
static const ICol
-tt2x4col[] = {
+tt2x5col[] = {
{ 0, tt2col[4] },
{ 1, tt2col[3] },
{ 2, tt2col[2] },
@@ -518,7 +596,7 @@ tt2x4col[] = {
static const ITab
tt2x1 = {
- "TT2X1", 2, tt2x1col
+ "TT2X1", 1, tt2x1col
};
static const ITab
@@ -533,7 +611,12 @@ tt2x3 = {
static const ITab
tt2x4 = {
- "TT2X4", 4, tt2x4col
+ "TT2X4", 2, tt2x4col
+};
+
+static const ITab
+tt2x5 = {
+ "TT2X5", 4, tt2x5col
};
static const ITab
@@ -541,12 +624,13 @@ tt2itab[] = {
tt2x1,
tt2x2,
tt2x3,
- tt2x4
+ tt2x4,
+ tt2x5
};
static const Tab
tt2 = {
- "TT2", 5, tt2col, 4, tt2itab
+ "TT2", 5, tt2col, 5, tt2itab
};
// all tables
@@ -567,40 +651,42 @@ struct Con {
NdbDictionary::Dictionary* m_dic;
NdbConnection* m_tx;
NdbOperation* m_op;
- NdbConnection* m_scantx;
- NdbOperation* m_scanop;
+ NdbScanOperation* m_scanop;
+ NdbIndexScanOperation* m_indexscanop;
+ NdbResultSet* m_resultset;
enum ScanMode { ScanNo = 0, Committed, Latest, Exclusive };
ScanMode m_scanmode;
enum ErrType { ErrNone = 0, ErrDeadlock, ErrOther };
ErrType m_errtype;
Con() :
m_ndb(0), m_dic(0), m_tx(0), m_op(0),
- m_scantx(0), m_scanop(0), m_scanmode(ScanNo), m_errtype(ErrNone) {}
+ m_scanop(0), m_indexscanop(0), m_resultset(0), m_scanmode(ScanNo), m_errtype(ErrNone) {}
+ ~Con() {
+ if (m_tx != 0)
+ closeTransaction();
+ }
int connect();
+ void connect(const Con& con);
void disconnect();
int startTransaction();
- int startBuddyTransaction(const Con& con);
int getNdbOperation(const Tab& tab);
- int getNdbOperation(const ITab& itab, const Tab& tab);
+ int getNdbScanOperation(const Tab& tab);
+ int getNdbScanOperation(const ITab& itab, const Tab& tab);
int equal(int num, const char* addr);
int getValue(int num, NdbRecAttr*& rec);
int setValue(int num, const char* addr);
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 executeScan();
- int nextScanResult();
- int takeOverForUpdate(Con& scan);
- int takeOverForDelete(Con& scan);
+ int nextScanResult(bool fetchAllowed);
+ int nextScanResult(bool fetchAllowed, bool& deadlock);
+ int updateScanTuple(Con& con2);
+ int deleteScanTuple(Con& con2);
void closeTransaction();
void printerror(NdbOut& out);
- // flush dict cache
- int bugger() {
- //disconnect();
- //CHK(connect() == 0);
- return 0;
- }
};
int
@@ -610,12 +696,18 @@ Con::connect()
m_ndb = new Ndb("TEST_DB");
CHKCON(m_ndb->init() == 0, *this);
CHKCON(m_ndb->waitUntilReady(30) == 0, *this);
- m_dic = m_ndb->getDictionary();
m_tx = 0, m_op = 0;
return 0;
}
void
+Con::connect(const Con& con)
+{
+ assert(m_ndb == 0);
+ m_ndb = con.m_ndb;
+}
+
+void
Con::disconnect()
{
delete m_ndb;
@@ -625,31 +717,34 @@ Con::disconnect()
int
Con::startTransaction()
{
- assert(m_ndb != 0 && m_tx == 0);
+ assert(m_ndb != 0);
+ if (m_tx != 0)
+ closeTransaction();
CHKCON((m_tx = m_ndb->startTransaction()) != 0, *this);
return 0;
}
int
-Con::startBuddyTransaction(const Con& con)
+Con::getNdbOperation(const Tab& tab)
{
- assert(m_ndb != 0 && m_tx == 0 && con.m_ndb == m_ndb && con.m_tx != 0);
- CHKCON((m_tx = m_ndb->hupp(con.m_tx)) != 0, *this);
+ assert(m_tx != 0);
+ CHKCON((m_op = m_tx->getNdbOperation(tab.m_name)) != 0, *this);
return 0;
}
int
-Con::getNdbOperation(const Tab& tab)
+Con::getNdbScanOperation(const Tab& tab)
{
assert(m_tx != 0);
- CHKCON((m_op = m_tx->getNdbOperation(tab.m_name)) != 0, *this);
+ CHKCON((m_op = m_scanop = m_tx->getNdbScanOperation(tab.m_name)) != 0, *this);
return 0;
}
int
-Con::getNdbOperation(const ITab& itab, const Tab& tab)
+Con::getNdbScanOperation(const ITab& itab, const Tab& tab)
{
- CHKCON((m_op = m_tx->getNdbOperation(itab.m_name, tab.m_name)) != 0, *this);
+ assert(m_tx != 0);
+ CHKCON((m_op = m_scanop = m_indexscanop = m_tx->getNdbIndexScanOperation(itab.m_name, tab.m_name)) != 0, *this);
return 0;
}
@@ -681,7 +776,7 @@ int
Con::setBound(int num, int type, const void* value)
{
assert(m_tx != 0 && m_op != 0);
- CHKCON(m_op->setBound(num, type, value) == 0, *this);
+ CHKCON(m_indexscanop->setBound(num, type, value) == 0, *this);
return 0;
}
@@ -694,10 +789,26 @@ Con::execute(ExecType t)
}
int
+Con::execute(ExecType t, bool& deadlock)
+{
+ int ret = execute(t);
+ if (ret != 0) {
+ if (deadlock && m_errtype == ErrDeadlock) {
+ LL3("caught deadlock");
+ ret = 0;
+ }
+ } else {
+ deadlock = false;
+ }
+ CHK(ret == 0);
+ return 0;
+}
+
+int
Con::openScanRead(unsigned parallelism)
{
assert(m_tx != 0 && m_op != 0);
- CHKCON(m_op->openScanRead(parallelism) == 0, *this);
+ CHKCON((m_resultset = m_scanop->readTuples(parallelism)) != 0, *this);
return 0;
}
@@ -705,39 +816,56 @@ int
Con::openScanExclusive(unsigned parallelism)
{
assert(m_tx != 0 && m_op != 0);
- CHKCON(m_op->openScanExclusive(parallelism) == 0, *this);
+ CHKCON((m_resultset = m_scanop->readTuplesExclusive(parallelism)) != 0, *this);
return 0;
}
int
Con::executeScan()
{
- CHKCON(m_tx->executeScan() == 0, *this);
+ CHKCON(m_tx->execute(NoCommit) == 0, *this);
return 0;
}
int
-Con::nextScanResult()
+Con::nextScanResult(bool fetchAllowed)
{
int ret;
- CHKCON((ret = m_tx->nextScanResult()) != -1, *this);
- assert(ret == 0 || ret == 1);
+ assert(m_resultset != 0);
+ CHKCON((ret = m_resultset->nextResult(fetchAllowed)) != -1, *this);
+ assert(ret == 0 || ret == 1 || (! fetchAllowed && ret == 2));
+ return ret;
+}
+
+int
+Con::nextScanResult(bool fetchAllowed, bool& deadlock)
+{
+ int ret = nextScanResult(fetchAllowed);
+ if (ret == -1) {
+ if (deadlock && m_errtype == ErrDeadlock) {
+ LL3("caught deadlock");
+ ret = 0;
+ }
+ } else {
+ deadlock = false;
+ }
+ CHK(ret == 0 || ret == 1 || (! fetchAllowed && ret == 2));
return ret;
}
int
-Con::takeOverForUpdate(Con& scan)
+Con::updateScanTuple(Con& con2)
{
- assert(m_tx != 0 && scan.m_op != 0);
- CHKCON((m_op = scan.m_op->takeOverForUpdate(m_tx)) != 0, scan);
+ assert(con2.m_tx != 0);
+ CHKCON((con2.m_op = m_resultset->updateTuple(con2.m_tx)) != 0, *this);
return 0;
}
int
-Con::takeOverForDelete(Con& scan)
+Con::deleteScanTuple(Con& con2)
{
- assert(m_tx != 0 && scan.m_op != 0);
- CHKCON((m_op = scan.m_op->takeOverForUpdate(m_tx)) != 0, scan);
+ assert(con2.m_tx != 0);
+ CHKCON(m_resultset->deleteTuple(con2.m_tx) == 0, *this);
return 0;
}
@@ -765,7 +893,7 @@ Con::printerror(NdbOut& out)
if (m_tx) {
if ((code = m_tx->getNdbError().code) != 0) {
LL0(++any << " con: error " << m_tx->getNdbError());
- if (code == 266 || code == 274 || code == 296 || code == 297)
+ if (code == 266 || code == 274 || code == 296 || code == 297 || code == 499)
m_errtype = ErrDeadlock;
}
if (m_op && m_op->getNdbError().code != 0) {
@@ -785,7 +913,7 @@ invalidateindex(Par par, const ITab& itab)
{
Con& con = par.con();
const Tab& tab = par.tab();
- con.m_dic->invalidateIndex(itab.m_name, tab.m_name);
+ con.m_ndb->getDictionary()->invalidateIndex(itab.m_name, tab.m_name);
return 0;
}
@@ -809,7 +937,7 @@ invalidatetable(Par par)
Con& con = par.con();
const Tab& tab = par.tab();
invalidateindex(par);
- con.m_dic->invalidateTable(tab.m_name);
+ con.m_ndb->getDictionary()->invalidateTable(tab.m_name);
return 0;
}
@@ -818,6 +946,7 @@ droptable(Par par)
{
Con& con = par.con();
const Tab& tab = par.tab();
+ con.m_dic = con.m_ndb->getDictionary();
if (con.m_dic->getTable(tab.m_name) == 0) {
// how to check for error
LL4("no table " << tab.m_name);
@@ -825,6 +954,7 @@ droptable(Par par)
LL3("drop table " << tab.m_name);
CHKCON(con.m_dic->dropTable(tab.m_name) == 0, con);
}
+ con.m_dic = 0;
return 0;
}
@@ -832,7 +962,6 @@ static int
createtable(Par par)
{
Con& con = par.con();
- CHK(con.bugger() == 0);
const Tab& tab = par.tab();
LL3("create table " << tab.m_name);
LL4(tab);
@@ -852,7 +981,9 @@ createtable(Par par)
c.setNullable(col.m_nullable);
t.addColumn(c);
}
+ con.m_dic = con.m_ndb->getDictionary();
CHKCON(con.m_dic->createTable(t) == 0, con);
+ con.m_dic = 0;
return 0;
}
@@ -861,6 +992,7 @@ dropindex(Par par, const ITab& itab)
{
Con& con = par.con();
const Tab& tab = par.tab();
+ con.m_dic = con.m_ndb->getDictionary();
if (con.m_dic->getIndex(itab.m_name, tab.m_name) == 0) {
// how to check for error
LL4("no index " << itab.m_name);
@@ -868,6 +1000,7 @@ dropindex(Par par, const ITab& itab)
LL3("drop index " << itab.m_name);
CHKCON(con.m_dic->dropIndex(itab.m_name, tab.m_name) == 0, con);
}
+ con.m_dic = 0;
return 0;
}
@@ -888,7 +1021,6 @@ static int
createindex(Par par, const ITab& itab)
{
Con& con = par.con();
- CHK(con.bugger() == 0);
const Tab& tab = par.tab();
LL3("create index " << itab.m_name);
LL4(itab);
@@ -900,7 +1032,9 @@ createindex(Par par, const ITab& itab)
const Col& col = itab.m_icol[k].m_col;
x.addColumnName(col.m_name);
}
+ con.m_dic = con.m_ndb->getDictionary();
CHKCON(con.m_dic->createIndex(x) == 0, con);
+ con.m_dic = 0;
return 0;
}
@@ -1115,9 +1249,9 @@ Val::cmp(const Val& val2) const
assert(col.m_type == col2.m_type && col.m_length == col2.m_length);
if (m_null || val2.m_null) {
if (! m_null)
- return -1;
- if (! val2.m_null)
return +1;
+ if (! val2.m_null)
+ return -1;
return 0;
}
// verify data formats
@@ -1175,6 +1309,8 @@ struct Row {
const Tab& m_tab;
Val** m_val;
bool m_exist;
+ enum Op { NoOp = 0, ReadOp, InsOp, UpdOp, DelOp };
+ Op m_pending;
Row(const Tab& tab);
~Row();
void copy(const Row& row2);
@@ -1199,6 +1335,7 @@ Row::Row(const Tab& tab) :
m_val[k] = new Val(col);
}
m_exist = false;
+ m_pending = NoOp;
}
Row::~Row()
@@ -1236,7 +1373,7 @@ int
Row::verify(const Row& row2) const
{
const Tab& tab = m_tab;
- assert(&tab == &row2.m_tab);
+ assert(&tab == &row2.m_tab && m_exist && row2.m_exist);
for (unsigned k = 0; k < tab.m_cols; k++) {
const Val& val = *m_val[k];
const Val& val2 = *row2.m_val[k];
@@ -1257,7 +1394,7 @@ Row::insrow(Par par)
const Val& val = *m_val[k];
CHK(val.setval(par) == 0);
}
- m_exist = true;
+ m_pending = InsOp;
return 0;
}
@@ -1273,6 +1410,7 @@ Row::updrow(Par par)
const Val& val = *m_val[k];
CHK(val.setval(par) == 0);
}
+ m_pending = UpdOp;
return 0;
}
@@ -1290,7 +1428,7 @@ Row::delrow(Par par)
if (col.m_pk)
CHK(val.setval(par) == 0);
}
- m_exist = false;
+ m_pending = DelOp;
return 0;
}
@@ -1307,7 +1445,6 @@ Row::selrow(Par par)
if (col.m_pk)
CHK(val.setval(par) == 0);
}
- m_exist = false;
return 0;
}
@@ -1322,6 +1459,7 @@ Row::setrow(Par par)
if (! col.m_pk)
CHK(val.setval(par) == 0);
}
+ m_pending = UpdOp;
return 0;
}
@@ -1349,6 +1487,10 @@ operator<<(NdbOut& out, const Row& row)
out << " ";
out << *row.m_val[i];
}
+ out << " [exist=" << row.m_exist;
+ if (row.m_pending)
+ out << " pending=" << row.m_pending;
+ out << "]";
return out;
}
@@ -1357,15 +1499,19 @@ operator<<(NdbOut& out, const Row& row)
struct Set {
const Tab& m_tab;
unsigned m_rows;
- unsigned m_count;
Row** m_row;
Row** m_saverow;
Row* m_keyrow;
NdbRecAttr** m_rec;
Set(const Tab& tab, unsigned rows);
~Set();
+ void reset();
+ unsigned count() const;
// row methods
bool exist(unsigned i) const;
+ Row::Op pending(unsigned i) const;
+ void notpending(unsigned i);
+ void notpending(const Lst& lst);
void calc(Par par, unsigned i);
int insrow(Par par, unsigned i);
int updrow(Par par, unsigned i);
@@ -1380,7 +1526,7 @@ struct Set {
void savepoint();
void commit();
void rollback();
- // locking (not perfect since ops may complete in different order)
+ // protect structure
NdbMutex* m_mutex;
void lock() {
NdbMutex_Lock(m_mutex);
@@ -1396,9 +1542,9 @@ Set::Set(const Tab& tab, unsigned rows) :
m_tab(tab)
{
m_rows = rows;
- m_count = 0;
m_row = new Row* [m_rows];
for (unsigned i = 0; i < m_rows; i++) {
+ // allocate on need to save space
m_row[i] = 0;
}
m_saverow = 0;
@@ -1425,11 +1571,47 @@ Set::~Set()
NdbMutex_Destroy(m_mutex);
}
+void
+Set::reset()
+{
+ for (unsigned i = 0; i < m_rows; i++) {
+ if (m_row[i] != 0) {
+ Row& row = *m_row[i];
+ row.m_exist = false;
+ }
+ }
+}
+
+unsigned
+Set::count() const
+{
+ unsigned count = 0;
+ for (unsigned i = 0; i < m_rows; i++) {
+ if (m_row[i] != 0) {
+ Row& row = *m_row[i];
+ if (row.m_exist)
+ count++;
+ }
+ }
+ return count;
+}
+
bool
Set::exist(unsigned i) const
{
assert(i < m_rows);
- return m_row[i] != 0 && m_row[i]->m_exist;
+ if (m_row[i] == 0) // not allocated => not exist
+ return false;
+ return m_row[i]->m_exist;
+}
+
+Row::Op
+Set::pending(unsigned i) const
+{
+ assert(i < m_rows);
+ if (m_row[i] == 0) // not allocated => not pending
+ return Row::NoOp;
+ return m_row[i]->m_pending;
}
void
@@ -1448,9 +1630,9 @@ Set::calc(Par par, unsigned i)
int
Set::insrow(Par par, unsigned i)
{
- assert(m_row[i] != 0 && m_count < m_rows);
- CHK(m_row[i]->insrow(par) == 0);
- m_count++;
+ assert(m_row[i] != 0);
+ Row& row = *m_row[i];
+ CHK(row.insrow(par) == 0);
return 0;
}
@@ -1458,16 +1640,17 @@ int
Set::updrow(Par par, unsigned i)
{
assert(m_row[i] != 0);
- CHK(m_row[i]->updrow(par) == 0);
+ Row& row = *m_row[i];
+ CHK(row.updrow(par) == 0);
return 0;
}
int
Set::delrow(Par par, unsigned i)
{
- assert(m_row[i] != 0 && m_count != 0);
- CHK(m_row[i]->delrow(par) == 0);
- m_count--;
+ assert(m_row[i] != 0);
+ Row& row = *m_row[i];
+ CHK(row.delrow(par) == 0);
return 0;
}
@@ -1507,7 +1690,7 @@ Set::getkey(Par par, unsigned* i)
assert(m_rec[0] != 0);
const char* aRef0 = m_rec[0]->aRef();
Uint32 key = *(const Uint32*)aRef0;
- CHKMSG(key < m_rows, "key=" << key << " rows=" << m_rows);
+ CHK(key < m_rows);
*i = key;
return 0;
}
@@ -1532,19 +1715,37 @@ Set::putval(unsigned i, bool force)
val.copy(aRef);
val.m_null = false;
}
- if (! row.m_exist) {
+ if (! row.m_exist)
row.m_exist = true;
- m_count++;
- }
return 0;
}
+void
+Set::notpending(unsigned i)
+{
+ assert(m_row[i] != 0);
+ Row& row = *m_row[i];
+ if (row.m_pending == Row::InsOp)
+ row.m_exist = true;
+ if (row.m_pending == Row::DelOp)
+ row.m_exist = false;
+ row.m_pending = Row::NoOp;
+}
+
+void
+Set::notpending(const Lst& lst)
+{
+ for (unsigned j = 0; j < lst.m_cnt; j++) {
+ unsigned i = lst.m_arr[j];
+ notpending(i);
+ }
+}
+
int
Set::verify(const Set& set2) const
{
const Tab& tab = m_tab;
assert(&tab == &set2.m_tab && m_rows == set2.m_rows);
- CHKMSG(m_count == set2.m_count, "set=" << m_count << " set2=" << set2.m_count);
for (unsigned i = 0; i < m_rows; i++) {
CHK(exist(i) == set2.exist(i));
if (! exist(i))
@@ -1618,8 +1819,8 @@ int
BVal::setbnd(Par par) const
{
Con& con = par.con();
- const char* addr = (const char*)dataaddr();
- assert(! m_null);
+ assert(g_compare_null || ! m_null);
+ const char* addr = ! m_null ? (const char*)dataaddr() : 0;
const ICol& icol = m_icol;
CHK(con.setBound(icol.m_num, m_type, addr) == 0);
return 0;
@@ -1647,7 +1848,10 @@ struct BSet {
unsigned m_bvals;
BVal** m_bval;
BSet(const Tab& tab, const ITab& itab, unsigned rows);
+ ~BSet();
+ void reset();
void calc(Par par);
+ void calcpk(Par par, unsigned i);
int setbnd(Par par) const;
void filter(const Set& set, Set& set2) const;
};
@@ -1659,12 +1863,31 @@ BSet::BSet(const Tab& tab, const ITab& itab, unsigned rows) :
m_bvals(0)
{
m_bval = new BVal* [m_alloc];
+ for (unsigned i = 0; i < m_alloc; i++) {
+ m_bval[i] = 0;
+ }
+}
+
+BSet::~BSet()
+{
+ delete [] m_bval;
+}
+
+void
+BSet::reset()
+{
+ while (m_bvals > 0) {
+ unsigned i = --m_bvals;
+ delete m_bval[i];
+ m_bval[i] = 0;
+ }
}
void
BSet::calc(Par par)
{
const ITab& itab = m_itab;
+ reset();
for (unsigned k = 0; k < itab.m_icols; k++) {
const ICol& icol = itab.m_icol[k];
const Col& col = icol.m_col;
@@ -1686,7 +1909,8 @@ BSet::calc(Par par)
if (k + 1 < itab.m_icols)
bval.m_type = 4;
// value generation parammeters
- par.m_pctnull = 0;
+ if (! g_compare_null)
+ par.m_pctnull = 0;
par.m_pctrange = 50; // bit higher
do {
bval.calc(par, 0);
@@ -1705,6 +1929,23 @@ BSet::calc(Par par)
}
}
+void
+BSet::calcpk(Par par, unsigned i)
+{
+ const ITab& itab = m_itab;
+ reset();
+ for (unsigned k = 0; k < itab.m_icols; k++) {
+ const ICol& icol = itab.m_icol[k];
+ const Col& col = icol.m_col;
+ assert(col.m_pk);
+ assert(m_bvals < m_alloc);
+ BVal& bval = *new BVal(icol);
+ m_bval[m_bvals++] = &bval;
+ bval.m_type = 4;
+ bval.calc(par, i);
+ }
+}
+
int
BSet::setbnd(Par par) const
{
@@ -1721,23 +1962,25 @@ BSet::filter(const Set& set, Set& set2) const
const Tab& tab = m_tab;
const ITab& itab = m_itab;
assert(&tab == &set2.m_tab && set.m_rows == set2.m_rows);
- assert(set2.m_count == 0);
+ assert(set2.count() == 0);
for (unsigned i = 0; i < set.m_rows; i++) {
if (! set.exist(i))
continue;
const Row& row = *set.m_row[i];
- bool ok1 = false;
- for (unsigned k = 0; k < itab.m_icols; k++) {
- const ICol& icol = itab.m_icol[k];
- const Col& col = icol.m_col;
- const Val& val = *row.m_val[col.m_num];
- if (! val.m_null) {
- ok1 = true;
- break;
+ if (! g_store_null_key) {
+ bool ok1 = false;
+ for (unsigned k = 0; k < itab.m_icols; k++) {
+ const ICol& icol = itab.m_icol[k];
+ const Col& col = icol.m_col;
+ const Val& val = *row.m_val[col.m_num];
+ if (! val.m_null) {
+ ok1 = true;
+ break;
+ }
}
+ if (! ok1)
+ continue;
}
- if (! ok1)
- continue;
bool ok2 = true;
for (unsigned j = 0; j < m_bvals; j++) {
const BVal& bval = *m_bval[j];
@@ -1769,7 +2012,6 @@ BSet::filter(const Set& set, Set& set2) const
assert(! row2.m_exist);
row2.copy(row);
row2.m_exist = true;
- set2.m_count++;
}
}
@@ -1794,28 +2036,46 @@ pkinsert(Par par)
Set& set = par.set();
LL3("pkinsert");
CHK(con.startTransaction() == 0);
- unsigned n = 0;
+ Lst lst;
for (unsigned j = 0; j < par.m_rows; j++) {
unsigned i = thrrow(par, j);
set.lock();
- if (set.exist(i)) {
+ if (set.exist(i) || set.pending(i)) {
set.unlock();
continue;
}
set.calc(par, i);
- LL4("pkinsert " << i << ": " << *set.m_row[i]);
- CHKTRY(set.insrow(par, i) == 0, set.unlock());
+ CHK(set.insrow(par, i) == 0);
set.unlock();
- if (++n == par.m_batch) {
- CHK(con.execute(Commit) == 0);
+ LL4("pkinsert " << i << ": " << *set.m_row[i]);
+ lst.push(i);
+ if (lst.cnt() == par.m_batch) {
+ bool deadlock = par.m_deadlock;
+ CHK(con.execute(Commit, deadlock) == 0);
con.closeTransaction();
+ if (deadlock) {
+ LL1("pkinsert: stop on deadlock");
+ return 0;
+ }
+ set.lock();
+ set.notpending(lst);
+ set.unlock();
+ lst.reset();
CHK(con.startTransaction() == 0);
- n = 0;
}
}
- if (n != 0) {
- CHK(con.execute(Commit) == 0);
- n = 0;
+ if (lst.cnt() != 0) {
+ bool deadlock = par.m_deadlock;
+ CHK(con.execute(Commit, deadlock) == 0);
+ con.closeTransaction();
+ if (deadlock) {
+ LL1("pkinsert: stop on deadlock");
+ return 0;
+ }
+ set.lock();
+ set.notpending(lst);
+ set.unlock();
+ return 0;
}
con.closeTransaction();
return 0;
@@ -1828,28 +2088,45 @@ pkupdate(Par par)
Set& set = par.set();
LL3("pkupdate");
CHK(con.startTransaction() == 0);
- unsigned n = 0;
+ Lst lst;
+ bool deadlock = false;
for (unsigned j = 0; j < par.m_rows; j++) {
unsigned i = thrrow(par, j);
set.lock();
- if (! set.exist(i)) {
+ if (! set.exist(i) || set.pending(i)) {
set.unlock();
continue;
}
set.calc(par, i);
- LL4("pkupdate " << i << ": " << *set.m_row[i]);
- CHKTRY(set.updrow(par, i) == 0, set.unlock());
+ CHK(set.updrow(par, i) == 0);
set.unlock();
- if (++n == par.m_batch) {
- CHK(con.execute(Commit) == 0);
+ LL4("pkupdate " << i << ": " << *set.m_row[i]);
+ lst.push(i);
+ if (lst.cnt() == par.m_batch) {
+ deadlock = par.m_deadlock;
+ CHK(con.execute(Commit, deadlock) == 0);
+ if (deadlock) {
+ LL1("pkupdate: stop on deadlock");
+ break;
+ }
con.closeTransaction();
+ set.lock();
+ set.notpending(lst);
+ set.unlock();
+ lst.reset();
CHK(con.startTransaction() == 0);
- n = 0;
}
}
- if (n != 0) {
- CHK(con.execute(Commit) == 0);
- n = 0;
+ if (! deadlock && lst.cnt() != 0) {
+ deadlock = par.m_deadlock;
+ CHK(con.execute(Commit, deadlock) == 0);
+ if (deadlock) {
+ LL1("pkupdate: stop on deadlock");
+ } else {
+ set.lock();
+ set.notpending(lst);
+ set.unlock();
+ }
}
con.closeTransaction();
return 0;
@@ -1862,27 +2139,44 @@ pkdelete(Par par)
Set& set = par.set();
LL3("pkdelete");
CHK(con.startTransaction() == 0);
- unsigned n = 0;
+ Lst lst;
+ bool deadlock = false;
for (unsigned j = 0; j < par.m_rows; j++) {
unsigned i = thrrow(par, j);
set.lock();
- if (! set.exist(i)) {
+ if (! set.exist(i) || set.pending(i)) {
set.unlock();
continue;
}
- LL4("pkdelete " << i << ": " << *set.m_row[i]);
- CHKTRY(set.delrow(par, i) == 0, set.unlock());
+ CHK(set.delrow(par, i) == 0);
set.unlock();
- if (++n == par.m_batch) {
- CHK(con.execute(Commit) == 0);
+ LL4("pkdelete " << i << ": " << *set.m_row[i]);
+ lst.push(i);
+ if (lst.cnt() == par.m_batch) {
+ deadlock = par.m_deadlock;
+ CHK(con.execute(Commit, deadlock) == 0);
+ if (deadlock) {
+ LL1("pkdelete: stop on deadlock");
+ break;
+ }
con.closeTransaction();
+ set.lock();
+ set.notpending(lst);
+ set.unlock();
+ lst.reset();
CHK(con.startTransaction() == 0);
- n = 0;
}
}
- if (n != 0) {
- CHK(con.execute(Commit) == 0);
- n = 0;
+ if (! deadlock && lst.cnt() != 0) {
+ deadlock = par.m_deadlock;
+ CHK(con.execute(Commit, deadlock) == 0);
+ if (deadlock) {
+ LL1("pkdelete: stop on deadlock");
+ } else {
+ set.lock();
+ set.notpending(lst);
+ set.unlock();
+ }
}
con.closeTransaction();
return 0;
@@ -1893,21 +2187,25 @@ pkread(Par par)
{
Con& con = par.con();
const Tab& tab = par.tab();
- const Set& set = par.set();
+ Set& set = par.set();
LL3((par.m_verify ? "pkverify " : "pkread ") << tab.m_name);
// expected
const Set& set1 = set;
Set set2(tab, set.m_rows);
for (unsigned i = 0; i < set.m_rows; i++) {
- if (! set.exist(i))
+ set.lock();
+ if (! set.exist(i) || set.pending(i)) {
+ set.unlock();
continue;
+ }
+ set.unlock();
CHK(con.startTransaction() == 0);
CHK(set2.selrow(par, i) == 0);
CHK(con.execute(Commit) == 0);
unsigned i2 = (unsigned)-1;
CHK(set2.getkey(par, &i2) == 0 && i == i2);
CHK(set2.putval(i, false) == 0);
- LL4("row " << set2.m_count << ": " << *set2.m_row[i]);
+ LL4("row " << set2.count() << ": " << *set2.m_row[i]);
con.closeTransaction();
}
if (par.m_verify)
@@ -1915,6 +2213,32 @@ pkread(Par par)
return 0;
}
+static int
+pkreadfast(Par par, unsigned count)
+{
+ Con& con = par.con();
+ const Tab& tab = par.tab();
+ const Set& set = par.set();
+ LL3("pkfast " << tab.m_name);
+ Row keyrow(tab);
+ // not batched on purpose
+ for (unsigned j = 0; j < count; j++) {
+ unsigned i = urandom(set.m_rows);
+ assert(set.exist(i));
+ CHK(con.startTransaction() == 0);
+ // define key
+ keyrow.calc(par, i);
+ CHK(keyrow.selrow(par) == 0);
+ NdbRecAttr* rec;
+ CHK(con.getValue((Uint32)0, rec) == 0);
+ CHK(con.executeScan() == 0);
+ // get 1st column
+ CHK(con.execute(Commit) == 0);
+ con.closeTransaction();
+ }
+ return 0;
+}
+
// scan read
static int
@@ -1928,19 +2252,19 @@ scanreadtable(Par par)
LL3((par.m_verify ? "scanverify " : "scanread ") << tab.m_name);
Set set2(tab, set.m_rows);
CHK(con.startTransaction() == 0);
- CHK(con.getNdbOperation(tab) == 0);
+ CHK(con.getNdbScanOperation(tab) == 0);
CHK(con.openScanRead(par.m_scanrd) == 0);
set2.getval(par);
CHK(con.executeScan() == 0);
while (1) {
int ret;
- CHK((ret = con.nextScanResult()) == 0 || ret == 1);
+ CHK((ret = con.nextScanResult(true)) == 0 || ret == 1);
if (ret == 1)
break;
unsigned i = (unsigned)-1;
CHK(set2.getkey(par, &i) == 0);
CHK(set2.putval(i, false) == 0);
- LL4("row " << set2.m_count << ": " << *set2.m_row[i]);
+ LL4("row " << set2.count() << ": " << *set2.m_row[i]);
}
con.closeTransaction();
if (par.m_verify)
@@ -1949,6 +2273,33 @@ scanreadtable(Par par)
}
static int
+scanreadtablefast(Par par, unsigned countcheck)
+{
+ Con& con = par.con();
+ const Tab& tab = par.tab();
+ const Set& set = par.set();
+ LL3("scanfast " << tab.m_name);
+ CHK(con.startTransaction() == 0);
+ CHK(con.getNdbScanOperation(tab) == 0);
+ CHK(con.openScanRead(par.m_scanrd) == 0);
+ // get 1st column
+ NdbRecAttr* rec;
+ CHK(con.getValue((Uint32)0, rec) == 0);
+ CHK(con.executeScan() == 0);
+ unsigned count = 0;
+ while (1) {
+ int ret;
+ CHK((ret = con.nextScanResult(true)) == 0 || ret == 1);
+ if (ret == 1)
+ break;
+ count++;
+ }
+ con.closeTransaction();
+ CHK(count == countcheck);
+ return 0;
+}
+
+static int
scanreadindex(Par par, const ITab& itab, const BSet& bset)
{
Con& con = par.con();
@@ -1961,21 +2312,21 @@ scanreadindex(Par par, const ITab& itab, const BSet& bset)
LL4(bset);
Set set2(tab, set.m_rows);
CHK(con.startTransaction() == 0);
- CHK(con.getNdbOperation(itab, tab) == 0);
+ CHK(con.getNdbScanOperation(itab, tab) == 0);
CHK(con.openScanRead(par.m_scanrd) == 0);
CHK(bset.setbnd(par) == 0);
set2.getval(par);
CHK(con.executeScan() == 0);
while (1) {
int ret;
- CHK((ret = con.nextScanResult()) == 0 || ret == 1);
+ CHK((ret = con.nextScanResult(true)) == 0 || ret == 1);
if (ret == 1)
break;
unsigned i = (unsigned)-1;
CHK(set2.getkey(par, &i) == 0);
LL4("key " << i);
CHK(set2.putval(i, par.m_dups) == 0);
- LL4("row " << set2.m_count << ": " << *set2.m_row[i]);
+ LL4("row " << set2.count() << ": " << *set2.m_row[i]);
}
con.closeTransaction();
if (par.m_verify)
@@ -1984,10 +2335,39 @@ scanreadindex(Par par, const ITab& itab, const BSet& bset)
}
static int
+scanreadindexfast(Par par, const ITab& itab, const BSet& bset, unsigned countcheck)
+{
+ Con& con = par.con();
+ const Tab& tab = par.tab();
+ const Set& set = par.set();
+ LL3("scanfast " << itab.m_name << " bounds=" << bset.m_bvals);
+ LL4(bset);
+ CHK(con.startTransaction() == 0);
+ CHK(con.getNdbScanOperation(itab, tab) == 0);
+ CHK(con.openScanRead(par.m_scanrd) == 0);
+ CHK(bset.setbnd(par) == 0);
+ // get 1st column
+ NdbRecAttr* rec;
+ CHK(con.getValue((Uint32)0, rec) == 0);
+ CHK(con.executeScan() == 0);
+ unsigned count = 0;
+ while (1) {
+ int ret;
+ CHK((ret = con.nextScanResult(true)) == 0 || ret == 1);
+ if (ret == 1)
+ break;
+ count++;
+ }
+ con.closeTransaction();
+ CHK(count == countcheck);
+ return 0;
+}
+
+static int
scanreadindex(Par par, const ITab& itab)
{
const Tab& tab = par.tab();
- for (unsigned i = 0; i < par.m_subloop; i++) {
+ for (unsigned i = 0; i < par.m_idxloop; i++) {
BSet bset(tab, itab, par.m_rows);
bset.calc(par);
CHK(scanreadindex(par, itab, bset) == 0);
@@ -2017,6 +2397,60 @@ scanreadall(Par par)
return 0;
}
+// timing scans
+
+static int
+timescantable(Par par)
+{
+ par.tmr().on();
+ CHK(scanreadtablefast(par, par.m_totrows) == 0);
+ par.tmr().off(par.set().m_rows);
+ return 0;
+}
+
+static int
+timescanpkindex(Par par)
+{
+ const Tab& tab = par.tab();
+ const ITab& itab = tab.m_itab[0]; // 1st index is on PK
+ BSet bset(tab, itab, par.m_rows);
+ par.tmr().on();
+ CHK(scanreadindexfast(par, itab, bset, par.m_totrows) == 0);
+ par.tmr().off(par.set().m_rows);
+ return 0;
+}
+
+static int
+timepkreadtable(Par par)
+{
+ par.tmr().on();
+ unsigned count = par.m_samples;
+ if (count == 0)
+ count = par.m_totrows;
+ CHK(pkreadfast(par, count) == 0);
+ par.tmr().off(count);
+ return 0;
+}
+
+static int
+timepkreadindex(Par par)
+{
+ const Tab& tab = par.tab();
+ const ITab& itab = tab.m_itab[0]; // 1st index is on PK
+ BSet bset(tab, itab, par.m_rows);
+ unsigned count = par.m_samples;
+ if (count == 0)
+ count = par.m_totrows;
+ par.tmr().on();
+ for (unsigned j = 0; j < count; j++) {
+ unsigned i = urandom(par.m_totrows);
+ bset.calcpk(par, i);
+ CHK(scanreadindexfast(par, itab, bset, 1) == 0);
+ }
+ par.tmr().off(count);
+ return 0;
+}
+
// scan update
static int
@@ -2028,36 +2462,70 @@ scanupdatetable(Par par)
LL3("scan update " << tab.m_name);
Set set2(tab, set.m_rows);
CHK(con.startTransaction() == 0);
- CHK(con.getNdbOperation(tab) == 0);
+ CHK(con.getNdbScanOperation(tab) == 0);
CHK(con.openScanExclusive(par.m_scanex) == 0);
set2.getval(par);
CHK(con.executeScan() == 0);
unsigned count = 0;
// updating trans
Con con2;
- con2.m_ndb = con.m_ndb;
- CHK(con2.startBuddyTransaction(con) == 0);
+ con2.connect(con);
+ CHK(con2.startTransaction() == 0);
+ Lst lst;
+ bool deadlock = false;
while (1) {
int ret;
- CHK((ret = con.nextScanResult()) == 0 || ret == 1);
+ deadlock = par.m_deadlock;
+ CHK((ret = con.nextScanResult(true, deadlock)) == 0 || ret == 1);
+ if (ret == 1)
+ break;
+ if (deadlock) {
+ LL1("scanupdatetable: stop on deadlock");
+ break;
+ }
+ do {
+ unsigned i = (unsigned)-1;
+ CHK(set2.getkey(par, &i) == 0);
+ const Row& row = *set.m_row[i];
+ set.lock();
+ if (! set.exist(i) || set.pending(i)) {
+ LL4("scan update " << tab.m_name << ": skip: " << row);
+ } else {
+ CHKTRY(set2.putval(i, false) == 0, set.unlock());
+ CHKTRY(con.updateScanTuple(con2) == 0, set.unlock());
+ Par par2 = par;
+ par2.m_con = &con2;
+ set.calc(par, i);
+ CHKTRY(set.setrow(par2, i) == 0, set.unlock());
+ LL4("scan update " << tab.m_name << ": " << row);
+ lst.push(i);
+ }
+ set.unlock();
+ if (lst.cnt() == par.m_batch) {
+ CHK(con2.execute(Commit) == 0);
+ con2.closeTransaction();
+ set.lock();
+ set.notpending(lst);
+ set.unlock();
+ count += lst.cnt();
+ lst.reset();
+ CHK(con2.startTransaction() == 0);
+ }
+ CHK((ret = con.nextScanResult(false)) == 0 || ret == 1 || ret == 2);
+ if (ret == 2 && lst.cnt() != 0) {
+ CHK(con2.execute(Commit) == 0);
+ con2.closeTransaction();
+ set.lock();
+ set.notpending(lst);
+ set.unlock();
+ count += lst.cnt();
+ lst.reset();
+ CHK(con2.startTransaction() == 0);
+ }
+ } while (ret == 0);
if (ret == 1)
break;
- unsigned i = (unsigned)-1;
- CHK(set2.getkey(par, &i) == 0);
- LL4("key " << i);
- CHK(set2.putval(i, false) == 0);
- CHK(con2.takeOverForUpdate(con) == 0);
- Par par2 = par;
- par2.m_con = &con2;
- set.lock();
- set.calc(par, i);
- LL4("scan update " << tab.m_name << ": " << *set.m_row[i]);
- CHKTRY(set.setrow(par2, i) == 0, set.unlock());
- set.unlock();
- CHK(con2.execute(NoCommit) == 0);
- count++;
}
- CHK(con2.execute(Commit) == 0);
con2.closeTransaction();
LL3("scan update " << tab.m_name << " rows updated=" << count);
con.closeTransaction();
@@ -2073,7 +2541,7 @@ scanupdateindex(Par par, const ITab& itab, const BSet& bset)
LL3("scan update " << itab.m_name);
Set set2(tab, set.m_rows);
CHK(con.startTransaction() == 0);
- CHK(con.getNdbOperation(itab, tab) == 0);
+ CHK(con.getNdbScanOperation(itab, tab) == 0);
CHK(con.openScanExclusive(par.m_scanex) == 0);
CHK(bset.setbnd(par) == 0);
set2.getval(par);
@@ -2081,32 +2549,61 @@ scanupdateindex(Par par, const ITab& itab, const BSet& bset)
unsigned count = 0;
// updating trans
Con con2;
- con2.m_ndb = con.m_ndb;
- CHK(con2.startBuddyTransaction(con) == 0);
+ con2.connect(con);
+ CHK(con2.startTransaction() == 0);
+ Lst lst;
+ bool deadlock = false;
while (1) {
int ret;
- CHK((ret = con.nextScanResult()) == 0 || ret == 1);
+ deadlock = par.m_deadlock;
+ CHK((ret = con.nextScanResult(true, deadlock)) == 0 || ret == 1);
if (ret == 1)
break;
- unsigned i = (unsigned)-1;
- CHK(set2.getkey(par, &i) == 0);
- LL4("key " << i);
- CHK(set2.putval(i, par.m_dups) == 0);
- // avoid deadlock for now
- //if (! isthrrow(par, i))
- //continue;
- CHK(con2.takeOverForUpdate(con) == 0);
- Par par2 = par;
- par2.m_con = &con2;
- set.lock();
- set.calc(par, i);
- LL4("scan update " << itab.m_name << ": " << *set.m_row[i]);
- CHKTRY(set.setrow(par2, i) == 0, set.unlock());
- set.unlock();
- CHK(con2.execute(NoCommit) == 0);
- count++;
+ if (deadlock) {
+ LL1("scanupdateindex: stop on deadlock");
+ break;
+ }
+ do {
+ unsigned i = (unsigned)-1;
+ CHK(set2.getkey(par, &i) == 0);
+ const Row& row = *set.m_row[i];
+ set.lock();
+ if (! set.exist(i) || set.pending(i)) {
+ LL4("scan update " << itab.m_name << ": skip: " << row);
+ } else {
+ CHKTRY(set2.putval(i, par.m_dups) == 0, set.unlock());
+ CHKTRY(con.updateScanTuple(con2) == 0, set.unlock());
+ Par par2 = par;
+ par2.m_con = &con2;
+ set.calc(par, i);
+ CHKTRY(set.setrow(par2, i) == 0, set.unlock());
+ LL4("scan update " << itab.m_name << ": " << row);
+ lst.push(i);
+ }
+ set.unlock();
+ if (lst.cnt() == par.m_batch) {
+ CHK(con2.execute(Commit) == 0);
+ con2.closeTransaction();
+ set.lock();
+ set.notpending(lst);
+ set.unlock();
+ count += lst.cnt();
+ lst.reset();
+ CHK(con2.startTransaction() == 0);
+ }
+ CHK((ret = con.nextScanResult(false)) == 0 || ret == 1 || ret == 2);
+ if (ret == 2 && lst.cnt() != 0) {
+ CHK(con2.execute(Commit) == 0);
+ con2.closeTransaction();
+ set.lock();
+ set.notpending(lst);
+ set.unlock();
+ count += lst.cnt();
+ lst.reset();
+ CHK(con2.startTransaction() == 0);
+ }
+ } while (ret == 0);
}
- CHK(con2.execute(Commit) == 0);
con2.closeTransaction();
LL3("scan update " << itab.m_name << " rows updated=" << count);
con.closeTransaction();
@@ -2117,7 +2614,7 @@ static int
scanupdateindex(Par par, const ITab& itab)
{
const Tab& tab = par.tab();
- for (unsigned i = 0; i < par.m_subloop; i++) {
+ for (unsigned i = 0; i < par.m_idxloop; i++) {
BSet bset(tab, itab, par.m_rows);
bset.calc(par);
CHK(scanupdateindex(par, itab, bset) == 0);
@@ -2148,41 +2645,15 @@ scanupdateall(Par par)
// medium level routines
-static bool
-ignoreverifyerror(Par par)
-{
- Con& con = par.con();
- bool b = par.m_threads > 1;
- if (b) {
- LL1("ignore verify error");
- if (con.m_tx != 0)
- con.closeTransaction();
- return true;
- }
- return b;
-}
-
static int
readverify(Par par)
{
par.m_verify = true;
- CHK(pkread(par) == 0 || ignoreverifyerror(par));
- CHK(scanreadall(par) == 0 || ignoreverifyerror(par));
+ CHK(pkread(par) == 0);
+ CHK(scanreadall(par) == 0);
return 0;
}
-static bool
-ignoredeadlock(Par par)
-{
- Con& con = par.con();
- if (con.m_errtype == Con::ErrDeadlock) {
- LL1("ignore deadlock");
- con.closeTransaction();
- return true;
- }
- return false;
-}
-
static int
pkupdatescanread(Par par)
{
@@ -2204,15 +2675,16 @@ static int
mixedoperations(Par par)
{
par.m_dups = true;
+ par.m_deadlock = true;
unsigned sel = urandom(10);
if (sel < 2) {
- CHK(pkdelete(par) == 0 || ignoredeadlock(par));
+ CHK(pkdelete(par) == 0);
} else if (sel < 4) {
- CHK(pkupdate(par) == 0 || ignoredeadlock(par));
+ CHK(pkupdate(par) == 0);
} else if (sel < 6) {
- CHK(scanupdatetable(par) == 0 || ignoredeadlock(par));
+ CHK(scanupdatetable(par) == 0);
} else {
- CHK(scanupdateindex(par) == 0 || ignoredeadlock(par));
+ CHK(scanupdateindex(par) == 0);
}
return 0;
}
@@ -2346,7 +2818,6 @@ Thr::run()
break;
}
LL4("start");
- CHK(con.bugger() == 0);
assert(m_state == Start);
m_ret = (*m_func)(m_par);
m_state = Stopped;
@@ -2426,6 +2897,7 @@ runstep(Par par, const char* fname, TFunc func, unsigned mode)
Thr& thr = *g_thrlist[n];
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_func = func;
thr.start();
}
@@ -2476,13 +2948,13 @@ tpkops(Par par)
RUNSTEP(par, pkinsert, MT);
RUNSTEP(par, createindex, ST);
RUNSTEP(par, invalidateindex, MT);
- RUNSTEP(par, readverify, MT);
+ RUNSTEP(par, readverify, ST);
for (unsigned i = 0; i < par.m_subloop; i++) {
RUNSTEP(par, pkupdatescanread, MT);
- RUNSTEP(par, readverify, MT);
+ RUNSTEP(par, readverify, ST);
}
RUNSTEP(par, pkdelete, MT);
- RUNSTEP(par, readverify, MT);
+ RUNSTEP(par, readverify, ST);
return 0;
}
@@ -2495,10 +2967,10 @@ tmixedops(Par par)
RUNSTEP(par, pkinsert, MT);
RUNSTEP(par, createindex, ST);
RUNSTEP(par, invalidateindex, MT);
- RUNSTEP(par, readverify, MT);
+ RUNSTEP(par, readverify, ST);
for (unsigned i = 0; i < par.m_subloop; i++) {
RUNSTEP(par, mixedoperations, MT);
- RUNSTEP(par, readverify, MT);
+ RUNSTEP(par, readverify, ST);
}
return 0;
}
@@ -2513,7 +2985,7 @@ tbusybuild(Par par)
for (unsigned i = 0; i < par.m_subloop; i++) {
RUNSTEP(par, pkupdateindexbuild, MT);
RUNSTEP(par, invalidateindex, MT);
- RUNSTEP(par, readverify, MT);
+ RUNSTEP(par, readverify, ST);
RUNSTEP(par, dropindex, ST);
}
return 0;
@@ -2564,6 +3036,50 @@ ttimemaint(Par par)
}
static int
+ttimescan(Par par)
+{
+ Tmr t1, t2;
+ RUNSTEP(par, droptable, ST);
+ RUNSTEP(par, createtable, ST);
+ RUNSTEP(par, invalidatetable, MT);
+ for (unsigned i = 0; i < par.m_subloop; i++) {
+ RUNSTEP(par, pkinsert, MT);
+ RUNSTEP(par, createindex, ST);
+ par.m_tmr = &t1;
+ RUNSTEP(par, timescantable, ST);
+ par.m_tmr = &t2;
+ RUNSTEP(par, timescanpkindex, ST);
+ RUNSTEP(par, dropindex, ST);
+ }
+ LL1("full scan table - " << t1.time());
+ LL1("full scan PK index - " << t2.time());
+ LL1("overhead - " << t2.over(t1));
+ return 0;
+}
+
+static int
+ttimepkread(Par par)
+{
+ Tmr t1, t2;
+ RUNSTEP(par, droptable, ST);
+ RUNSTEP(par, createtable, ST);
+ RUNSTEP(par, invalidatetable, MT);
+ for (unsigned i = 0; i < par.m_subloop; i++) {
+ RUNSTEP(par, pkinsert, MT);
+ RUNSTEP(par, createindex, ST);
+ par.m_tmr = &t1;
+ RUNSTEP(par, timepkreadtable, ST);
+ par.m_tmr = &t2;
+ RUNSTEP(par, timepkreadindex, ST);
+ RUNSTEP(par, dropindex, ST);
+ }
+ LL1("pk read table - " << t1.time());
+ LL1("pk read PK index - " << t2.time());
+ LL1("overhead - " << t2.over(t1));
+ return 0;
+}
+
+static int
tdrop(Par par)
{
RUNSTEP(par, droptable, ST);
@@ -2589,6 +3105,8 @@ tcaselist[] = {
TCase("d", 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"),
+ TCase("w", ttimepkread, "time pk read table vs index on pk"),
TCase("z", tdrop, "drop test tables")
};
@@ -2608,7 +3126,7 @@ printcases()
static void
printtables()
{
- ndbout << "tables and indexes:" << endl;
+ ndbout << "tables and indexes (X1 is on table PK):" << endl;
for (unsigned j = 0; j < tabcount; j++) {
const Tab& tab = tablist[j];
ndbout << " " << tab.m_name;
@@ -2624,7 +3142,8 @@ static int
runtest(Par par)
{
LL1("start");
- srandom(par.m_seed);
+ if (par.m_seed != 0)
+ srandom(par.m_seed);
Con con;
CHK(con.connect() == 0);
par.m_con = &con;
@@ -2639,6 +3158,8 @@ runtest(Par par)
}
for (unsigned l = 0; par.m_loop == 0 || l < par.m_loop; l++) {
LL1("loop " << l);
+ if (par.m_seed == 0)
+ srandom(l);
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)
@@ -2649,8 +3170,8 @@ runtest(Par par)
continue;
const Tab& tab = tablist[j];
par.m_tab = &tab;
- Set set(tab, par.m_totrows);
- par.m_set = &set;
+ delete par.m_set;
+ par.m_set = new Set(tab, par.m_totrows);
LL1("table " << tab.m_name);
CHK(tcase.m_func(par) == 0);
}
@@ -2680,6 +3201,12 @@ NDB_COMMAND(testOIBasic, "testOIBasic", "testOIBasic", "testOIBasic", 65535)
ndbout << "testOIBasic: unknown argument " << arg;
goto usage;
}
+ if (strcmp(arg, "-batch") == 0) {
+ if (++argv, --argc > 0) {
+ g_opt.m_batch = atoi(argv[0]);
+ continue;
+ }
+ }
if (strcmp(arg, "-case") == 0) {
if (++argv, --argc > 0) {
g_opt.m_case = strdup(argv[0]);
@@ -2736,6 +3263,12 @@ NDB_COMMAND(testOIBasic, "testOIBasic", "testOIBasic", "testOIBasic", 65535)
continue;
}
}
+ if (strcmp(arg, "-samples") == 0) {
+ if (++argv, --argc > 0) {
+ g_opt.m_samples = atoi(argv[0]);
+ continue;
+ }
+ }
if (strcmp(arg, "-scanrd") == 0) {
if (++argv, --argc > 0) {
g_opt.m_scanrd = atoi(argv[0]);
diff --git a/ndb/test/ndbapi/testRestartGci.cpp b/ndb/test/ndbapi/testRestartGci.cpp
index e3dd1f8e2ce..54d38654ff2 100644
--- a/ndb/test/ndbapi/testRestartGci.cpp
+++ b/ndb/test/ndbapi/testRestartGci.cpp
@@ -216,3 +216,5 @@ NDBT_TESTSUITE_END(testRestartGci);
int main(int argc, const char** argv){
return testRestartGci.execute(argc, argv);
}
+
+template class Vector<SavedRecord>;
diff --git a/ndb/test/ndbapi/testScan.cpp b/ndb/test/ndbapi/testScan.cpp
index bc3be0b7dc9..3d8b37df0ca 100644
--- a/ndb/test/ndbapi/testScan.cpp
+++ b/ndb/test/ndbapi/testScan.cpp
@@ -65,7 +65,7 @@ int runDropAllTablesExceptTestTable(NDBT_Context* ctx, NDBT_Step* step){
}
int res = GETNDB(step)->getDictionary()->dropTable(tab->getName());
- if(res != -1){
+ if(res == -1){
return NDBT_FAILED;
}
}
@@ -776,108 +776,19 @@ int runOnlyOpenScanOnce(NDBT_Context* ctx, NDBT_Step* step){
}
int runOnlyOneOpInScanTrans(NDBT_Context* ctx, NDBT_Step* step){
- const NdbDictionary::Table* pTab = ctx->getTab();
- int records = ctx->getNumRecords();
- int numFailed = 0;
-
- ScanFunctions scanF(*pTab);
- if (scanF.scanReadFunctions(GETNDB(step),
- records,
- 6,
- ScanFunctions::OnlyOneOpInScanTrans,
- false) == 0){
- numFailed++;
- }
- if (scanF.scanReadFunctions(GETNDB(step),
- records,
- 6,
- ScanFunctions::OnlyOneOpInScanTrans,
- true) == 0){
- numFailed++;
- }
-
-
- if(numFailed > 0)
- return NDBT_FAILED;
- else
- return NDBT_OK;
-
+ return NDBT_OK;
}
int runExecuteScanWithoutOpenScan(NDBT_Context* ctx, NDBT_Step* step){
- const NdbDictionary::Table* pTab = ctx->getTab();
- int records = ctx->getNumRecords();
- int numFailed = 0;
- ScanFunctions scanF(*pTab);
- if (scanF.scanReadFunctions(GETNDB(step),
- records,
- 1,
- ScanFunctions::ExecuteScanWithOutOpenScan,
- false) == 0){
- numFailed++;
- }
-
- if(numFailed > 0)
- return NDBT_FAILED;
- else
- return NDBT_OK;
+ return NDBT_OK;
}
-
-
int runOnlyOneOpBeforeOpenScan(NDBT_Context* ctx, NDBT_Step* step){
- const NdbDictionary::Table* pTab = ctx->getTab();
- int records = ctx->getNumRecords();
- int numFailed = 0;
-
- ScanFunctions scanF(*pTab);
- if (scanF.scanReadFunctions(GETNDB(step),
- records,
- 6,
- ScanFunctions::OnlyOneOpBeforeOpenScan,
- false) == 0){
- numFailed++;
- }
- if (scanF.scanReadFunctions(GETNDB(step),
- records,
- 6,
- ScanFunctions::OnlyOneOpBeforeOpenScan,
- true) == 0){
- numFailed++;
- }
-
- if(numFailed > 0)
- return NDBT_FAILED;
- else
return NDBT_OK;
-
}
-int runOnlyOneScanPerTrans(NDBT_Context* ctx, NDBT_Step* step){
- const NdbDictionary::Table* pTab = ctx->getTab();
- int records = ctx->getNumRecords();
- int numFailed = 0;
-
- ScanFunctions scanF(*pTab);
- if (scanF.scanReadFunctions(GETNDB(step),
- records,
- 6,
- ScanFunctions::OnlyOneScanPerTrans,
- false) == 0){
- numFailed++;
- }
- if (scanF.scanReadFunctions(GETNDB(step),
- records,
- 6,
- ScanFunctions::OnlyOneScanPerTrans,
- true) == 0){
- numFailed++;
- }
-
- if(numFailed > 0)
- return NDBT_FAILED;
- else
- return NDBT_OK;
+int runOnlyOneScanPerTrans(NDBT_Context* ctx, NDBT_Step* step){
+ return NDBT_OK;
}
int runNoCloseTransaction(NDBT_Context* ctx, NDBT_Step* step){
@@ -970,6 +881,93 @@ int runCheckInactivityBeforeClose(NDBT_Context* ctx, NDBT_Step* step){
}
+int runScanRestart(NDBT_Context* ctx, NDBT_Step* step){
+ int loops = ctx->getNumLoops();
+ int records = ctx->getNumRecords();
+ Ndb * pNdb = GETNDB(step);
+ const NdbDictionary::Table* pTab = ctx->getTab();
+
+ HugoCalculator calc(* pTab);
+ NDBT_ResultRow tmpRow(* pTab);
+
+ int i = 0;
+ while (i<loops && !ctx->isTestStopped()) {
+ g_info << i++ << ": ";
+ const int record = (rand() % records);
+ g_info << " row=" << record;
+
+ NdbConnection* pCon = pNdb->startTransaction();
+ NdbScanOperation* pOp = pCon->getNdbScanOperation(pTab->getName());
+ if (pOp == NULL) {
+ ERR(pCon->getNdbError());
+ return NDBT_FAILED;
+ }
+
+ NdbResultSet* rs = pOp->readTuples();
+ if( rs == 0 ) {
+ ERR(pCon->getNdbError());
+ return NDBT_FAILED;
+ }
+
+ int check = pOp->interpret_exit_ok();
+ if( check == -1 ) {
+ ERR(pCon->getNdbError());
+ return NDBT_FAILED;
+ }
+
+ // Define attributes to read
+ for(int a = 0; a<pTab->getNoOfColumns(); a++){
+ if((tmpRow.attributeStore(a) =
+ pOp->getValue(pTab->getColumn(a)->getName())) == 0) {
+ ERR(pCon->getNdbError());
+ return NDBT_FAILED;
+ }
+ }
+
+ check = pCon->execute(NoCommit);
+ if( check == -1 ) {
+ ERR(pCon->getNdbError());
+ return NDBT_FAILED;
+ }
+
+ int res;
+ int row = 0;
+ while(row < record && (res = rs->nextResult()) == 0) {
+ if(calc.verifyRowValues(&tmpRow) != 0){
+ abort();
+ return NDBT_FAILED;
+ }
+ row++;
+ }
+ if(row != record){
+ ERR(pCon->getNdbError());
+ abort();
+ return NDBT_FAILED;
+ }
+ g_info << " restarting" << endl;
+ if((res = rs->restart()) != 0){
+ ERR(pCon->getNdbError());
+ abort();
+ return NDBT_FAILED;
+ }
+
+ row = 0;
+ while((res = rs->nextResult()) == 0) {
+ if(calc.verifyRowValues(&tmpRow) != 0){
+ abort();
+ return NDBT_FAILED;
+ }
+ row++;
+ }
+ if(res != 1 || row != records){
+ ERR(pCon->getNdbError());
+ abort();
+ return NDBT_FAILED;
+ }
+ pCon->close();
+ }
+ return NDBT_OK;
+}
NDBT_TESTSUITE(testScan);
@@ -1393,6 +1391,12 @@ TESTCASE("ScanReadWhileNodeIsDown",
STEP(runStopAndStartNode);
FINALIZER(runClearTable);
}
+TESTCASE("ScanRestart",
+ "Verify restart functionallity"){
+ INITIALIZER(runLoadTable);
+ STEP(runScanRestart);
+ FINALIZER(runClearTable);
+}
NDBT_TESTSUITE_END(testScan);
int main(int argc, const char** argv){
@@ -1400,3 +1404,4 @@ int main(int argc, const char** argv){
return testScan.execute(argc, argv);
}
+template class Vector<Attrib*>;
diff --git a/ndb/test/ndbapi/testScanPerf/testScanPerf.cpp b/ndb/test/ndbapi/testScanPerf.cpp
index 61af1ffb989..61af1ffb989 100644
--- a/ndb/test/ndbapi/testScanPerf/testScanPerf.cpp
+++ b/ndb/test/ndbapi/testScanPerf.cpp
diff --git a/ndb/test/ndbapi/testScanPerf/Makefile b/ndb/test/ndbapi/testScanPerf/Makefile
deleted file mode 100644
index fdf5980b385..00000000000
--- a/ndb/test/ndbapi/testScanPerf/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
-include .defs.mk
-
-TYPE = ndbapitest
-
-BIN_TARGET = testScanPerf
-
-SOURCES = testScanPerf.cpp
-
-include $(NDB_TOP)/Epilogue.mk
diff --git a/ndb/test/ndbapi/testTimeout.cpp b/ndb/test/ndbapi/testTimeout.cpp
index 8a7866880b3..62e69125073 100644
--- a/ndb/test/ndbapi/testTimeout.cpp
+++ b/ndb/test/ndbapi/testTimeout.cpp
@@ -20,6 +20,44 @@
#include <UtilTransactions.hpp>
#include <random.h>
#include <NdbConfig.hpp>
+#include <signaldata/DumpStateOrd.hpp>
+
+#define TIMEOUT 3000
+
+Uint32 g_org_timeout = 3000;
+
+int
+setTransactionTimeout(NDBT_Context* ctx, NDBT_Step* step){
+ NdbRestarter restarter;
+
+ NdbConfig conf(GETNDB(step)->getNodeId()+1);
+ unsigned int nodeId = conf.getMasterNodeId();
+ if (!conf.getProperty(nodeId,
+ NODE_TYPE_DB,
+ CFG_DB_TRANSACTION_INACTIVE_TIMEOUT,
+ &g_org_timeout)){
+ return NDBT_FAILED;
+ }
+
+ int val[] = { DumpStateOrd::TcSetApplTransactionTimeout, TIMEOUT };
+ if(restarter.dumpStateAllNodes(val, 2) != 0){
+ return NDBT_FAILED;
+ }
+
+ return NDBT_OK;
+}
+
+int
+resetTransactionTimeout(NDBT_Context* ctx, NDBT_Step* step){
+ NdbRestarter restarter;
+
+ int val[] = { DumpStateOrd::TcSetApplTransactionTimeout, g_org_timeout };
+ if(restarter.dumpStateAllNodes(val, 2) != 0){
+ return NDBT_FAILED;
+ }
+
+ return NDBT_OK;
+}
int runLoadTable(NDBT_Context* ctx, NDBT_Step* step){
@@ -55,16 +93,10 @@ int runTimeoutTrans(NDBT_Context* ctx, NDBT_Step* step){
NdbConfig conf(GETNDB(step)->getNodeId()+1);
unsigned int nodeId = conf.getMasterNodeId();
int stepNo = step->getStepNo();
- Uint32 timeoutVal;
- if (!conf.getProperty(nodeId,
- NODE_TYPE_DB,
- CFG_DB_TRANSACTION_INACTIVE_TIMEOUT,
- &timeoutVal)){
- return NDBT_FAILED;
- }
- int minSleep = (int)(timeoutVal * 1.5);
- int maxSleep = timeoutVal * 2;
- ndbout << "TransactionInactiveTimeout="<<timeoutVal
+
+ int minSleep = (int)(TIMEOUT * 1.5);
+ int maxSleep = TIMEOUT * 2;
+ ndbout << "TransactionInactiveTimeout="<< TIMEOUT
<< ", minSleep="<<minSleep
<< ", maxSleep="<<maxSleep<<endl;
@@ -89,7 +121,125 @@ int runTimeoutTrans(NDBT_Context* ctx, NDBT_Step* step){
} while(false);
hugoOps.closeTransaction(pNdb);
+ }
+
+ return result;
+}
+
+int runTimeoutTrans2(NDBT_Context* ctx, NDBT_Step* step){
+ int result = NDBT_OK;
+ int loops = ctx->getNumLoops();
+ int stepNo = step->getStepNo();
+ int mul1 = ctx->getProperty("Op1", (Uint32)0);
+ int mul2 = ctx->getProperty("Op2", (Uint32)0);
+ int records = ctx->getNumRecords();
+
+ int minSleep = (int)(TIMEOUT * 1.5);
+ int maxSleep = TIMEOUT * 2;
+ HugoOperations hugoOps(*ctx->getTab());
+ Ndb* pNdb = GETNDB(step);
+
+ for (int l = 0; l<loops && !ctx->isTestStopped() && result == NDBT_OK; l++){
+
+ int op1 = 0 + (l + stepNo) * mul1;
+ int op2 = 0 + (l + stepNo) * mul2;
+
+ op1 = (op1 % 5);
+ op2 = (op2 % 5);
+
+ ndbout << stepNo << ": TransactionInactiveTimeout="<< TIMEOUT
+ << ", minSleep="<<minSleep
+ << ", maxSleep="<<maxSleep
+ << ", op1=" << op1
+ << ", op2=" << op2 << endl;;
+
+ do{
+ // Commit transaction
+ CHECK(hugoOps.startTransaction(pNdb) == 0);
+
+ switch(op1){
+ case 0:
+ break;
+ case 1:
+ if(hugoOps.pkReadRecord(pNdb, stepNo, true) != 0){
+ g_err << stepNo << ": Fail" << __LINE__ << endl;
+ result = NDBT_FAILED; break;
+ }
+ break;
+ case 2:
+ if(hugoOps.pkUpdateRecord(pNdb, stepNo, true) != 0){
+ g_err << stepNo << ": Fail" << __LINE__ << endl;
+ result = NDBT_FAILED; break;
+ }
+ break;
+ case 3:
+ if(hugoOps.pkDeleteRecord(pNdb, stepNo, true) != 0){
+ g_err << stepNo << ": Fail" << __LINE__ << endl;
+ result = NDBT_FAILED; break;
+ }
+ break;
+ case 4:
+ if(hugoOps.pkInsertRecord(pNdb, stepNo+records+l, true) != 0){
+ g_err << stepNo << ": Fail" << __LINE__ << endl;
+ result = NDBT_FAILED; break;
+ }
+ break;
+ }
+
+ if(result != NDBT_OK)
+ break;
+
+ int res = hugoOps.execute_NoCommit(pNdb);
+ if(res != 0){
+ g_err << stepNo << ": Fail" << __LINE__ << endl;
+ result = NDBT_FAILED; break;
+ }
+
+ int sleep = minSleep + myRandom48(maxSleep-minSleep);
+ ndbout << stepNo << ": Sleeping for "<< sleep << " milliseconds" << endl;
+ NdbSleep_MilliSleep(sleep);
+
+ switch(op2){
+ case 0:
+ break;
+ case 1:
+ if(hugoOps.pkReadRecord(pNdb, stepNo, true) != 0){
+ g_err << stepNo << ": Fail" << __LINE__ << endl;
+ result = NDBT_FAILED; break;
+ }
+ break;
+ case 2:
+ if(hugoOps.pkUpdateRecord(pNdb, stepNo, true) != 0){
+ g_err << stepNo << ": Fail" << __LINE__ << endl;
+ result = NDBT_FAILED; break;
+ }
+ break;
+ case 3:
+ if(hugoOps.pkDeleteRecord(pNdb, stepNo, true) != 0){
+ g_err << stepNo << ": Fail" << __LINE__ << endl;
+ result = NDBT_FAILED; break;
+ }
+ break;
+ case 4:
+ if(hugoOps.pkInsertRecord(pNdb, stepNo+2*records+l, true) != 0){
+ g_err << stepNo << ": Fail" << __LINE__ << endl;
+ result = NDBT_FAILED; break;
+ }
+ break;
+ }
+
+ // Expect that transaction has timed-out
+ res = hugoOps.execute_Commit(pNdb);
+ if(op1 != 0 && res != 266){
+ g_err << stepNo << ": Fail: " << res << "!= 237, op1="
+ << op1 << ", op2=" << op2 << endl;
+ result = NDBT_FAILED; break;
+ }
+
+ } while(false);
+
+ hugoOps.closeTransaction(pNdb);
}
return result;
@@ -98,18 +248,10 @@ int runTimeoutTrans(NDBT_Context* ctx, NDBT_Step* step){
int runDontTimeoutTrans(NDBT_Context* ctx, NDBT_Step* step){
int result = NDBT_OK;
int loops = ctx->getNumLoops();
- NdbConfig conf(GETNDB(step)->getNodeId()+1);
- unsigned int nodeId = conf.getMasterNodeId();
int stepNo = step->getStepNo();
- Uint32 timeoutVal;
- if (!conf.getProperty(nodeId,
- NODE_TYPE_DB,
- CFG_DB_TRANSACTION_INACTIVE_TIMEOUT,
- &timeoutVal)){
- return NDBT_FAILED;
- }
- int maxSleep = (int)(timeoutVal * 0.5);
- ndbout << "TransactionInactiveTimeout="<<timeoutVal
+
+ int maxSleep = (int)(TIMEOUT * 0.5);
+ ndbout << "TransactionInactiveTimeout="<< TIMEOUT
<< ", maxSleep="<<maxSleep<<endl;
@@ -134,11 +276,8 @@ int runDontTimeoutTrans(NDBT_Context* ctx, NDBT_Step* step){
} while(false);
hugoOps.closeTransaction(pNdb);
-
-
}
-
return result;
}
@@ -146,18 +285,9 @@ int runBuddyTransNoTimeout(NDBT_Context* ctx, NDBT_Step* step){
int result = NDBT_OK;
int loops = ctx->getNumLoops();
int records = ctx->getNumRecords();
- NdbConfig conf(GETNDB(step)->getNodeId()+1);
- unsigned int nodeId = conf.getMasterNodeId();
int stepNo = step->getStepNo();
- Uint32 timeoutVal;
- if (!conf.getProperty(nodeId,
- NODE_TYPE_DB,
- CFG_DB_TRANSACTION_INACTIVE_TIMEOUT,
- &timeoutVal)){
- return NDBT_FAILED;
- }
- int maxSleep = (int)(timeoutVal * 0.3);
- ndbout << "TransactionInactiveTimeout="<<timeoutVal
+ int maxSleep = (int)(TIMEOUT * 0.3);
+ ndbout << "TransactionInactiveTimeout="<< TIMEOUT
<< ", maxSleep="<<maxSleep<<endl;
HugoOperations hugoOps(*ctx->getTab());
@@ -172,11 +302,11 @@ int runBuddyTransNoTimeout(NDBT_Context* ctx, NDBT_Step* step){
CHECK(hugoOps.pkInsertRecord(pNdb, recordNo, true) == 0);
CHECK(hugoOps.execute_NoCommit(pNdb) == 0);
- for (int i = 0; i < 10; i++){
+ for (int i = 0; i < 3; i++){
// Perform buddy scan reads
- CHECK(hugoOps.scanReadRecords(pNdb) == 0);
- CHECK(hugoOps.executeScanRead(pNdb) == 0);
-
+ CHECK((hugoOps.scanReadRecords(pNdb)) == 0);
+ CHECK(hugoOps.execute_NoCommit(pNdb) == 0);
+
int sleep = myRandom48(maxSleep);
ndbout << "Sleeping for " << sleep << " milliseconds" << endl;
NdbSleep_MilliSleep(sleep);
@@ -188,10 +318,7 @@ int runBuddyTransNoTimeout(NDBT_Context* ctx, NDBT_Step* step){
} while(false);
hugoOps.closeTransaction(pNdb);
-
-
}
-
return result;
}
@@ -202,7 +329,9 @@ TESTCASE("DontTimeoutTransaction",
"if we sleep during the transaction. Use a sleep "\
"value which is smaller than TransactionInactiveTimeout"){
INITIALIZER(runLoadTable);
+ INITIALIZER(setTransactionTimeout);
STEPS(runDontTimeoutTrans, 1);
+ FINALIZER(resetTransactionTimeout);
FINALIZER(runClearTable);
}
TESTCASE("DontTimeoutTransaction5",
@@ -211,7 +340,9 @@ TESTCASE("DontTimeoutTransaction5",
"value which is smaller than TransactionInactiveTimeout" \
"Five simultaneous threads"){
INITIALIZER(runLoadTable);
+ INITIALIZER(setTransactionTimeout);
STEPS(runDontTimeoutTrans, 5);
+ FINALIZER(resetTransactionTimeout);
FINALIZER(runClearTable);
}
TESTCASE("TimeoutTransaction",
@@ -219,7 +350,9 @@ TESTCASE("TimeoutTransaction",
"if we sleep during the transaction. Use a sleep "\
"value which is larger than TransactionInactiveTimeout"){
INITIALIZER(runLoadTable);
+ INITIALIZER(setTransactionTimeout);
STEPS(runTimeoutTrans, 1);
+ FINALIZER(resetTransactionTimeout);
FINALIZER(runClearTable);
}
TESTCASE("TimeoutTransaction5",
@@ -228,7 +361,21 @@ TESTCASE("TimeoutTransaction5",
"value which is larger than TransactionInactiveTimeout" \
"Five simultaneous threads"){
INITIALIZER(runLoadTable);
+ INITIALIZER(setTransactionTimeout);
STEPS(runTimeoutTrans, 5);
+ FINALIZER(resetTransactionTimeout);
+ FINALIZER(runClearTable);
+}
+TESTCASE("TimeoutRandTransaction",
+ "Test that the transaction does timeout "\
+ "if we sleep during the transaction. Use a sleep "\
+ "value which is larger than TransactionInactiveTimeout"){
+ INITIALIZER(runLoadTable);
+ INITIALIZER(setTransactionTimeout);
+ TC_PROPERTY("Op1", 7);
+ TC_PROPERTY("Op2", 11);
+ STEPS(runTimeoutTrans2, 5);
+ FINALIZER(resetTransactionTimeout);
FINALIZER(runClearTable);
}
TESTCASE("BuddyTransNoTimeout",
@@ -238,7 +385,9 @@ TESTCASE("BuddyTransNoTimeout",
"The total sleep time is longer than TransactionInactiveTimeout" \
"Commit the first transaction, it should not have timed out."){
INITIALIZER(runLoadTable);
+ INITIALIZER(setTransactionTimeout);
STEPS(runBuddyTransNoTimeout, 1);
+ FINALIZER(resetTransactionTimeout);
FINALIZER(runClearTable);
}
TESTCASE("BuddyTransNoTimeout5",
@@ -249,7 +398,9 @@ TESTCASE("BuddyTransNoTimeout5",
"Commit the first transaction, it should not have timed out." \
"Five simultaneous threads"){
INITIALIZER(runLoadTable);
+ INITIALIZER(setTransactionTimeout);
STEPS(runBuddyTransNoTimeout, 5);
+ FINALIZER(resetTransactionTimeout);
FINALIZER(runClearTable);
}
NDBT_TESTSUITE_END(testTimeout);
diff --git a/ndb/test/ndbapi/testTransactions.cpp b/ndb/test/ndbapi/testTransactions.cpp
index 9ce928f8736..67a2df24390 100644
--- a/ndb/test/ndbapi/testTransactions.cpp
+++ b/ndb/test/ndbapi/testTransactions.cpp
@@ -102,7 +102,7 @@ OperationTestCase matrix[] = {
{ "ScanExInsert", true, "SCAN-EX",1, "INSERT", 266, X, 0, 1 },
{ "ScanExUpdate", true, "SCAN-EX",1, "UPDATE", 266, 2, 0, 1 },
{ "ScanExDelete", true, "SCAN-EX",1, "DELETE", 266, X, 0, 1 },
- { "ScanExScan", true, "SCAN-EX",1, "SCAN", 274, X, 0, 1 },
+ { "ScanExScan", true, "SCAN-EX",1, "SCAN", 0, 1, 0, 1 },
{ "ScanExScanHl", true, "SCAN-EX",1, "SCAN-HL", 274, X, 0, 1 },
{ "ScanExScanEx", true, "SCAN-EX",1, "SCAN-EX", 274, X, 0, 1 },
#if 0
@@ -117,8 +117,8 @@ OperationTestCase matrix[] = {
{ "ReadExInsert", true, "READ-EX",1, "INSERT", 266, X, 0, 1 },
{ "ReadExUpdate", true, "READ-EX",1, "UPDATE", 266, X, 0, 1 },
{ "ReadExDelete", true, "READ-EX",1, "DELETE", 266, X, 0, 1 },
- { "ReadExScan", true, "READ-EX",1, "SCAN", 274, 1, 0, 1 },
- { "ReadExScanHl", true, "READ-EX",1, "SCAN-HL", 274, 1, 0, 1 },
+ { "ReadExScan", true, "READ-EX",1, "SCAN", 0, 1, 0, 1 },
+ { "ReadExScanHl", true, "READ-EX",1, "SCAN-HL", 274, X, 0, 1 },
{ "ReadExScanEx", true, "READ-EX",1, "SCAN-EX", 274, X, 0, 1 },
#if 0
{ "ReadExScanUp", true, "READ-EX",1, "SCAN-UP", 266, X, 0, 1 },
@@ -132,7 +132,7 @@ OperationTestCase matrix[] = {
{ "InsertInsert", false, "INSERT", 1, "INSERT", 266, X, 0, 1 },
{ "InsertUpdate", false, "INSERT", 1, "UPDATE", 266, X, 0, 1 },
{ "InsertDelete", false, "INSERT", 1, "DELETE", 266, X, 0, 1 },
- { "InsertScan", false, "INSERT", 1, "SCAN", 274, X, 0, 1 },
+ { "InsertScan", false, "INSERT", 1, "SCAN", 626, X, 0, 1 },
{ "InsertScanHl", false, "INSERT", 1, "SCAN-HL", 274, X, 0, 1 },
{ "InsertScanEx", false, "INSERT", 1, "SCAN-EX", 274, X, 0, 1 },
#if 0
@@ -147,7 +147,7 @@ OperationTestCase matrix[] = {
{ "UpdateInsert", true, "UPDATE", 2, "INSERT", 266, X, 0, 2 },
{ "UpdateUpdate", true, "UPDATE", 2, "UPDATE", 266, X, 0, 2 },
{ "UpdateDelete", true, "UPDATE", 2, "DELETE", 266, X, 0, 2 },
- { "UpdateScan", true, "UPDATE", 2, "SCAN", 274, X, 0, 2 },
+ { "UpdateScan", true, "UPDATE", 2, "SCAN", 0, 1, 0, 2 },
{ "UpdateScanHl", true, "UPDATE", 2, "SCAN-HL", 274, X, 0, 2 },
{ "UpdateScanEx", true, "UPDATE", 2, "SCAN-EX", 274, X, 0, 2 },
#if 0
@@ -162,7 +162,7 @@ OperationTestCase matrix[] = {
{ "DeleteInsert", true, "DELETE", X, "INSERT", 266, X, 626, X },
{ "DeleteUpdate", true, "DELETE", X, "UPDATE", 266, X, 626, X },
{ "DeleteDelete", true, "DELETE", X, "DELETE", 266, X, 626, X },
- { "DeleteScan", true, "DELETE", X, "SCAN", 274, X, 626, X },
+ { "DeleteScan", true, "DELETE", X, "SCAN", 0, 1, 626, X },
{ "DeleteScanHl", true, "DELETE", X, "SCAN-HL", 274, X, 626, X },
{ "DeleteScanEx", true, "DELETE", X, "SCAN-EX", 274, X, 626, X },
#if 0
@@ -206,9 +206,9 @@ runOp(HugoOperations & hugoOps,
} else if(strcmp(op, "SCAN") == 0){
C2(hugoOps.scanReadRecords(pNdb) == 0);
} else if(strcmp(op, "SCAN-HL") == 0){
- C2(hugoOps.scanReadRecords(pNdb, 240, HugoOperations::SL_ReadHold) == 0);
+ C2(hugoOps.scanReadRecords(pNdb, NdbScanOperation::LM_Read)== 0);
} else if(strcmp(op, "SCAN-EX") == 0){
- C2(hugoOps.scanReadRecords(pNdb, 240, HugoOperations::SL_Exclusive) == 0);
+ C2(hugoOps.scanReadRecords(pNdb, NdbScanOperation::LM_Exclusive)== 0);
} else {
g_err << __FILE__ << " - " << __LINE__
<< ": Unknown operation" << op << endl;
diff --git a/ndb/test/run-test/Makefile.am b/ndb/test/run-test/Makefile.am
index 3dd9632ce4b..04be35325db 100644
--- a/ndb/test/run-test/Makefile.am
+++ b/ndb/test/run-test/Makefile.am
@@ -1,18 +1,18 @@
-ndbtest_PROGRAMS = atrt
+testdir=$(prefix)/mysql-test/ndb
-atrt_SOURCES = main.cpp
+include $(top_srcdir)/ndb/config/common.mk.am
+include $(top_srcdir)/ndb/config/type_util.mk.am
+include $(top_srcdir)/ndb/config/type_mgmapiclient.mk.am
-ndbtest_SCRIPTS = atrt-analyze-result.sh atrt-gather-result.sh atrt-setup.sh \
+test_PROGRAMS = atrt
+test_DATA=daily-basic-tests.txt daily-devel-tests.txt
+test_SCRIPTS=atrt-analyze-result.sh atrt-gather-result.sh atrt-setup.sh \
atrt-clear-result.sh make-config.sh make-index.sh make-html-reports.sh
-EXTRA_DIST = $(ndbtest_SCRIPTS)
+atrt_SOURCES = main.cpp
INCLUDES_LOC = -I$(top_srcdir)/ndb/src/mgmclient
LDADD_LOC = $(top_builddir)/ndb/src/mgmclient/CpcClient.o $(top_builddir)/ndb/src/libndbclient.la
-include $(top_srcdir)/ndb/config/common.mk.am
-include $(top_srcdir)/ndb/config/type_util.mk.am
-include $(top_srcdir)/ndb/config/type_mgmapiclient.mk.am
-
# Don't update the files from bitkeeper
%::SCCS/s.%
diff --git a/ndb/test/run-test/daily-basic-tests.txt b/ndb/test/run-test/daily-basic-tests.txt
new file mode 100644
index 00000000000..631378cb636
--- /dev/null
+++ b/ndb/test/run-test/daily-basic-tests.txt
@@ -0,0 +1,1008 @@
+# BASIC FUNCTIONALITY
+max-time: 500
+cmd: testBasic
+args: -n PkRead
+
+max-time: 500
+cmd: testBasic
+args: -n PkUpdate
+
+max-time: 500
+cmd: testBasic
+args: -n PkDelete
+
+max-time: 500
+cmd: testBasic
+args: -n PkInsert
+
+max-time: 600
+cmd: testBasic
+args: -n UpdateAndRead
+
+max-time: 500
+cmd: testBasic
+args: -n PkReadAndLocker T6
+
+max-time: 500
+cmd: testBasic
+args: -n PkReadAndLocker2 T6
+
+max-time: 500
+cmd: testBasic
+args: -n PkReadUpdateAndLocker T6
+
+max-time: 500
+cmd: testBasic
+args: -n ReadWithLocksAndInserts T6
+
+max-time: 500
+cmd: testBasic
+args: -n PkInsertTwice T1 T6 T10
+
+max-time: 1500
+cmd: testBasic
+args: -n Fill T13
+
+max-time: 1500
+cmd: testBasic
+args: -n Fill T6
+
+max-time: 500
+cmd: testBasic
+args: -n NoCommitSleep T6
+
+max-time: 500
+cmd: testBasic
+args: -n NoCommit626 T6
+
+max-time: 500
+cmd: testBasic
+args: -n NoCommitAndClose T6
+
+max-time: 500
+cmd: testBasic
+args: -n Commit626 T6
+
+max-time: 500
+cmd: testBasic
+args: -n CommitTry626 T6
+
+max-time: 500
+cmd: testBasic
+args: -n CommitAsMuch626 T6
+
+max-time: 500
+cmd: testBasic
+args: -n NoCommit626 T6
+
+max-time: 500
+cmd: testBasic
+args: -n NoCommitRollback626 T1 T6
+
+max-time: 500
+cmd: testBasic
+args: -n Commit630 T1 T6
+
+max-time: 500
+cmd: testBasic
+args: -n CommitTry630 T1 T6
+
+max-time: 500
+cmd: testBasic
+args: -n CommitAsMuch630 T1 T6
+
+max-time: 500
+cmd: testBasic
+args: -n NoCommit630 T1 T6
+
+max-time: 500
+cmd: testBasic
+args: -n NoCommitRollback630 T1 T6
+
+max-time: 500
+cmd: testBasic
+args: -n NoCommitAndClose T1 T6
+
+max-time: 500
+cmd: testBasic
+args: -n RollbackUpdate T1 T6
+
+max-time: 500
+cmd: testBasic
+args: -n RollbackDeleteMultiple T1 T6
+
+max-time: 500
+cmd: testBasic
+args: -n ImplicitRollbackDelete T1 T6
+
+max-time: 500
+cmd: testBasic
+args: -n CommitDelete T1 T6
+
+max-time: 500
+cmd: testBasic
+args: -n RollbackNothing T1 T6
+
+max-time: 500
+cmd: testBasicAsynch
+args: -n PkInsertAsynch
+
+max-time: 500
+cmd: testBasicAsynch
+args: -n PkReadAsynch
+
+max-time: 500
+cmd: testBasicAsynch
+args: -n PkUpdateAsynch
+
+max-time: 500
+cmd: testBasicAsynch
+args: -n PkDeleteAsynch
+
+max-time: 500
+cmd: testBasic
+args: -n MassiveRollback T1 T6 T13
+
+max-time: 500
+cmd: testBasic
+args: -n MassiveRollback2 T1 T6 T13
+
+#-m 500 1: testBasic -n ReadConsistency T6
+max-time: 500
+cmd: testTimeout
+args: -n DontTimeoutTransaction T1
+
+max-time: 500
+cmd: testTimeout
+args: -n DontTimeoutTransaction5 T1
+
+max-time: 500
+cmd: testTimeout
+args: -n TimeoutTransaction T1
+
+max-time: 500
+cmd: testTimeout
+args: -n TimeoutTransaction5 T1
+
+max-time: 500
+cmd: testTimeout
+args: -n BuddyTransNoTimeout T1
+
+max-time: 500
+cmd: testTimeout
+args: -n BuddyTransNoTimeout5 T1
+
+max-time: 500
+cmd: testTimeout
+args: -n TimeoutRandTransaction T1
+
+# SCAN TESTS
+#
+max-time: 500
+cmd: testScan
+args: -n ScanRead16
+
+max-time: 500
+cmd: testScan
+args: -n ScanRead240
+
+max-time: 500
+cmd: testScan
+args: -n ScanReadCommitted240
+
+max-time: 500
+cmd: testScan
+args: -n ScanUpdate
+
+max-time: 500
+cmd: testScan
+args: -n ScanUpdate2 T6
+
+max-time: 500
+cmd: testScan
+args: -n ScanDelete
+
+max-time: 500
+cmd: testScan
+args: -n ScanDelete2 T10
+
+max-time: 500
+cmd: testScan
+args: -n ScanUpdateAndScanRead T6
+
+max-time: 500
+cmd: testScan
+args: -n ScanReadAndLocker T6
+
+max-time: 500
+cmd: testScan
+args: -n ScanReadAndPkRead T6
+
+max-time: 500
+cmd: testScan
+args: -n ScanRead488 -l 10 T6
+
+max-time: 600
+cmd: testScan
+args: -n ScanRead40 -l 100 T2
+
+max-time: 1800
+cmd: testScan
+args: -n ScanRead100 -l 100 T1
+
+max-time: 600
+cmd: testScan
+args: -n ScanRead40 -l 100 T1
+
+max-time: 1800
+cmd: testScan
+args: -n ScanRead40RandomTable -l 100 T1
+
+max-time: 3600
+cmd: testScan
+args: -n ScanRead40RandomTable -l 1000 T2
+
+max-time: 500
+cmd: testScan
+args: -n ScanWithLocksAndInserts T6
+
+max-time: 500
+cmd: testScan
+args: -n ScanReadAbort T6
+
+max-time: 500
+cmd: testScan
+args: -n ScanReadAbort15 T6
+
+max-time: 500
+cmd: testScan
+args: -n ScanReadAbort240 T6
+
+max-time: 500
+cmd: testScan
+args: -n ScanUpdateAbort16 T6
+
+max-time: 3600
+cmd: testScan
+args: -n ScanReadRestart T1 T6 T13
+
+max-time: 500
+cmd: testScan
+args: -n ScanUpdateRestart T6
+
+max-time: 500
+cmd: testScan
+args: -n CheckGetValue T6
+
+max-time: 500
+cmd: testScan
+args: -n CloseWithoutStop T6
+
+max-time: 500
+cmd: testScan
+args: -n NextScanWhenNoMore T6
+
+max-time: 500
+cmd: testScan
+args: -n ExecuteScanWithoutOpenScan T6
+
+max-time: 500
+cmd: testScan
+args: -n OnlyOpenScanOnce T6
+
+max-time: 500
+cmd: testScan
+args: -n OnlyOneOpInScanTrans T6
+
+max-time: 500
+cmd: testScan
+args: -n OnlyOneOpBeforeOpenScan T6
+
+max-time: 500
+cmd: testScan
+args: -n OnlyOneScanPerTrans T6
+
+max-time: 500
+cmd: testScan
+args: -n NoCloseTransaction T6
+
+max-time: 500
+cmd: testScan
+args: -n CheckInactivityTimeOut T6
+
+max-time: 500
+cmd: testScan
+args: -n CheckInactivityBeforeClose T6
+
+max-time: 500
+cmd: testScan
+args: -n CheckAfterTerror T6
+
+max-time: 500
+cmd: testScan
+args: -n ScanReadError5021 T1
+
+max-time: 500
+cmd: testScan
+args: -n ScanReaderror5022 T1
+
+max-time: 500
+cmd: testScan
+args: -n ScanReadError5023 T1
+
+max-time: 500
+cmd: testScan
+args: -n ScanReadError5024 T1
+
+max-time: 500
+cmd: testScan
+args: -n ScanReadError5025 T1
+
+max-time: 500
+cmd: testScan
+args: -n ScanReadError5030 T1
+
+max-time: 500
+cmd: testScan
+args: -n InsertDelete T1 T6
+
+max-time: 500
+cmd: testScan
+args: -n CheckAfterTerror T1
+
+max-time: 500
+cmd: testScan
+args: -n ScanReadWhileNodeIsDown T1
+
+max-time: 500
+cmd: testScan
+args: -n ScanRestart T1
+
+# OLD FLEX
+max-time: 500
+cmd: flexBench
+args: -c 25 -t 10
+
+max-time: 500
+cmd: flexHammer
+args: -r 5 -t 32
+
+#
+# DICT TESTS
+max-time: 1500
+cmd: testDict
+args: -n CreateAndDrop
+
+max-time: 1500
+cmd: testDict
+args: -n CreateAndDropWithData
+
+max-time: 1500
+cmd: testDict
+args: -n CreateAndDropDuring T6 T10
+
+max-time: 1500
+cmd: testDict
+args: -n CreateInvalidTables
+
+max-time: 1500
+cmd: testDict
+args: -n CreateTableWhenDbIsFull T6
+
+max-time: 1500
+cmd: testDict
+args: -n CreateMaxTables T6
+
+max-time: 500
+cmd: testDict
+args: -n FragmentTypeSingle T1
+
+max-time: 1500
+cmd: testDict
+args: -n FragmentTypeAll T1 T6 T7 T8
+
+max-time: 1500
+cmd: testDict
+args: -n FragmentTypeAllLarge T1 T6 T7 T8
+
+max-time: 1500
+cmd: testDict
+args: -n TemporaryTables T1 T6 T7 T8
+
+#
+# TEST NDBAPI
+#
+max-time: 500
+cmd: testDataBuffers
+args:
+
+# Testsuite: testNdbApi
+# Number of tests: 5
+max-time: 500
+cmd: testNdbApi
+args: -n MaxNdb T6
+
+max-time: 500
+cmd: testNdbApi
+args: -n MaxTransactions T1 T6 T7 T8 T13
+
+max-time: 500
+cmd: testNdbApi
+args: -n MaxOperations T1 T6 T7 T8 T13
+
+max-time: 500
+cmd: testNdbApi
+args: -n MaxGetValue T1 T6 T7 T8 T13
+
+max-time: 500
+cmd: testNdbApi
+args: -n MaxEqual
+
+max-time: 500
+cmd: testNdbApi
+args: -n DeleteNdb T1 T6
+
+max-time: 500
+cmd: testNdbApi
+args: -n WaitUntilReady T1 T6 T7 T8 T13
+
+max-time: 500
+cmd: testNdbApi
+args: -n GetOperationNoTab T6
+
+max-time: 500
+cmd: testNdbApi
+args: -n NdbErrorOperation T6
+
+max-time: 500
+cmd: testNdbApi
+args: -n MissingOperation T6
+
+max-time: 500
+cmd: testNdbApi
+args: -n GetValueInUpdate T6
+
+max-time: 500
+cmd: testNdbApi
+args: -n UpdateWithoutKeys T6
+
+max-time: 500
+cmd: testNdbApi
+args: -n UpdateWithoutValues T6
+
+#max-time: 500
+#cmd: testInterpreter
+#args: T1
+#
+max-time: 1500
+cmd: testOperations
+args: -n ReadRead
+
+max-time: 1500
+cmd: testOperations
+args: -n ReadReadEx
+
+max-time: 1500
+cmd: testOperations
+args: -n ReadInsert
+
+max-time: 1500
+cmd: testOperations
+args: -n ReadUpdate
+
+max-time: 1500
+cmd: testOperations
+args: -n ReadDelete
+
+max-time: 1500
+cmd: testOperations
+args: -n FReadRead
+
+max-time: 1500
+cmd: testOperations
+args: -n FReadReadEx
+
+max-time: 1500
+cmd: testOperations
+args: -n FReadInsert
+
+max-time: 1500
+cmd: testOperations
+args: -n FReadUpdate
+
+max-time: 1500
+cmd: testOperations
+args: -n FReadDelete
+
+max-time: 1500
+cmd: testOperations
+args: -n ReadExRead
+
+max-time: 1500
+cmd: testOperations
+args: -n ReadExReadEx
+
+max-time: 1500
+cmd: testOperations
+args: -n ReadExInsert
+
+max-time: 1500
+cmd: testOperations
+args: -n ReadExUpdate
+
+max-time: 1500
+cmd: testOperations
+args: -n ReadExDelete
+
+max-time: 1500
+cmd: testOperations
+args: -n InsertRead
+
+max-time: 1500
+cmd: testOperations
+args: -n InsertReadEx
+
+max-time: 1500
+cmd: testOperations
+args: -n InsertInsert
+
+max-time: 1500
+cmd: testOperations
+args: -n InsertUpdate
+
+max-time: 1500
+cmd: testOperations
+args: -n InsertDelete
+
+max-time: 1500
+cmd: testOperations
+args: -n UpdateRead
+
+max-time: 1500
+cmd: testOperations
+args: -n UpdateReadEx
+
+max-time: 1500
+cmd: testOperations
+args: -n UpdateInsert
+
+max-time: 1500
+cmd: testOperations
+args: -n UpdateUpdate
+
+max-time: 1500
+cmd: testOperations
+args: -n UpdateDelete
+
+max-time: 1500
+cmd: testOperations
+args: -n DeleteRead
+
+max-time: 1500
+cmd: testOperations
+args: -n DeleteReadEx
+
+max-time: 1500
+cmd: testOperations
+args: -n DeleteInsert
+
+max-time: 1500
+cmd: testOperations
+args: -n DeleteUpdate
+
+max-time: 1500
+cmd: testOperations
+args: -n DeleteDelete
+
+max-time: 1500
+cmd: testOperations
+args: -n ReadSimpleRead
+
+max-time: 1500
+cmd: testOperations
+args: -n ReadDirtyRead
+
+max-time: 1500
+cmd: testOperations
+args: -n FReadSimpleRead
+
+max-time: 1500
+cmd: testOperations
+args: -n FReadDirtyRead
+
+max-time: 1500
+cmd: testOperations
+args: -n ReadExSimpleRead
+
+max-time: 1500
+cmd: testOperations
+args: -n ReadExDirtyRead
+
+max-time: 1500
+cmd: testOperations
+args: -n InsertSimpleRead
+
+max-time: 1500
+cmd: testOperations
+args: -n InsertDirtyRead
+
+max-time: 1500
+cmd: testOperations
+args: -n UpdateSimpleRead
+
+max-time: 1500
+cmd: testOperations
+args: -n UpdateDirtyRead
+
+max-time: 1500
+cmd: testOperations
+args: -n DeleteSimpleRead
+
+max-time: 1500
+cmd: testOperations
+args: -n DeleteDirtyRead
+
+max-time: 1500
+cmd: testTransactions
+args: -n ReadRead
+
+max-time: 1500
+cmd: testTransactions
+args: -n ReadReadEx
+
+max-time: 1500
+cmd: testTransactions
+args: -n ReadInsert
+
+max-time: 1500
+cmd: testTransactions
+args: -n ReadUpdate
+
+max-time: 1500
+cmd: testTransactions
+args: -n ReadDelete
+
+max-time: 1500
+cmd: testTransactions
+args: -n ReadExRead
+
+max-time: 1500
+cmd: testTransactions
+args: -n ReadExReadEx
+
+max-time: 1500
+cmd: testTransactions
+args: -n ReadExInsert
+
+max-time: 1500
+cmd: testTransactions
+args: -n ReadExUpdate
+
+max-time: 1500
+cmd: testTransactions
+args: -n ReadExDelete
+
+max-time: 1500
+cmd: testTransactions
+args: -n InsertRead
+
+max-time: 1500
+cmd: testTransactions
+args: -n InsertReadEx
+
+max-time: 1500
+cmd: testTransactions
+args: -n InsertInsert
+
+max-time: 1500
+cmd: testTransactions
+args: -n InsertUpdate
+
+max-time: 1500
+cmd: testTransactions
+args: -n InsertDelete
+
+max-time: 1500
+cmd: testTransactions
+args: -n UpdateRead
+
+max-time: 1500
+cmd: testTransactions
+args: -n UpdateReadEx
+
+max-time: 1500
+cmd: testTransactions
+args: -n UpdateInsert
+
+max-time: 1500
+cmd: testTransactions
+args: -n UpdateUpdate
+
+max-time: 1500
+cmd: testTransactions
+args: -n UpdateDelete
+
+max-time: 1500
+cmd: testTransactions
+args: -n DeleteRead
+
+max-time: 1500
+cmd: testTransactions
+args: -n DeleteReadEx
+
+max-time: 1500
+cmd: testTransactions
+args: -n DeleteInsert
+
+max-time: 1500
+cmd: testTransactions
+args: -n DeleteUpdate
+
+max-time: 1500
+cmd: testTransactions
+args: -n DeleteDelete
+
+max-time: 1500
+cmd: testTransactions
+args: -n ReadSimpleRead
+
+max-time: 1500
+cmd: testTransactions
+args: -n ReadDirtyRead
+
+max-time: 1500
+cmd: testTransactions
+args: -n ReadExSimpleRead
+
+max-time: 1500
+cmd: testTransactions
+args: -n ReadExDirtyRead
+
+max-time: 1500
+cmd: testTransactions
+args: -n InsertSimpleRead
+
+max-time: 1500
+cmd: testTransactions
+args: -n InsertDirtyRead
+
+max-time: 1500
+cmd: testTransactions
+args: -n UpdateSimpleRead
+
+max-time: 1500
+cmd: testTransactions
+args: -n UpdateDirtyRead
+
+max-time: 1500
+cmd: testTransactions
+args: -n DeleteSimpleRead
+
+max-time: 1500
+cmd: testTransactions
+args: -n DeleteDirtyRead
+
+max-time: 1500
+cmd: testTransactions
+args: -n ReadScan
+
+max-time: 1500
+cmd: testTransactions
+args: -n ReadScanHl
+
+max-time: 1500
+cmd: testTransactions
+args: -n ReadScanEx
+
+max-time: 1500
+cmd: testTransactions
+args: -n ScanRead
+
+max-time: 1500
+cmd: testTransactions
+args: -n ScanReadEx
+
+max-time: 1500
+cmd: testTransactions
+args: -n ScanSimpleRead
+
+max-time: 1500
+cmd: testTransactions
+args: -n ScanDirtyRead
+
+max-time: 1500
+cmd: testTransactions
+args: -n ScanInsert
+
+max-time: 1500
+cmd: testTransactions
+args: -n ScanUpdate
+
+max-time: 1500
+cmd: testTransactions
+args: -n ScanDelete
+
+max-time: 1500
+cmd: testTransactions
+args: -n ScanScan
+
+max-time: 1500
+cmd: testTransactions
+args: -n ScanScanHl
+
+max-time: 1500
+cmd: testTransactions
+args: -n ScanScanEx
+
+max-time: 1500
+cmd: testTransactions
+args: -n ScanHlRead
+
+max-time: 1500
+cmd: testTransactions
+args: -n ScanHlReadEx
+
+max-time: 1500
+cmd: testTransactions
+args: -n ScanHlSimpleRead
+
+max-time: 1500
+cmd: testTransactions
+args: -n ScanHlDirtyRead
+
+max-time: 1500
+cmd: testTransactions
+args: -n ScanHlInsert
+
+max-time: 1500
+cmd: testTransactions
+args: -n ScanHlUpdate
+
+max-time: 1500
+cmd: testTransactions
+args: -n ScanHlDelete
+
+max-time: 1500
+cmd: testTransactions
+args: -n ScanHlScan
+
+max-time: 1500
+cmd: testTransactions
+args: -n ScanHlScanHl
+
+max-time: 1500
+cmd: testTransactions
+args: -n ScanHlScanEx
+
+max-time: 1500
+cmd: testTransactions
+args: -n ScanExRead
+
+max-time: 1500
+cmd: testTransactions
+args: -n ScanExReadEx
+
+max-time: 1500
+cmd: testTransactions
+args: -n ScanExSimpleRead
+
+max-time: 1500
+cmd: testTransactions
+args: -n ScanExDirtyRead
+
+max-time: 1500
+cmd: testTransactions
+args: -n ScanExInsert
+
+max-time: 1500
+cmd: testTransactions
+args: -n ScanExUpdate
+
+max-time: 1500
+cmd: testTransactions
+args: -n ScanExDelete
+
+max-time: 1500
+cmd: testTransactions
+args: -n ScanExScan
+
+max-time: 1500
+cmd: testTransactions
+args: -n ScanExScanHl
+
+max-time: 1500
+cmd: testTransactions
+args: -n ScanExScanEx
+
+max-time: 1500
+cmd: testTransactions
+args: -n ReadExScan
+
+max-time: 1500
+cmd: testTransactions
+args: -n ReadExScanHl
+
+max-time: 1500
+cmd: testTransactions
+args: -n ReadExScanEx
+
+max-time: 1500
+cmd: testTransactions
+args: -n InsertScan
+
+max-time: 1500
+cmd: testTransactions
+args: -n InsertScanHl
+
+max-time: 1500
+cmd: testTransactions
+args: -n InsertScanEx
+
+max-time: 1500
+cmd: testTransactions
+args: -n UpdateScan
+
+max-time: 1500
+cmd: testTransactions
+args: -n UpdateScanHl
+
+max-time: 1500
+cmd: testTransactions
+args: -n UpdateScanEx
+
+max-time: 1500
+cmd: testTransactions
+args: -n DeleteScan
+
+max-time: 1500
+cmd: testTransactions
+args: -n DeleteScanHl
+
+max-time: 1500
+cmd: testTransactions
+args: -n DeleteScanEx
+
+max-time: 1500
+cmd: testRestartGci
+args: T6
+
+max-time: 600
+cmd: testBlobs
+args:
+
+max-time: 2500
+cmd: testOIBasic
+args:
+
+#
+#
+# SYSTEM RESTARTS
+#
+max-time: 1500
+cmd: testSystemRestart
+args: -n SR1 T1
+
+max-time: 1500
+cmd: testSystemRestart
+args: -n SR1 T6
+
+max-time: 1500
+cmd: testSystemRestart
+args: -n SR1 T7
+
+max-time: 1500
+cmd: testSystemRestart
+args: -n SR1 T8
+
+max-time: 1500
+cmd: testSystemRestart
+args: -n SR2 T1
+
+max-time: 1500
+cmd: testSystemRestart
+args: -n SR2 T6
+
+max-time: 1500
+cmd: testSystemRestart
+args: -n SR2 T7
+
diff --git a/ndb/test/run-test/daily-devel-tests.txt b/ndb/test/run-test/daily-devel-tests.txt
new file mode 100644
index 00000000000..15fa4db4abc
--- /dev/null
+++ b/ndb/test/run-test/daily-devel-tests.txt
@@ -0,0 +1,204 @@
+#
+# INDEX
+#
+max-time: 1500
+cmd: testIndex
+args: -n CreateAll T1 T6 T13
+
+#-m 7200 1: testIndex -n InsertDeleteGentle T7
+max-time: 3600
+cmd: testIndex
+args: -n InsertDelete T1 T10
+
+#-m 3600 1: testIndex -n CreateLoadDropGentle T7
+max-time: 3600
+cmd: testIndex
+args: -n CreateLoadDrop T1 T10
+
+#
+# BACKUP
+#
+max-time: 600
+cmd: testBackup
+args: -n BackupOne T1 T6 T3 I3
+
+#max-time: 600
+#cmd: testBackup
+#args: -n BackupBank T6
+#
+#
+# MGMAPI AND MGSRV
+#
+max-time: 1800
+cmd: testMgm
+args: -n SingleUserMode T1
+
+#
+#
+# SYSTEM RESTARTS
+#
+max-time: 1500
+cmd: testSystemRestart
+args: -n SR_UNDO T1
+
+max-time: 1500
+cmd: testSystemRestart
+args: -n SR_UNDO T6
+
+max-time: 1500
+cmd: testSystemRestart
+args: -n SR_UNDO T7
+
+max-time: 1500
+cmd: testSystemRestart
+args: -n SR_UNDO T8
+
+max-time: 1500
+cmd: testSystemRestart
+args: -n SR3 T6
+
+max-time: 1500
+cmd: testSystemRestart
+args: -n SR4 T6
+
+#
+max-time: 1500
+cmd: testSystemRestart
+args: -n SR_FULLDB T1
+
+#
+# NODE RESTARTS
+#
+max-time: 2500
+cmd: testNodeRestart
+args: -n NoLoad T6 T8 T13
+
+max-time: 2500
+cmd: testNodeRestart
+args: -n PkRead T6 T8 T13
+
+max-time: 2500
+cmd: testNodeRestart
+args: -l 1 -n PkReadPkUpdate
+
+max-time: 2500
+cmd: testNodeRestart
+args: -l 1 -n ReadUpdateScan
+
+max-time: 2500
+cmd: testNodeRestart
+args: -n Terror T6 T13
+
+max-time: 2500
+cmd: testNodeRestart
+args: -n FullDb T6 T13
+
+max-time: 2500
+cmd: testNodeRestart
+args: -n RestartRandomNode T6 T13
+
+max-time: 2500
+cmd: testNodeRestart
+args: -n RestartRandomNodeError T6 T13
+
+max-time: 2500
+cmd: testNodeRestart
+args: -n RestartRandomNodeInitial T6 T13
+
+max-time: 3600
+cmd: testNodeRestart
+args: -l 1 -n RestartNFDuringNR T6 T13
+
+max-time: 2500
+cmd: testNodeRestart
+args: -n RestartMasterNodeError T6 T8 T13
+
+max-time: 3600
+cmd: testNodeRestart
+args: -n RestartNodeDuringLCP T6
+
+max-time: 2500
+cmd: testNodeRestart
+args: -n TwoNodeFailure T6 T8 T13
+
+max-time: 2500
+cmd: testNodeRestart
+args: -n TwoMasterNodeFailure T6 T8 T13
+
+max-time: 2500
+cmd: testNodeRestart
+args: -n FiftyPercentFail T6 T8 T13
+
+max-time: 2500
+cmd: testNodeRestart
+args: -n RestartAllNodes T6 T8 T13
+
+max-time: 2500
+cmd: testNodeRestart
+args: -n RestartAllNodesAbort T6 T8 T13
+
+max-time: 2500
+cmd: testNodeRestart
+args: -n RestartAllNodesError9999 T6 T8 T13
+
+max-time: 2500
+cmd: testNodeRestart
+args: -n FiftyPercentStopAndWait T6 T8 T13
+
+#max-time: 500
+#cmd: testNodeRestart
+#args: -n StopOnError T1
+#
+#
+max-time: 2500
+cmd: testIndex
+args: -n NFNR1 T6 T13
+
+max-time: 2500
+cmd: testIndex
+args: -n NFNR2 T6 T13
+
+max-time: 2500
+cmd: testIndex
+args: -n NFNR3 T6 T13
+
+max-time: 2500
+cmd: testIndex
+args: -n BuildDuring T6
+
+max-time: 2500
+cmd: testIndex
+args: -l 2 -n SR1 T6 T13
+
+max-time: 2500
+cmd: testIndex
+args: -n NFNR1_O T6 T13
+
+max-time: 2500
+cmd: testIndex
+args: -n NFNR2_O T6 T13
+
+max-time: 2500
+cmd: testIndex
+args: -n NFNR3_O T6 T13
+
+max-time: 2500
+cmd: testIndex
+args: -n BuildDuring_O T6
+
+max-time: 2500
+cmd: testIndex
+args: -l 2 -n SR1_O T6 T13
+
+max-time: 500
+cmd: testIndex
+args: -n MixedTransaction T1
+
+max-time: 2500
+cmd: testDict
+args: -n NF1 T1 T6 T13
+
+max-time: 2500
+cmd: test_event
+args: -n BasicEventOperation T1 T6
+
diff --git a/ndb/test/run-test/main.cpp b/ndb/test/run-test/main.cpp
index 9e318b0219e..6f1899fdbe2 100644
--- a/ndb/test/run-test/main.cpp
+++ b/ndb/test/run-test/main.cpp
@@ -106,13 +106,6 @@ main(int argc, const char ** argv){
if(!setup_hosts(g_config))
goto end;
- if(!start_processes(g_config, atrt_process::NDB_MGM))
- goto end;
-
- if(!connect_ndb_mgm(g_config)){
- goto end;
- }
-
/**
* Main loop
*/
@@ -122,25 +115,32 @@ main(int argc, const char ** argv){
*/
if(restart){
g_logger.info("(Re)starting ndb processes");
+ if(!stop_processes(g_config, atrt_process::NDB_MGM))
+ goto end;
+
if(!stop_processes(g_config, atrt_process::NDB_DB))
goto end;
- if(!wait_ndb(g_config, NDB_MGM_NODE_STATUS_NO_CONTACT))
+ if(!start_processes(g_config, atrt_process::NDB_MGM))
goto end;
+ if(!connect_ndb_mgm(g_config)){
+ goto end;
+ }
+
if(!start_processes(g_config, atrt_process::NDB_DB))
goto end;
-
+
if(!wait_ndb(g_config, NDB_MGM_NODE_STATUS_NOT_STARTED))
goto end;
-
+
for(Uint32 i = 0; i<3; i++)
if(wait_ndb(g_config, NDB_MGM_NODE_STATUS_STARTED))
goto started;
-
+
goto end;
-
-started:
+
+ started:
g_logger.info("Ndb start completed");
}
@@ -211,7 +211,7 @@ started:
(result == 0 ? "OK" : "FAILED"), result);
if(g_report_file != 0){
- fprintf(g_report_file, "%s %s ; %d ; %d ; %d\n",
+ fprintf(g_report_file, "%s %s ; %d ; %d ; %ld\n",
test_case.m_command.c_str(),
test_case.m_args.c_str(),
test_no, result, elapsed);
@@ -447,7 +447,6 @@ setup_config(atrt_config& config){
proc.m_proc.m_owner = "atrt";
proc.m_proc.m_group = "group";
proc.m_proc.m_cwd.assign(dir).append("/run/");
- proc.m_proc.m_env.assfmt("LD_LIBRARY_PATH=%s/lib/mysql", dir.c_str());
proc.m_proc.m_stdout = "log.out";
proc.m_proc.m_stderr = "2>&1";
proc.m_proc.m_runas = proc.m_host->m_user;
@@ -460,7 +459,7 @@ setup_config(atrt_config& config){
proc.m_proc.m_path.assign(dir).append("/libexec/ndb_mgmd");
proc.m_proc.m_args = "-n -c initconfig.txt";
proc.m_proc.m_cwd.appfmt("%d.ndb_mgmd", index);
- connect_string.appfmt(";host=%s:%d",
+ connect_string.appfmt("host=%s:%d;",
proc.m_hostname.c_str(), proc.m_ndb_mgm_port);
} else if(split1[0] == "ndb"){
proc.m_type = atrt_process::NDB_DB;
@@ -502,10 +501,10 @@ setup_config(atrt_config& config){
// Setup connect string
for(size_t i = 0; i<config.m_processes.size(); i++){
- config.m_processes[i].m_proc.m_env.appfmt(" NDB_CONNECTSTRING=nodeid=%d%s",
- i+1, connect_string.c_str());
+ config.m_processes[i].m_proc.m_env.assfmt("NDB_CONNECTSTRING=%s",
+ connect_string.c_str());
}
-
+
end:
fclose(f);
return result;
@@ -615,11 +614,22 @@ wait_ndb(atrt_config& config, int goal){
/**
* 1) retreive current state
*/
- state = ndb_mgm_get_status(handle);
- if(state == 0){
- g_logger.critical("Unable to poll db state");
- return false;
- }
+ state = 0;
+ do {
+ state = ndb_mgm_get_status(handle);
+ if(state == 0){
+ const int err = ndb_mgm_get_latest_error(handle);
+ g_logger.error("Unable to poll db state: %d %s %s",
+ ndb_mgm_get_latest_error(handle),
+ ndb_mgm_get_latest_error_msg(handle),
+ ndb_mgm_get_latest_error_desc(handle));
+ if(err == NDB_MGM_SERVER_NOT_CONNECTED && connect_ndb_mgm(config)){
+ g_logger.error("Reconnected...");
+ continue;
+ }
+ return false;
+ }
+ } while(state == 0);
NdbAutoPtr<void> tmp(state);
min2 = goal;
@@ -791,6 +801,10 @@ update_status(atrt_config& config, int){
proc.m_proc.m_id,
proc.m_hostname.c_str(),
proc.m_proc.m_path.c_str());
+ for(size_t j = 0; j<h_procs.size(); j++){
+ g_logger.error("found: %d %s", h_procs[j].m_id,
+ h_procs[j].m_path.c_str());
+ }
return false;
}
}
@@ -924,9 +938,11 @@ gather_result(atrt_config& config, int * result){
BaseString tmp = g_gather_progname;
for(size_t i = 0; i<config.m_processes.size(); i++){
atrt_process & proc = config.m_processes[i];
- tmp.appfmt(" %s:%s",
- proc.m_hostname.c_str(),
- proc.m_proc.m_cwd.c_str());
+ if(proc.m_proc.m_path != ""){
+ tmp.appfmt(" %s:%s",
+ proc.m_hostname.c_str(),
+ proc.m_proc.m_cwd.c_str());
+ }
}
const int r1 = system(tmp.c_str());
@@ -970,3 +986,7 @@ setup_hosts(atrt_config& config){
}
return true;
}
+
+template class Vector<Vector<SimpleCpcClient::Process> >;
+template class Vector<atrt_host>;
+template class Vector<atrt_process>;
diff --git a/ndb/test/src/HugoAsynchTransactions.cpp b/ndb/test/src/HugoAsynchTransactions.cpp
index 2af22b5f48d..f75293f5a14 100644
--- a/ndb/test/src/HugoAsynchTransactions.cpp
+++ b/ndb/test/src/HugoAsynchTransactions.cpp
@@ -165,12 +165,13 @@ HugoAsynchTransactions::pkUpdateRecordsAsynch(Ndb* pNdb,
allocRows(trans*operations);
allocTransactions(trans);
+ int a, t, r;
for (int i = 0; i < batch; i++) { // For each batch
while (cRecords < records*batch) {
cTrans = 0;
cReadIndex = 0;
- for (int t = 0; t < trans; t++) { // For each transaction
+ for (t = 0; t < trans; t++) { // For each transaction
transactions[t] = pNdb->startTransaction();
if (transactions[t] == NULL) {
ERR(pNdb->getNdbError());
@@ -187,7 +188,7 @@ HugoAsynchTransactions::pkUpdateRecordsAsynch(Ndb* pNdb,
// Read
// Define primary keys
check = pOp->readTupleExclusive();
- for (int a = 0; a < tab.getNoOfColumns(); a++) {
+ for (a = 0; a < tab.getNoOfColumns(); a++) {
if (tab.getColumn(a)->getPrimaryKey() == true) {
if (equalForAttr(pOp, a, cReadRecords) != 0){
ERR(transactions[t]->getNdbError());
@@ -197,7 +198,7 @@ HugoAsynchTransactions::pkUpdateRecordsAsynch(Ndb* pNdb,
}
}
// Define attributes to read
- for (int a = 0; a < tab.getNoOfColumns(); a++) {
+ for (a = 0; a < tab.getNoOfColumns(); a++) {
if ((rows[cReadIndex]->attributeStore(a) =
pOp->getValue(tab.getColumn(a)->getName())) == 0) {
ERR(transactions[t]->getNdbError());
@@ -225,7 +226,7 @@ HugoAsynchTransactions::pkUpdateRecordsAsynch(Ndb* pNdb,
pNdb->sendPollNdb(3000, 0, 0);
// Verify the data!
- for (int r = 0; r < trans*operations; r++) {
+ for (r = 0; r < trans*operations; r++) {
if (calc.verifyRowValues(rows[r]) != 0) {
g_info << "|- Verify failed..." << endl;
// Close all transactions
@@ -239,7 +240,7 @@ HugoAsynchTransactions::pkUpdateRecordsAsynch(Ndb* pNdb,
// Update
cTrans = 0;
cIndex = 0;
- for (int t = 0; t < trans; t++) { // For each transaction
+ for (t = 0; t < trans; t++) { // For each transaction
for (int k = 0; k < operations; k++) { // For each operation
NdbOperation* pOp = transactions[t]->getNdbOperation(tab.getName());
if (pOp == NULL) {
@@ -258,7 +259,7 @@ HugoAsynchTransactions::pkUpdateRecordsAsynch(Ndb* pNdb,
}
// Set search condition for the record
- for (int a = 0; a < tab.getNoOfColumns(); a++) {
+ for (a = 0; a < tab.getNoOfColumns(); a++) {
if (tab.getColumn(a)->getPrimaryKey() == true) {
if (equalForAttr(pOp, a, cRecords) != 0) {
ERR(transactions[t]->getNdbError());
@@ -269,7 +270,7 @@ HugoAsynchTransactions::pkUpdateRecordsAsynch(Ndb* pNdb,
}
// Update the record
- for (int a = 0; a < tab.getNoOfColumns(); a++) {
+ for (a = 0; a < tab.getNoOfColumns(); a++) {
if (tab.getColumn(a)->getPrimaryKey() == false) {
if (setValueForAttr(pOp, a, cRecords, updates) != 0) {
ERR(transactions[t]->getNdbError());
@@ -298,7 +299,7 @@ HugoAsynchTransactions::pkUpdateRecordsAsynch(Ndb* pNdb,
pNdb->sendPollNdb(3000, 0, 0);
// Close all transactions
- for (int t = 0; t < cTrans; t++) {
+ for (t = 0; t < cTrans; t++) {
pNdb->closeTransaction(transactions[t]);
}
@@ -346,6 +347,7 @@ HugoAsynchTransactions::executeAsynchOperation(Ndb* pNdb,
int cTrans = 0;
int cRecords = 0;
int cIndex = 0;
+ int a,t,r;
transactionsCompleted = 0;
allocTransactions(trans);
@@ -354,7 +356,7 @@ HugoAsynchTransactions::executeAsynchOperation(Ndb* pNdb,
while (cRecords < records*batch) {
cTrans = 0;
cIndex = 0;
- for (int t = 0; t < trans; t++) { // For each transaction
+ for (t = 0; t < trans; t++) { // For each transaction
transactions[t] = pNdb->startTransaction();
if (transactions[t] == NULL) {
ERR(pNdb->getNdbError());
@@ -379,7 +381,7 @@ HugoAsynchTransactions::executeAsynchOperation(Ndb* pNdb,
}
// Set a calculated value for each attribute in this table
- for (int a = 0; a < tab.getNoOfColumns(); a++) {
+ for (a = 0; a < tab.getNoOfColumns(); a++) {
if (setValueForAttr(pOp, a, cRecords, 0 ) != 0) {
ERR(transactions[t]->getNdbError());
pNdb->closeTransaction(transactions[t]);
@@ -394,7 +396,7 @@ HugoAsynchTransactions::executeAsynchOperation(Ndb* pNdb,
case NO_READ:
// Define primary keys
check = pOp->readTuple();
- for (int a = 0; a < tab.getNoOfColumns(); a++) {
+ for (a = 0; a < tab.getNoOfColumns(); a++) {
if (tab.getColumn(a)->getPrimaryKey() == true) {
if (equalForAttr(pOp, a, cRecords) != 0){
ERR(transactions[t]->getNdbError());
@@ -404,7 +406,7 @@ HugoAsynchTransactions::executeAsynchOperation(Ndb* pNdb,
}
}
// Define attributes to read
- for (int a = 0; a < tab.getNoOfColumns(); a++) {
+ for (a = 0; a < tab.getNoOfColumns(); a++) {
if ((rows[cIndex]->attributeStore(a) =
pOp->getValue(tab.getColumn(a)->getName())) == 0) {
ERR(transactions[t]->getNdbError());
@@ -423,7 +425,7 @@ HugoAsynchTransactions::executeAsynchOperation(Ndb* pNdb,
}
// Define primary keys
- for (int a = 0; a < tab.getNoOfColumns(); a++) {
+ for (a = 0; a < tab.getNoOfColumns(); a++) {
if (tab.getColumn(a)->getPrimaryKey() == true){
if (equalForAttr(pOp, a, cRecords) != 0) {
ERR(transactions[t]->getNdbError());
@@ -462,7 +464,7 @@ HugoAsynchTransactions::executeAsynchOperation(Ndb* pNdb,
switch (theOperation) {
case NO_READ:
// Verify the data!
- for (int r = 0; r < trans*operations; r++) {
+ for (r = 0; r < trans*operations; r++) {
if (calc.verifyRowValues(rows[r]) != 0) {
g_info << "|- Verify failed..." << endl;
// Close all transactions
@@ -476,11 +478,11 @@ HugoAsynchTransactions::executeAsynchOperation(Ndb* pNdb,
case NO_INSERT:
case NO_UPDATE:
case NO_DELETE:
- abort();
+ break;
}
// Close all transactions
- for (int t = 0; t < cTrans; t++) {
+ for (t = 0; t < cTrans; t++) {
pNdb->closeTransaction(transactions[t]);
}
diff --git a/ndb/test/src/HugoCalculator.cpp b/ndb/test/src/HugoCalculator.cpp
index 55aa96a4909..147c8b104d8 100644
--- a/ndb/test/src/HugoCalculator.cpp
+++ b/ndb/test/src/HugoCalculator.cpp
@@ -28,7 +28,8 @@
HugoCalculator::HugoCalculator(const NdbDictionary::Table& tab) : m_tab(tab) {
// The "id" column of this table is found in the first integer column
- for (int i=0; i<m_tab.getNoOfColumns(); i++){
+ int i;
+ for (i=0; i<m_tab.getNoOfColumns(); i++){
const NdbDictionary::Column* attr = m_tab.getColumn(i);
if (attr->getType() == NdbDictionary::Column::Unsigned){
m_idCol = i;
@@ -37,7 +38,7 @@ HugoCalculator::HugoCalculator(const NdbDictionary::Table& tab) : m_tab(tab) {
}
// The "number of updates" column for this table is found in the last column
- for (int i=m_tab.getNoOfColumns()-1; i>=0; i--){
+ for (i=m_tab.getNoOfColumns()-1; i>=0; i--){
const NdbDictionary::Column* attr = m_tab.getColumn(i);
if (attr->getType() == NdbDictionary::Column::Unsigned){
m_updatesCol = i;
@@ -102,7 +103,8 @@ HugoCalculator::calcValue(int record,
// Fill buf with some pattern so that we can detect
// anomalies in the area that we don't fill with chars
- for (int i = 0; i<attr->getLength(); i++)
+ int i;
+ for (i = 0; i<attr->getLength(); i++)
buf[i] = ((i+2) % 255);
// Calculate length of the string to create. We want the string
@@ -116,7 +118,7 @@ HugoCalculator::calcValue(int record,
else
len++;
}
- for(int i=0; i < len; i++)
+ for(i=0; i < len; i++)
buf[i] = a[((val^i)%25)];
buf[len] = 0;
}
diff --git a/ndb/test/src/HugoOperations.cpp b/ndb/test/src/HugoOperations.cpp
index 91263aa29b4..7c05cb86a93 100644
--- a/ndb/test/src/HugoOperations.cpp
+++ b/ndb/test/src/HugoOperations.cpp
@@ -40,6 +40,9 @@ int HugoOperations::closeTransaction(Ndb* pNdb){
}
pTrans = NULL;
+ m_result_sets.clear();
+ m_executed_result_sets.clear();
+
return NDBT_OK;
}
@@ -51,7 +54,7 @@ int HugoOperations::pkReadRecord(Ndb* pNdb,
int recordNo,
bool exclusive,
int numRecords){
-
+ int a;
allocRows(numRecords);
int check;
for(int r=0; r < numRecords; r++){
@@ -71,7 +74,7 @@ int HugoOperations::pkReadRecord(Ndb* pNdb,
}
// Define primary keys
- for(int a = 0; a<tab.getNoOfColumns(); a++){
+ for(a = 0; a<tab.getNoOfColumns(); a++){
if (tab.getColumn(a)->getPrimaryKey() == true){
if(equalForAttr(pOp, a, r+recordNo) != 0){
ERR(pTrans->getNdbError());
@@ -81,7 +84,7 @@ int HugoOperations::pkReadRecord(Ndb* pNdb,
}
// Define attributes to read
- for(int a = 0; a<tab.getNoOfColumns(); a++){
+ for(a = 0; a<tab.getNoOfColumns(); a++){
if((rows[r]->attributeStore(a) =
pOp->getValue(tab.getColumn(a)->getName())) == 0) {
ERR(pTrans->getNdbError());
@@ -95,7 +98,7 @@ int HugoOperations::pkReadRecord(Ndb* pNdb,
int HugoOperations::pkDirtyReadRecord(Ndb* pNdb,
int recordNo,
int numRecords){
-
+ int a;
allocRows(numRecords);
int check;
for(int r=0; r < numRecords; r++){
@@ -113,7 +116,7 @@ int HugoOperations::pkDirtyReadRecord(Ndb* pNdb,
}
// Define primary keys
- for(int a = 0; a<tab.getNoOfColumns(); a++){
+ for(a = 0; a<tab.getNoOfColumns(); a++){
if (tab.getColumn(a)->getPrimaryKey() == true){
if(equalForAttr(pOp, a, r+recordNo) != 0){
ERR(pTrans->getNdbError());
@@ -123,7 +126,7 @@ int HugoOperations::pkDirtyReadRecord(Ndb* pNdb,
}
// Define attributes to read
- for(int a = 0; a<tab.getNoOfColumns(); a++){
+ for(a = 0; a<tab.getNoOfColumns(); a++){
if((rows[r]->attributeStore(a) =
pOp->getValue(tab.getColumn(a)->getName())) == 0) {
ERR(pTrans->getNdbError());
@@ -137,7 +140,7 @@ int HugoOperations::pkDirtyReadRecord(Ndb* pNdb,
int HugoOperations::pkSimpleReadRecord(Ndb* pNdb,
int recordNo,
int numRecords){
-
+ int a;
allocRows(numRecords);
int check;
for(int r=0; r < numRecords; r++){
@@ -155,7 +158,7 @@ int HugoOperations::pkSimpleReadRecord(Ndb* pNdb,
}
// Define primary keys
- for(int a = 0; a<tab.getNoOfColumns(); a++){
+ for(a = 0; a<tab.getNoOfColumns(); a++){
if (tab.getColumn(a)->getPrimaryKey() == true){
if(equalForAttr(pOp, a, r+recordNo) != 0){
ERR(pTrans->getNdbError());
@@ -165,7 +168,7 @@ int HugoOperations::pkSimpleReadRecord(Ndb* pNdb,
}
// Define attributes to read
- for(int a = 0; a<tab.getNoOfColumns(); a++){
+ for(a = 0; a<tab.getNoOfColumns(); a++){
if((rows[r]->attributeStore(a) =
pOp->getValue(tab.getColumn(a)->getName())) == 0) {
ERR(pTrans->getNdbError());
@@ -180,7 +183,7 @@ int HugoOperations::pkUpdateRecord(Ndb* pNdb,
int recordNo,
int numRecords,
int updatesValue){
-
+ int a;
allocRows(numRecords);
int check;
for(int r=0; r < numRecords; r++){
@@ -197,7 +200,7 @@ int HugoOperations::pkUpdateRecord(Ndb* pNdb,
}
// Define primary keys
- for(int a = 0; a<tab.getNoOfColumns(); a++){
+ for(a = 0; a<tab.getNoOfColumns(); a++){
if (tab.getColumn(a)->getPrimaryKey() == true){
if(equalForAttr(pOp, a, r+recordNo) != 0){
ERR(pTrans->getNdbError());
@@ -207,7 +210,7 @@ int HugoOperations::pkUpdateRecord(Ndb* pNdb,
}
// Define attributes to update
- for(int a = 0; a<tab.getNoOfColumns(); a++){
+ for(a = 0; a<tab.getNoOfColumns(); a++){
if (tab.getColumn(a)->getPrimaryKey() == false){
if(setValueForAttr(pOp, a, recordNo+r, updatesValue ) != 0){
ERR(pTrans->getNdbError());
@@ -224,7 +227,7 @@ int HugoOperations::pkInsertRecord(Ndb* pNdb,
int numRecords,
int updatesValue){
- int check;
+ int a, check;
for(int r=0; r < numRecords; r++){
NdbOperation* pOp = pTrans->getNdbOperation(tab.getName());
if (pOp == NULL) {
@@ -239,7 +242,7 @@ int HugoOperations::pkInsertRecord(Ndb* pNdb,
}
// Define primary keys
- for(int a = 0; a<tab.getNoOfColumns(); a++){
+ for(a = 0; a<tab.getNoOfColumns(); a++){
if (tab.getColumn(a)->getPrimaryKey() == true){
if(equalForAttr(pOp, a, r+recordNo) != 0){
ERR(pTrans->getNdbError());
@@ -249,7 +252,7 @@ int HugoOperations::pkInsertRecord(Ndb* pNdb,
}
// Define attributes to update
- for(int a = 0; a<tab.getNoOfColumns(); a++){
+ for(a = 0; a<tab.getNoOfColumns(); a++){
if (tab.getColumn(a)->getPrimaryKey() == false){
if(setValueForAttr(pOp, a, recordNo+r, updatesValue ) != 0){
ERR(pTrans->getNdbError());
@@ -265,7 +268,7 @@ int HugoOperations::pkDeleteRecord(Ndb* pNdb,
int recordNo,
int numRecords){
- int check;
+ int a, check;
for(int r=0; r < numRecords; r++){
NdbOperation* pOp = pTrans->getNdbOperation(tab.getName());
if (pOp == NULL) {
@@ -280,7 +283,7 @@ int HugoOperations::pkDeleteRecord(Ndb* pNdb,
}
// Define primary keys
- for(int a = 0; a<tab.getNoOfColumns(); a++){
+ for(a = 0; a<tab.getNoOfColumns(); a++){
if (tab.getColumn(a)->getPrimaryKey() == true){
if(equalForAttr(pOp, a, r+recordNo) != 0){
ERR(pTrans->getNdbError());
@@ -291,110 +294,70 @@ int HugoOperations::pkDeleteRecord(Ndb* pNdb,
}
return NDBT_OK;
}
-
-int HugoOperations::scanReadRecords(Ndb* pNdb,
- Uint32 parallelism, ScanLock lock){
-
- NdbConnection * pCon = pNdb->hupp(pTrans);
+#if 0
+NdbResultSet*
+HugoOperations::scanReadRecords(Ndb* pNdb, ScanLock lock){
+
NDBT_ResultRow * m_tmpRow = new NDBT_ResultRow(tab);
- ScanTmp tmp(pCon, m_tmpRow);
- tmp.m_op = ScanTmp::READ;
- NdbOperation* pOp = pCon->getNdbOperation(tab.getName());
+ NdbScanOperation* pOp = pTrans->getNdbScanOperation(tab.getName());
if (pOp == NULL) {
- ERR(pCon->getNdbError());
- return NDBT_FAILED;
+ ERR(pTrans->getNdbError());
+ return 0;
}
+
int check = 0;
+ NdbResultSet * rs = 0;
switch(lock){
case SL_ReadHold:
- check = pOp->openScanReadHoldLock(parallelism);
+ rs = pOp->readTuples(NdbScanOperation::LM_Read, 1, 1);
break;
case SL_Exclusive:
- check = pOp->openScanExclusive(parallelism);
+ rs = pOp->readTuples(NdbScanOperation::LM_Exclusive, 1, 1);
break;
case SL_Read:
default:
- check = pOp->openScanRead(parallelism);
+ rs = pOp->readTuples(NdbScanOperation::LM_Dirty, 1, 1);
}
- if( check == -1 ) {
- ERR(pCon->getNdbError());
- return NDBT_FAILED;
+ if( rs == 0) {
+ ERR(pTrans->getNdbError());
+ return 0;
}
check = pOp->interpret_exit_ok();
if( check == -1 ) {
- ERR(pCon->getNdbError());
- return NDBT_FAILED;
+ ERR(pTrans->getNdbError());
+ return 0;
}
// Define attributes to read
for(int a = 0; a<tab.getNoOfColumns(); a++){
if((m_tmpRow->attributeStore(a) =
pOp->getValue(tab.getColumn(a)->getName())) == 0) {
- ERR(pCon->getNdbError());
- return NDBT_FAILED;
+ ERR(pTrans->getNdbError());
+ return 0;
}
}
-
- check = tmp.pTrans->executeScan();
- if( check == -1 ) {
- NdbError err = tmp.pTrans->getNdbError();
- ERR(err);
- return err.code;
- }
-
- tmp.m_delete = false;
- m_scans.push_back(tmp);
-
- return 0;
+ return rs;
}
-int HugoOperations::executeScanRead(Ndb* pNdb){
-
- int check = 0;
- for(Uint32 i = 0; i<m_scans.size(); i++){
- ScanTmp & tmp = m_scans[i];
- check = run(tmp);
- if(check != 0){
- return check;
- }
- }
- while(m_scans.size() > 0){
- ScanTmp & tmp = m_scans[m_scans.size() - 1];
- if(tmp.m_op != ScanTmp::DONE)
- abort();
-
- tmp.pTrans->close();
- delete tmp.m_tmpRow;
- m_scans.erase(m_scans.size() - 1);
- }
- if(check != 0){
- return check;
+int
+HugoOperations::readTuples(NdbResultSet* rs){
+ int res = 0;
+ while((res = rs->nextResult()) == 0){
}
-
+ if(res != 1)
+ return NDBT_FAILED;
return NDBT_OK;
}
+#endif
int HugoOperations::execute_Commit(Ndb* pNdb,
AbortOption eao){
int check = 0;
- while(m_scans.size() > 0){
- ScanTmp & tmp = m_scans[m_scans.size() - 1];
- if(tmp.m_op != ScanTmp::DONE)
- abort();
-
- tmp.pTrans->close();
- delete tmp.m_tmpRow;
- m_scans.erase(m_scans.size() - 1);
- }
- if(check != 0){
- return check;
- }
-
check = pTrans->execute(Commit, eao);
if( check == -1 ) {
@@ -409,55 +372,41 @@ int HugoOperations::execute_Commit(Ndb* pNdb,
return NDBT_FAILED;
return err.code;
}
- return NDBT_OK;
-}
-int
-HugoOperations::run(ScanTmp & tmp){
- int count = 0;
- if(tmp.m_op == ScanTmp::DONE)
- abort();
+ for(int i = 0; i<m_result_sets.size(); i++){
+ m_executed_result_sets.push_back(m_result_sets[i]);
- int eof = tmp.pTrans->nextScanResult(true) ;
- while(eof == 0){
- count++;
- switch(tmp.m_op){
- case ScanTmp::READ:
- case ScanTmp::UPDATE:
- case ScanTmp::DELETE:
- break;
- case ScanTmp::DONE:
- abort();
+ int rows = m_result_sets[i].records;
+ NdbResultSet* rs = m_result_sets[i].m_result_set;
+ int res = rs->nextResult();
+ switch(res){
+ case 1:
+ return 626;
+ case -1:
+ const NdbError err = pTrans->getNdbError();
+ ERR(err);
+ return (err.code > 0 ? err.code : NDBT_FAILED);
}
- rows.push_back(tmp.m_tmpRow->clone());
- eof = tmp.pTrans->nextScanResult(false);
- }
- tmp.m_op = ScanTmp::DONE;
- if (eof == -1) {
- deallocRows();
- NdbError err = tmp.pTrans->getNdbError();
- ERR(err);
- return err.code;
- }
+ // A row found
- if(count == 0)
- return 626;
+ switch(rows){
+ case 0:
+ return 4000;
+ default:
+ m_result_sets[i].records--;
+ break;
+ }
+ }
- return 0;
+ m_result_sets.clear();
+
+ return NDBT_OK;
}
int HugoOperations::execute_NoCommit(Ndb* pNdb, AbortOption eao){
int check;
- for(Uint32 i = 0; i<m_scans.size(); i++){
- ScanTmp & tmp = m_scans[i];
- check = run(tmp);
- if(check != 0){
- return check;
- }
- }
-
check = pTrans->execute(NoCommit, eao);
if( check == -1 ) {
@@ -472,6 +421,35 @@ int HugoOperations::execute_NoCommit(Ndb* pNdb, AbortOption eao){
return NDBT_FAILED;
return err.code;
}
+
+ for(int i = 0; i<m_result_sets.size(); i++){
+ m_executed_result_sets.push_back(m_result_sets[i]);
+
+ int rows = m_result_sets[i].records;
+ NdbResultSet* rs = m_result_sets[i].m_result_set;
+ int res = rs->nextResult();
+ switch(res){
+ case 1:
+ return 626;
+ case -1:
+ const NdbError err = pTrans->getNdbError();
+ ERR(err);
+ return (err.code > 0 ? err.code : NDBT_FAILED);
+ }
+
+ // A row found
+
+ switch(rows){
+ case 0:
+ return 4000;
+ default:
+ case 1:
+ break;
+ }
+ }
+
+ m_result_sets.clear();
+
return NDBT_OK;
}
@@ -697,16 +675,13 @@ HugoOperations::refresh() {
NdbConnection* t = getTransaction();
if(t)
t->refresh();
- for(Uint32 i = 0; i<m_scans.size(); i++){
- if(m_scans[i].pTrans)
- m_scans[i].pTrans->refresh();
- }
}
int HugoOperations::indexReadRecords(Ndb*, const char * idxName, int recordNo,
bool exclusive,
int numRecords){
+ int a;
allocRows(numRecords);
int check;
for(int r=0; r < numRecords; r++){
@@ -726,7 +701,7 @@ int HugoOperations::indexReadRecords(Ndb*, const char * idxName, int recordNo,
}
// Define primary keys
- for(int a = 0; a<tab.getNoOfColumns(); a++){
+ for(a = 0; a<tab.getNoOfColumns(); a++){
if (tab.getColumn(a)->getPrimaryKey() == true){
if(equalForAttr(pOp, a, r+recordNo) != 0){
ERR(pTrans->getNdbError());
@@ -736,7 +711,7 @@ int HugoOperations::indexReadRecords(Ndb*, const char * idxName, int recordNo,
}
// Define attributes to read
- for(int a = 0; a<tab.getNoOfColumns(); a++){
+ for(a = 0; a<tab.getNoOfColumns(); a++){
if((rows[r]->attributeStore(a) =
pOp->getValue(tab.getColumn(a)->getName())) == 0) {
ERR(pTrans->getNdbError());
@@ -753,7 +728,7 @@ HugoOperations::indexUpdateRecord(Ndb*,
int recordNo,
int numRecords,
int updatesValue){
-
+ int a;
allocRows(numRecords);
int check;
for(int r=0; r < numRecords; r++){
@@ -770,7 +745,7 @@ HugoOperations::indexUpdateRecord(Ndb*,
}
// Define primary keys
- for(int a = 0; a<tab.getNoOfColumns(); a++){
+ for(a = 0; a<tab.getNoOfColumns(); a++){
if (tab.getColumn(a)->getPrimaryKey() == true){
if(equalForAttr(pOp, a, r+recordNo) != 0){
ERR(pTrans->getNdbError());
@@ -780,7 +755,7 @@ HugoOperations::indexUpdateRecord(Ndb*,
}
// Define attributes to update
- for(int a = 0; a<tab.getNoOfColumns(); a++){
+ for(a = 0; a<tab.getNoOfColumns(); a++){
if (tab.getColumn(a)->getPrimaryKey() == false){
if(setValueForAttr(pOp, a, recordNo+r, updatesValue ) != 0){
ERR(pTrans->getNdbError());
@@ -791,3 +766,35 @@ HugoOperations::indexUpdateRecord(Ndb*,
}
return NDBT_OK;
}
+
+int
+HugoOperations::scanReadRecords(Ndb* pNdb, NdbScanOperation::LockMode lm,
+ int records){
+
+ allocRows(records);
+ NdbScanOperation * pOp = pTrans->getNdbScanOperation(tab.getName());
+
+ if(!pOp)
+ return -1;
+
+ NdbResultSet * rs = pOp->readTuples(lm, 1, 1);
+
+ if(!rs){
+ return -1;
+ }
+
+ for(int a = 0; a<tab.getNoOfColumns(); a++){
+ if((rows[0]->attributeStore(a) =
+ pOp->getValue(tab.getColumn(a)->getName())) == 0) {
+ ERR(pTrans->getNdbError());
+ return NDBT_FAILED;
+ }
+ }
+
+ RsPair p = {rs, records};
+ m_result_sets.push_back(p);
+
+ return 0;
+}
+
+template class Vector<HugoOperations::RsPair>;
diff --git a/ndb/test/src/HugoTransactions.cpp b/ndb/test/src/HugoTransactions.cpp
index 7f12484ddc8..05039562c76 100644
--- a/ndb/test/src/HugoTransactions.cpp
+++ b/ndb/test/src/HugoTransactions.cpp
@@ -46,9 +46,9 @@ HugoTransactions::scanReadRecords(Ndb* pNdb,
int retryAttempt = 0;
const int retryMax = 100;
- int check;
+ int check, a;
NdbConnection *pTrans;
- NdbOperation *pOp;
+ NdbScanOperation *pOp;
while (true){
@@ -72,19 +72,18 @@ HugoTransactions::scanReadRecords(Ndb* pNdb,
return NDBT_FAILED;
}
- pOp = pTrans->getNdbOperation(tab.getName());
+ pOp = pTrans->getNdbScanOperation(tab.getName());
if (pOp == NULL) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
return NDBT_FAILED;
}
- if (committed == true)
- check = pOp->openScanReadCommitted(parallelism);
- else
- check = pOp->openScanRead(parallelism);
+ NdbResultSet * rs;
+ rs = pOp ->readTuples(committed ? NdbScanOperation::LM_CommittedRead :
+ NdbScanOperation::LM_Read);
- if( check == -1 ) {
+ if( rs == 0 ) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
return NDBT_FAILED;
@@ -97,7 +96,7 @@ HugoTransactions::scanReadRecords(Ndb* pNdb,
return NDBT_FAILED;
}
- for(int a = 0; a<tab.getNoOfColumns(); a++){
+ for(a = 0; a<tab.getNoOfColumns(); a++){
if((row.attributeStore(a) =
pOp->getValue(tab.getColumn(a)->getName())) == 0) {
ERR(pTrans->getNdbError());
@@ -106,7 +105,7 @@ HugoTransactions::scanReadRecords(Ndb* pNdb,
}
}
- check = pTrans->executeScan();
+ check = pTrans->execute(NoCommit);
if( check == -1 ) {
const NdbError err = pTrans->getNdbError();
if (err.status == NdbError::TemporaryError){
@@ -130,12 +129,10 @@ HugoTransactions::scanReadRecords(Ndb* pNdb,
if (abortCount < abortPercent)
abortTrans = true;
}
-
+
int eof;
int rows = 0;
- eof = pTrans->nextScanResult();
-
- while(eof == 0){
+ while((eof = rs->nextResult(true)) == 0){
rows++;
if (calc.verifyRowValues(&row) != 0){
pNdb->closeTransaction(pTrans);
@@ -145,22 +142,20 @@ HugoTransactions::scanReadRecords(Ndb* pNdb,
if (abortCount == rows && abortTrans == true){
ndbout << "Scan is aborted" << endl;
g_info << "Scan is aborted" << endl;
- check = pTrans->stopScan();
+ rs->close();
if( check == -1 ) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
return NDBT_FAILED;
}
-
+
pNdb->closeTransaction(pTrans);
return NDBT_OK;
}
-
- eof = pTrans->nextScanResult();
}
if (eof == -1) {
const NdbError err = pTrans->getNdbError();
-
+
if (err.status == NdbError::TemporaryError){
ERR_INFO(err);
pNdb->closeTransaction(pTrans);
@@ -199,106 +194,6 @@ HugoTransactions::scanReadRecords(Ndb* pNdb,
#define RESTART_SCAN 99
-// Take over one record from pOrgOp and update it
-int
-HugoTransactions::takeOverAndUpdateRecord(Ndb* pNdb,
- NdbOperation* pOrgOp){
- int retryAttempt = 0;
- const int retryMax = 10;
- int check;
- NdbConnection *pUpdTrans;
- NdbOperation *pUpdOp;
-
- while (true){
-
- if (retryAttempt >= retryMax){
- g_info << "ERROR: has retried this operation " << retryAttempt
- << " times, failing!" << endl;
- return NDBT_FAILED;
- }
-
- pUpdTrans = pNdb->startTransaction();
- if (pUpdTrans == NULL) {
- const NdbError err = pNdb->getNdbError();
-
- if (err.status == NdbError::TemporaryError){
- ERR(err);
- NdbSleep_MilliSleep(50);
- retryAttempt++;
- continue;
- }
- ERR(err);
- return NDBT_FAILED;
- }
-
- if ((pUpdOp = pOrgOp->takeOverForUpdate(pUpdTrans)) == NULL){
- ERR(pNdb->getNdbError());
- return NDBT_FAILED;
- }
-
- int updates = calc.getUpdatesValue(&row) + 1;
- int id = calc.getIdValue(&row);
-
- // Set a calculated value for each non-PK attribute in this table
- for (int a = 0; a<tab.getNoOfColumns(); a++){
- if (tab.getColumn(a)->getPrimaryKey() == false){
- if(setValueForAttr(pUpdOp, a, id, updates ) != 0){
- ERR(pUpdTrans->getNdbError());
- pNdb->closeTransaction(pUpdTrans);
- return NDBT_FAILED;
- }
- }
- }
- check = pUpdTrans->execute( Commit );
- if(check == -1 ) {
- const NdbError err = pUpdTrans->getNdbError();
- pNdb->closeTransaction(pUpdTrans);
-
- ERR(err);
- if(err.code == 499 || err.code == 250){
- return RESTART_SCAN;
- }
-
- switch(err.status){
- case NdbError::Success:
- g_info << "ERROR: NdbError reports success when transcaction failed"
- << endl;
- return NDBT_FAILED;
- break;
-
- case NdbError::TemporaryError:
- NdbSleep_MilliSleep(50+50*retryAttempt);
- retryAttempt++;
- continue;
- break;
-
- case NdbError::UnknownResult:
- return NDBT_FAILED;
- break;
-
- default:
- case NdbError::PermanentError:
- switch (err.code){
- case 499:
- case 250:
- return NDBT_TEMPORARY;
-
- default:
- return NDBT_FAILED;
- break;
- }
- break;
- }
- }
- else{
- pNdb->closeTransaction(pUpdTrans);
- }
-
- return NDBT_OK;
- }
- return NDBT_FAILED;
-}
-
int
HugoTransactions::scanUpdateRecords(Ndb* pNdb,
int records,
@@ -320,9 +215,12 @@ HugoTransactions::scanUpdateRecords1(Ndb* pNdb,
int records,
int abortPercent,
int parallelism){
+#if 1
+ return scanUpdateRecords3(pNdb, records, abortPercent, 1);
+#else
int retryAttempt = 0;
const int retryMax = 100;
- int check;
+ int check, a;
NdbConnection *pTrans;
NdbOperation *pOp;
@@ -371,7 +269,7 @@ HugoTransactions::scanUpdateRecords1(Ndb* pNdb,
}
// Read all attributes from this table
- for(int a=0; a<tab.getNoOfColumns(); a++){
+ for(a=0; a<tab.getNoOfColumns(); a++){
if((row.attributeStore(a) = pOp->getValue(tab.getColumn(a)->getName())) == NULL){
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
@@ -472,9 +370,9 @@ HugoTransactions::scanUpdateRecords1(Ndb* pNdb,
return NDBT_OK;
}
return NDBT_FAILED;
+#endif
}
-
// Scan all records exclusive and update
// them batched by asking nextScanResult to
// give us all cached records before fetching new
@@ -484,9 +382,12 @@ HugoTransactions::scanUpdateRecords2(Ndb* pNdb,
int records,
int abortPercent,
int parallelism){
+#if 1
+ return scanUpdateRecords3(pNdb, records, abortPercent, parallelism);
+#else
int retryAttempt = 0;
const int retryMax = 100;
- int check;
+ int check, a;
NdbConnection *pTrans;
NdbOperation *pOp;
@@ -535,7 +436,7 @@ HugoTransactions::scanUpdateRecords2(Ndb* pNdb,
}
// Read all attributes from this table
- for(int a=0; a<tab.getNoOfColumns(); a++){
+ for(a=0; a<tab.getNoOfColumns(); a++){
if((row.attributeStore(a) = pOp->getValue(tab.getColumn(a)->getName())) == NULL){
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
@@ -642,35 +543,9 @@ HugoTransactions::scanUpdateRecords2(Ndb* pNdb,
return NDBT_OK;
}
return NDBT_FAILED;
+#endif
}
-int
-HugoTransactions::addRowToUpdate(Ndb* pNdb,
- NdbConnection* pUpdTrans,
- NdbOperation* pOrgOp){
-
- int updates = calc.getUpdatesValue(&row) + 1;
- int r = calc.getIdValue(&row);
-
- NdbOperation* pUpdOp = pOrgOp->takeOverForUpdate(pUpdTrans);
- if (pUpdOp == NULL){
- ERR(pNdb->getNdbError());
- return NDBT_FAILED;
- }
-
- for(int a = 0; a<tab.getNoOfColumns(); a++){
- if (tab.getColumn(a)->getPrimaryKey() == false){
- if(setValueForAttr(pUpdOp, a, r, updates ) != 0){
- ERR(pUpdTrans->getNdbError());
- pNdb->closeTransaction(pUpdTrans);
- return NDBT_FAILED;
- }
- }
- }
- return NDBT_OK;
-}
-
-
int
HugoTransactions::scanUpdateRecords3(Ndb* pNdb,
int records,
@@ -678,7 +553,7 @@ HugoTransactions::scanUpdateRecords3(Ndb* pNdb,
int parallelism){
int retryAttempt = 0;
const int retryMax = 100;
- int check;
+ int check, a;
NdbConnection *pTrans;
NdbScanOperation *pOp;
@@ -717,7 +592,7 @@ HugoTransactions::scanUpdateRecords3(Ndb* pNdb,
}
// Read all attributes from this table
- for(int a=0; a<tab.getNoOfColumns(); a++){
+ for(a=0; a<tab.getNoOfColumns(); a++){
if((row.attributeStore(a) = pOp->getValue(tab.getColumn(a)->getName())) == NULL){
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
@@ -759,8 +634,7 @@ HugoTransactions::scanUpdateRecords3(Ndb* pNdb,
}
const int updates = calc.getUpdatesValue(&row) + 1;
const int r = calc.getIdValue(&row);
-
- for(int a = 0; a<tab.getNoOfColumns(); a++){
+ for(a = 0; a<tab.getNoOfColumns(); a++){
if (tab.getColumn(a)->getPrimaryKey() == false){
if(setValueForAttr(pUp, a, r, updates ) != 0){
ERR(pTrans->getNdbError());
@@ -780,7 +654,7 @@ HugoTransactions::scanUpdateRecords3(Ndb* pNdb,
if(check != -1){
check = pTrans->execute(Commit);
- pTrans->releaseCompletedOperations();
+ pTrans->restart();
}
const NdbError err = pTrans->getNdbError();
@@ -794,7 +668,7 @@ HugoTransactions::scanUpdateRecords3(Ndb* pNdb,
return NDBT_FAILED;
}
}
-
+
const NdbError err = pTrans->getNdbError();
if( check == -1 ) {
pNdb->closeTransaction(pTrans);
@@ -819,12 +693,14 @@ HugoTransactions::loadTable(Ndb* pNdb,
int records,
int batch,
bool allowConstraintViolation,
- int doSleep){
- int check;
+ int doSleep,
+ bool oneTrans){
+ int check, a;
int retryAttempt = 0;
int retryMax = 5;
NdbConnection *pTrans;
NdbOperation *pOp;
+ bool first_batch = true;
const int org = batch;
const int cols = tab.getNoOfColumns();
@@ -833,7 +709,7 @@ HugoTransactions::loadTable(Ndb* pNdb,
batch = (batch * 256); // -> 512 -> 65536k per commit
batch = batch/bytes; //
batch = batch == 0 ? 1 : batch;
-
+
if(batch != org){
g_info << "batch = " << org << " rowsize = " << bytes
<< " -> rows/commit = " << batch << endl;
@@ -841,7 +717,7 @@ HugoTransactions::loadTable(Ndb* pNdb,
g_info << "|- Inserting records..." << endl;
for (int c=0 ; c<records ; ){
-
+ bool closeTrans;
if (retryAttempt >= retryMax){
g_info << "Record " << c << " could not be inserted, has retried "
<< retryAttempt << " times " << endl;
@@ -852,19 +728,22 @@ HugoTransactions::loadTable(Ndb* pNdb,
if (doSleep > 0)
NdbSleep_MilliSleep(doSleep);
- pTrans = pNdb->startTransaction();
-
- if (pTrans == NULL) {
- const NdbError err = pNdb->getNdbError();
+ if (first_batch || !oneTrans) {
+ first_batch = false;
+ pTrans = pNdb->startTransaction();
+
+ if (pTrans == NULL) {
+ const NdbError err = pNdb->getNdbError();
- if (err.status == NdbError::TemporaryError){
- ERR(err);
- NdbSleep_MilliSleep(50);
- retryAttempt++;
- continue;
+ if (err.status == NdbError::TemporaryError){
+ ERR(err);
+ NdbSleep_MilliSleep(50);
+ retryAttempt++;
+ continue;
+ }
+ ERR(err);
+ return NDBT_FAILED;
}
- ERR(err);
- return NDBT_FAILED;
}
for(int b = 0; b < batch && c+b<records; b++){
@@ -884,7 +763,7 @@ HugoTransactions::loadTable(Ndb* pNdb,
}
// Set a calculated value for each attribute in this table
- for (int a = 0; a<tab.getNoOfColumns(); a++){
+ for (a = 0; a<tab.getNoOfColumns(); a++){
if(setValueForAttr(pOp, a, c+b, 0 ) != 0){
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
@@ -894,7 +773,13 @@ HugoTransactions::loadTable(Ndb* pNdb,
}
// Execute the transaction and insert the record
- check = pTrans->execute( Commit );
+ if (!oneTrans || (c + batch) >= records) {
+ closeTrans = true;
+ check = pTrans->execute( Commit );
+ } else {
+ closeTrans = false;
+ check = pTrans->execute( NoCommit );
+ }
if(check == -1 ) {
const NdbError err = pTrans->getNdbError();
pNdb->closeTransaction(pTrans);
@@ -937,8 +822,10 @@ HugoTransactions::loadTable(Ndb* pNdb,
break;
}
}
- else{
- pNdb->closeTransaction(pTrans);
+ else{
+ if (closeTrans) {
+ pNdb->closeTransaction(pTrans);
+ }
}
// Step to next record
@@ -951,7 +838,7 @@ HugoTransactions::loadTable(Ndb* pNdb,
int
HugoTransactions::fillTable(Ndb* pNdb,
int batch){
- int check;
+ int check, a, b;
int retryAttempt = 0;
int retryMax = 5;
NdbConnection *pTrans;
@@ -982,7 +869,7 @@ HugoTransactions::fillTable(Ndb* pNdb,
return NDBT_FAILED;
}
- for(int b = 0; b < batch; b++){
+ for(b = 0; b < batch; b++){
pOp = pTrans->getNdbOperation(tab.getName());
if (pOp == NULL) {
@@ -999,7 +886,7 @@ HugoTransactions::fillTable(Ndb* pNdb,
}
// Set a calculated value for each attribute in this table
- for (int a = 0; a<tab.getNoOfColumns(); a++){
+ for (a = 0; a<tab.getNoOfColumns(); a++){
if(setValueForAttr(pOp, a, c+b, 0 ) != 0){
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
@@ -1138,7 +1025,7 @@ int
HugoTransactions::eventOperation(Ndb* pNdb, void* pstats,
int records) {
int myXXXXX = XXXXX++;
-
+ Uint32 i;
const char function[] = "HugoTransactions::eventOperation: ";
struct receivedEvent* recInsertEvent;
NdbAutoObjArrayPtr<struct receivedEvent>
@@ -1155,7 +1042,7 @@ HugoTransactions::eventOperation(Ndb* pNdb, void* pstats,
stats.n_duplicates = 0;
stats.n_inconsistent_gcis = 0;
- for (int i = 0; i < records; i++) {
+ for (i = 0; i < records; i++) {
recInsertEvent[i].pk = 0xFFFFFFFF;
recInsertEvent[i].count = 0;
recInsertEvent[i].event = 0xFFFFFFFF;
@@ -1263,7 +1150,7 @@ HugoTransactions::eventOperation(Ndb* pNdb, void* pstats,
}
g_info << "overrun " << overrun << " pk " << pk;
- for (int i = 1; i < noEventColumnName; i++) {
+ for (i = 1; i < noEventColumnName; i++) {
if (recAttr[i]->isNULL() >= 0) { // we have a value
g_info << " post[" << i << "]=";
if (recAttr[i]->isNULL() == 0) // we have a non-null value
@@ -1306,7 +1193,7 @@ HugoTransactions::eventOperation(Ndb* pNdb, void* pstats,
if (stats.n_updates > 0) {
stats.n_consecutive++;
}
- for (Uint32 i = 0; i < (Uint32)records/3; i++) {
+ for (i = 0; i < (Uint32)records/3; i++) {
if (recInsertEvent[i].pk != i) {
stats.n_consecutive ++;
ndbout << "missing insert pk " << i << endl;
@@ -1345,7 +1232,7 @@ HugoTransactions::pkReadRecords(Ndb* pNdb,
int r = 0;
int retryAttempt = 0;
const int retryMax = 100;
- int check;
+ int check, a;
NdbConnection *pTrans;
NdbOperation *pOp;
@@ -1397,7 +1284,7 @@ HugoTransactions::pkReadRecords(Ndb* pNdb,
}
// Define primary keys
- for(int a = 0; a<tab.getNoOfColumns(); a++){
+ for(a = 0; a<tab.getNoOfColumns(); a++){
if (tab.getColumn(a)->getPrimaryKey() == true){
if(equalForAttr(pOp, a, r+b) != 0){
ERR(pTrans->getNdbError());
@@ -1408,7 +1295,7 @@ HugoTransactions::pkReadRecords(Ndb* pNdb,
}
// Define attributes to read
- for(int a = 0; a<tab.getNoOfColumns(); a++){
+ for(a = 0; a<tab.getNoOfColumns(); a++){
if((rows[b]->attributeStore(a) =
pOp->getValue(tab.getColumn(a)->getName())) == 0) {
ERR(pTrans->getNdbError());
@@ -1471,13 +1358,13 @@ HugoTransactions::pkUpdateRecords(Ndb* pNdb,
int r = 0;
int retryAttempt = 0;
const int retryMax = 100;
- int check;
+ int check, a, b;
NdbConnection *pTrans;
NdbOperation *pOp;
allocRows(batch);
- g_info << "|- Updating records..." << endl;
+ g_info << "|- Updating records (batch=" << batch << ")..." << endl;
while (r < records){
if (retryAttempt >= retryMax){
@@ -1503,7 +1390,7 @@ HugoTransactions::pkUpdateRecords(Ndb* pNdb,
return NDBT_FAILED;
}
- for(int b = 0; b<batch && (r+b) < records; b++){
+ for(b = 0; b<batch && (r+b) < records; b++){
pOp = pTrans->getNdbOperation(tab.getName());
if (pOp == NULL) {
ERR(pTrans->getNdbError());
@@ -1519,7 +1406,7 @@ HugoTransactions::pkUpdateRecords(Ndb* pNdb,
}
// Define primary keys
- for(int a = 0; a<tab.getNoOfColumns(); a++){
+ for(a = 0; a<tab.getNoOfColumns(); a++){
if (tab.getColumn(a)->getPrimaryKey() == true){
if(equalForAttr(pOp, a, r+b) != 0){
ERR(pTrans->getNdbError());
@@ -1530,7 +1417,7 @@ HugoTransactions::pkUpdateRecords(Ndb* pNdb,
}
// Define attributes to read
- for(int a = 0; a<tab.getNoOfColumns(); a++){
+ for(a = 0; a<tab.getNoOfColumns(); a++){
if((rows[b]->attributeStore(a) =
pOp->getValue(tab.getColumn(a)->getName())) == 0) {
ERR(pTrans->getNdbError());
@@ -1556,7 +1443,7 @@ HugoTransactions::pkUpdateRecords(Ndb* pNdb,
return NDBT_FAILED;
}
- for(int b = 0; b<batch && (b+r)<records; b++){
+ for(b = 0; b<batch && (b+r)<records; b++){
if (calc.verifyRowValues(rows[b]) != 0){
pNdb->closeTransaction(pTrans);
return NDBT_FAILED;
@@ -1579,7 +1466,7 @@ HugoTransactions::pkUpdateRecords(Ndb* pNdb,
return NDBT_FAILED;
}
- for(int a = 0; a<tab.getNoOfColumns(); a++){
+ for(a = 0; a<tab.getNoOfColumns(); a++){
if (tab.getColumn(a)->getPrimaryKey() == true){
if(equalForAttr(pUpdOp, a, r+b) != 0){
ERR(pTrans->getNdbError());
@@ -1589,7 +1476,7 @@ HugoTransactions::pkUpdateRecords(Ndb* pNdb,
}
}
- for(int a = 0; a<tab.getNoOfColumns(); a++){
+ for(a = 0; a<tab.getNoOfColumns(); a++){
if (tab.getColumn(a)->getPrimaryKey() == false){
if(setValueForAttr(pUpdOp, a, r+b, updates ) != 0){
ERR(pTrans->getNdbError());
@@ -1639,7 +1526,7 @@ HugoTransactions::pkInterpretedUpdateRecords(Ndb* pNdb,
int r = 0;
int retryAttempt = 0;
const int retryMax = 100;
- int check;
+ int check, a;
NdbConnection *pTrans;
while (r < records){
@@ -1679,7 +1566,7 @@ HugoTransactions::pkInterpretedUpdateRecords(Ndb* pNdb,
}
// Define primary keys
- for(int a = 0; a<tab.getNoOfColumns(); a++){
+ for(a = 0; a<tab.getNoOfColumns(); a++){
if (tab.getColumn(a)->getPrimaryKey() == true){
if(equalForAttr(pOp, a, r) != 0){
ERR(pTrans->getNdbError());
@@ -1690,7 +1577,7 @@ HugoTransactions::pkInterpretedUpdateRecords(Ndb* pNdb,
}
// Read update value
- for(int a = 0; a<tab.getNoOfColumns(); a++){
+ for(a = 0; a<tab.getNoOfColumns(); a++){
if (calc.isUpdateCol(a) == true){
if((row.attributeStore(a) =
pOp->getValue(tab.getColumn(a)->getName())) == 0) {
@@ -1735,7 +1622,7 @@ HugoTransactions::pkInterpretedUpdateRecords(Ndb* pNdb,
}
// PKs
- for(int a = 0; a<tab.getNoOfColumns(); a++){
+ for(a = 0; a<tab.getNoOfColumns(); a++){
if (tab.getColumn(a)->getPrimaryKey() == true){
if(equalForAttr(pUpdOp, a, r) != 0){
ERR(pTrans->getNdbError());
@@ -1746,7 +1633,7 @@ HugoTransactions::pkInterpretedUpdateRecords(Ndb* pNdb,
}
// Update col
- for(int a = 0; a<tab.getNoOfColumns(); a++){
+ for(a = 0; a<tab.getNoOfColumns(); a++){
if ((tab.getColumn(a)->getPrimaryKey() == false) &&
(calc.isUpdateCol(a) == true)){
@@ -1763,7 +1650,7 @@ HugoTransactions::pkInterpretedUpdateRecords(Ndb* pNdb,
}
// Remaining attributes
- for(int a = 0; a<tab.getNoOfColumns(); a++){
+ for(a = 0; a<tab.getNoOfColumns(); a++){
if ((tab.getColumn(a)->getPrimaryKey() == false) &&
(calc.isUpdateCol(a) == false)){
if(setValueForAttr(pUpdOp, a, r, updates ) != 0){
@@ -1818,7 +1705,7 @@ HugoTransactions::pkDelRecords(Ndb* pNdb,
int r = 0;
int retryAttempt = 0;
const int retryMax = 100;
- int check;
+ int check, a;
NdbConnection *pTrans;
NdbOperation *pOp;
@@ -1863,7 +1750,7 @@ HugoTransactions::pkDelRecords(Ndb* pNdb,
}
// Define primary keys
- for(int a = 0; a<tab.getNoOfColumns(); a++){
+ for(a = 0; a<tab.getNoOfColumns(); a++){
if (tab.getColumn(a)->getPrimaryKey() == true){
if(equalForAttr(pOp, a, r) != 0){
ERR(pTrans->getNdbError());
@@ -1933,7 +1820,7 @@ HugoTransactions::lockRecords(Ndb* pNdb,
int r = 0;
int retryAttempt = 0;
const int retryMax = 100;
- int check;
+ int check, a, b;
NdbConnection *pTrans;
NdbOperation *pOp;
@@ -1970,7 +1857,7 @@ HugoTransactions::lockRecords(Ndb* pNdb,
return NDBT_FAILED;
}
- for(int b = 0; (b<lockBatch) && (r+b < records); b++){
+ for(b = 0; (b<lockBatch) && (r+b < records); b++){
pOp = pTrans->getNdbOperation(tab.getName());
if (pOp == NULL) {
ERR(pTrans->getNdbError());
@@ -1986,7 +1873,7 @@ HugoTransactions::lockRecords(Ndb* pNdb,
}
// Define primary keys
- for(int a = 0; a<tab.getNoOfColumns(); a++){
+ for(a = 0; a<tab.getNoOfColumns(); a++){
if (tab.getColumn(a)->getPrimaryKey() == true){
if(equalForAttr(pOp, a, r+b) != 0){
ERR(pTrans->getNdbError());
@@ -1997,7 +1884,7 @@ HugoTransactions::lockRecords(Ndb* pNdb,
}
// Define attributes to read
- for(int a = 0; a<tab.getNoOfColumns(); a++){
+ for(a = 0; a<tab.getNoOfColumns(); a++){
if((rows[b]->attributeStore(a) =
pOp->getValue(tab.getColumn(a)->getName())) == 0) {
ERR(pTrans->getNdbError());
@@ -2080,10 +1967,10 @@ HugoTransactions::indexReadRecords(Ndb* pNdb,
int r = 0;
int retryAttempt = 0;
const int retryMax = 100;
- int check;
+ int check, a;
NdbConnection *pTrans;
NdbOperation *pOp;
- NdbScanOperation *sOp;
+ NdbIndexScanOperation *sOp;
NdbResultSet * rs;
const NdbDictionary::Index* pIndex
@@ -2134,7 +2021,7 @@ HugoTransactions::indexReadRecords(Ndb* pNdb,
}
check = pOp->readTuple();
} else {
- pOp = sOp = pTrans->getNdbScanOperation(idxName, tab.getName());
+ pOp = sOp = pTrans->getNdbIndexScanOperation(idxName, tab.getName());
if (sOp == NULL) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
@@ -2152,7 +2039,7 @@ HugoTransactions::indexReadRecords(Ndb* pNdb,
}
// Define primary keys
- for(int a = 0; a<tab.getNoOfColumns(); a++){
+ for(a = 0; a<tab.getNoOfColumns(); a++){
if (tab.getColumn(a)->getPrimaryKey() == true){
if(equalForAttr(pOp, a, r+b) != 0){
ERR(pTrans->getNdbError());
@@ -2163,7 +2050,7 @@ HugoTransactions::indexReadRecords(Ndb* pNdb,
}
// Define attributes to read
- for(int a = 0; a<tab.getNoOfColumns(); a++){
+ for(a = 0; a<tab.getNoOfColumns(); a++){
if((rows[b]->attributeStore(a) =
pOp->getValue(tab.getColumn(a)->getName())) == 0) {
ERR(pTrans->getNdbError());
@@ -2231,7 +2118,7 @@ HugoTransactions::indexUpdateRecords(Ndb* pNdb,
int r = 0;
int retryAttempt = 0;
const int retryMax = 100;
- int check;
+ int check, a, b;
NdbConnection *pTrans;
NdbOperation *pOp;
NdbScanOperation * sOp;
@@ -2268,7 +2155,7 @@ HugoTransactions::indexUpdateRecords(Ndb* pNdb,
return NDBT_FAILED;
}
- for(int b = 0; b<batchsize && (b+r)<records; b++){
+ for(b = 0; b<batchsize && (b+r)<records; b++){
if(!ordered){
pOp = pTrans->getNdbIndexOperation(idxName, tab.getName());
if (pOp == NULL) {
@@ -2284,7 +2171,7 @@ HugoTransactions::indexUpdateRecords(Ndb* pNdb,
return NDBT_FAILED;
}
} else {
- pOp = sOp = pTrans->getNdbScanOperation(idxName, tab.getName());
+ pOp = sOp = pTrans->getNdbIndexScanOperation(idxName, tab.getName());
if (pOp == NULL) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
@@ -2296,7 +2183,7 @@ HugoTransactions::indexUpdateRecords(Ndb* pNdb,
}
// Define primary keys
- for(int a = 0; a<tab.getNoOfColumns(); a++){
+ for(a = 0; a<tab.getNoOfColumns(); a++){
if (tab.getColumn(a)->getPrimaryKey() == true){
if(equalForAttr(pOp, a, r+b) != 0){
ERR(pTrans->getNdbError());
@@ -2307,7 +2194,7 @@ HugoTransactions::indexUpdateRecords(Ndb* pNdb,
}
// Define attributes to read
- for(int a = 0; a<tab.getNoOfColumns(); a++){
+ for(a = 0; a<tab.getNoOfColumns(); a++){
if((rows[b]->attributeStore(a) =
pOp->getValue(tab.getColumn(a)->getName())) == 0) {
ERR(pTrans->getNdbError());
@@ -2338,7 +2225,7 @@ HugoTransactions::indexUpdateRecords(Ndb* pNdb,
return NDBT_FAILED;
}
- for(int b = 0; b<batchsize && (b+r)<records; b++){
+ for(b = 0; b<batchsize && (b+r)<records; b++){
if (calc.verifyRowValues(rows[b]) != 0){
pNdb->closeTransaction(pTrans);
return NDBT_FAILED;
@@ -2367,7 +2254,7 @@ HugoTransactions::indexUpdateRecords(Ndb* pNdb,
}
if(!ordered){
- for(int a = 0; a<tab.getNoOfColumns(); a++){
+ for(a = 0; a<tab.getNoOfColumns(); a++){
if (tab.getColumn(a)->getPrimaryKey() == true){
if(equalForAttr(pUpdOp, a, r+b) != 0){
ERR(pTrans->getNdbError());
@@ -2378,7 +2265,7 @@ HugoTransactions::indexUpdateRecords(Ndb* pNdb,
}
}
- for(int a = 0; a<tab.getNoOfColumns(); a++){
+ for(a = 0; a<tab.getNoOfColumns(); a++){
if (tab.getColumn(a)->getPrimaryKey() == false){
if(setValueForAttr(pUpdOp, a, r+b, updates ) != 0){
ERR(pTrans->getNdbError());
@@ -2415,4 +2302,4 @@ HugoTransactions::indexUpdateRecords(Ndb* pNdb,
return NDBT_OK;
}
-
+template class Vector<NDBT_ResultRow*>;
diff --git a/ndb/test/src/NDBT_Table.cpp b/ndb/test/src/NDBT_Table.cpp
index 485377e690a..d283cdf5912 100644
--- a/ndb/test/src/NDBT_Table.cpp
+++ b/ndb/test/src/NDBT_Table.cpp
@@ -19,35 +19,6 @@
#include <NDBT.hpp>
class NdbOut&
-operator <<(class NdbOut& ndbout, const NDBT_Attribute & attr){
-
- NdbDictionary::Column::Type type = attr.getType();
-
- ndbout << attr.getName() << " " << type;
-
- switch(type){
- case NdbDictionary::Column::Decimal:
- ndbout << "(" << attr.getScale() << ", " << attr.getPrecision() << ")";
- break;
- default:
- break;
- }
-
- if(attr.getLength() != 1)
- ndbout << "[" << attr.getLength() << "]";
-
- if(attr.getNullable())
- ndbout << " NULL";
- else
- ndbout << " NOT NULL";
-
- if(attr.getPrimaryKey())
- ndbout << " PRIMARY KEY";
-
- return ndbout;
-}
-
-class NdbOut&
operator <<(class NdbOut& ndbout, const NDBT_Table & tab)
{
ndbout << "-- " << tab.getName() << " --" << endl;
diff --git a/ndb/test/src/NDBT_Tables.cpp b/ndb/test/src/NDBT_Tables.cpp
index 548e755a3fb..ff6db3e892c 100644
--- a/ndb/test/src/NDBT_Tables.cpp
+++ b/ndb/test/src/NDBT_Tables.cpp
@@ -297,7 +297,7 @@ NDBT_Table T14("T14", sizeof(T14Attribs)/sizeof(NDBT_Attribute), T14Attribs);
*/
static
const
-NDBT_Attribute C2_PORTS_Attribs[] = {
+NDBT_Attribute I1_Cols[] = {
NDBT_Attribute("ID", NdbDictionary::Column::Unsigned, true),
NDBT_Attribute("PORT", NdbDictionary::Column::Char, 16, true),
NDBT_Attribute("ACCESSNODE", NdbDictionary::Column::Char, 16, true),
@@ -310,11 +310,19 @@ NDBT_Attribute C2_PORTS_Attribs[] = {
};
static
-NDBT_Table C2_PORTS("C2_PORTS", sizeof(C2_PORTS_Attribs)/sizeof(NDBT_Attribute), C2_PORTS_Attribs);
+const
+char* I1_Indexes[] = {
+ "UNIQUE", "ID", "PORT", "ACCESSNODE", "POP", "PORTSTATE", 0,
+ 0
+};
+
+static
+NDBT_Table I1("I1", sizeof(I1_Cols)/sizeof(NDBT_Attribute), I1_Cols
+ );// ,I1_Indexes);
static
const
-NDBT_Attribute C2_SERVICES_Attribs[] = {
+NDBT_Attribute I2_Cols[] = {
NDBT_Attribute("ID", NdbDictionary::Column::Unsigned, true),
NDBT_Attribute("PORT", NdbDictionary::Column::Char, 16, true),
NDBT_Attribute("ACCESSNODE", NdbDictionary::Column::Char, 16, true),
@@ -331,12 +339,20 @@ NDBT_Attribute C2_SERVICES_Attribs[] = {
NDBT_Attribute("UPDATES", NdbDictionary::Column::Unsigned)
};
+const
+char* I2_Indexes[] = {
+ "ORDERED", "CUSTOMER_ID", 0,
+ "ORDERED", "NUM_IP", 0,
+ 0
+};
+
static
-NDBT_Table C2_SERVICES("C2_SERVICES", sizeof(C2_SERVICES_Attribs)/sizeof(NDBT_Attribute), C2_SERVICES_Attribs);
+NDBT_Table I2("I2", sizeof(I2_Cols)/sizeof(NDBT_Attribute), I2_Cols
+ );//, I2_Indexes);
static
const
-NDBT_Attribute C2_CLIENTS_Attribs[] = {
+NDBT_Attribute I3_Cols[] = {
NDBT_Attribute("ID", NdbDictionary::Column::Unsigned, true),
NDBT_Attribute("PORT", NdbDictionary::Column::Char, 16), // SI2
NDBT_Attribute("ACCESSNODE", NdbDictionary::Column::Char, 16), // SI2
@@ -355,8 +371,17 @@ NDBT_Attribute C2_CLIENTS_Attribs[] = {
NDBT_Attribute("UPDATES", NdbDictionary::Column::Unsigned)
};
+const
+char* I3_Indexes[] = {
+ "UNIQUE", "ID", 0,
+ "ORDERED", "MAC", 0,
+ "ORDERED", "GW", 0,
+ 0
+};
+
static
-NDBT_Table C2_CLIENTS("C2_CLIENTS", sizeof(C2_CLIENTS_Attribs)/sizeof(NDBT_Attribute), C2_CLIENTS_Attribs);
+NDBT_Table I3("I3", sizeof(I3_Cols)/sizeof(NDBT_Attribute), I3_Cols
+ ); // ,I3_Indexes);
// Define array with pointer to all tables
static
@@ -377,10 +402,23 @@ NDBT_Table *test_tables[]=
&T12,
&T13,
&T14,
- &C2_PORTS,
- &C2_SERVICES,
- &C2_CLIENTS
+ &I1,
+ &I2,
+ &I3
+};
+
+struct NDBT_IndexList {
+ const char * m_table;
+ const char ** m_indexes;
+};
+static
+const
+NDBT_IndexList indexes[] = {
+ "I1", I1_Indexes,
+ "I2", I2_Indexes,
+ "I3", I3_Indexes,
+ 0, 0
};
static
@@ -430,7 +468,7 @@ NDBT_Table F2("F2", sizeof(F2Attribs)/sizeof(NDBT_Attribute), F2Attribs);
/* F3
*
- * Error: Too many primary keys defined, 16 is max?
+ * Error: Too many primary keys defined, 32 is max
*/
static
const
@@ -452,10 +490,26 @@ NDBT_Attribute F3Attribs[] = {
NDBT_Attribute("KOL15", NdbDictionary::Column::Unsigned, 1, true),
NDBT_Attribute("KOL16", NdbDictionary::Column::Unsigned, 1, true),
NDBT_Attribute("KOL17", NdbDictionary::Column::Unsigned, 1, true),
- NDBT_Attribute("KOL20", NdbDictionary::Column::Unsigned),
- NDBT_Attribute("KOL30", NdbDictionary::Column::Unsigned),
+ NDBT_Attribute("KOL18", NdbDictionary::Column::Unsigned, 1, true),
+ NDBT_Attribute("KOL19", NdbDictionary::Column::Unsigned, 1, true),
+ NDBT_Attribute("KOL20", NdbDictionary::Column::Unsigned, 1, true),
+ NDBT_Attribute("KOL21", NdbDictionary::Column::Unsigned, 1, true),
+ NDBT_Attribute("KOL22", NdbDictionary::Column::Unsigned, 1, true),
+ NDBT_Attribute("KOL23", NdbDictionary::Column::Unsigned, 1, true),
+ NDBT_Attribute("KOL24", NdbDictionary::Column::Unsigned, 1, true),
+ NDBT_Attribute("KOL25", NdbDictionary::Column::Unsigned, 1, true),
+ NDBT_Attribute("KOL26", NdbDictionary::Column::Unsigned, 1, true),
+ NDBT_Attribute("KOL27", NdbDictionary::Column::Unsigned, 1, true),
+ NDBT_Attribute("KOL28", NdbDictionary::Column::Unsigned, 1, true),
+ NDBT_Attribute("KOL29", NdbDictionary::Column::Unsigned, 1, true),
+ NDBT_Attribute("KOL30", NdbDictionary::Column::Unsigned, 1, true),
+ NDBT_Attribute("KOL31", NdbDictionary::Column::Unsigned, 1, true),
+ NDBT_Attribute("KOL32", NdbDictionary::Column::Unsigned, 1, true),
+ NDBT_Attribute("KOL33", NdbDictionary::Column::Unsigned, 1, true),
NDBT_Attribute("KOL40", NdbDictionary::Column::Unsigned),
- NDBT_Attribute("KOL50", NdbDictionary::Column::Unsigned)
+ NDBT_Attribute("KOL50", NdbDictionary::Column::Unsigned),
+ NDBT_Attribute("KOL60", NdbDictionary::Column::Unsigned),
+ NDBT_Attribute("KOL70", NdbDictionary::Column::Unsigned)
};
static
@@ -678,17 +732,18 @@ NdbDictionary::Table*
NDBT_Tables::getTable(const char* _nam){
// Search tables list to find a table
NDBT_Table* tab = NULL;
- for (int i=0; i<numTestTables; i++){
+ int i;
+ for (i=0; i<numTestTables; i++){
if (strcmp(test_tables[i]->getName(), _nam) == 0){
return test_tables[i];
}
}
- for (int i=0; i<numFailTables; i++){
+ for (i=0; i<numFailTables; i++){
if (strcmp(fail_tables[i]->getName(), _nam) == 0){
return fail_tables[i];
}
}
- for (int i=0; i<numUtilTables; i++){
+ for (i=0; i<numUtilTables; i++){
if (strcmp(util_tables[i]->getName(), _nam) == 0){
return util_tables[i];
}
@@ -746,26 +801,13 @@ NDBT_Tables::getNumTables(){
int
NDBT_Tables::createAllTables(Ndb* pNdb, bool _temp, bool existsOk){
-
+
for (int i=0; i < NDBT_Tables::getNumTables(); i++){
-
- const NdbDictionary::Table* tab = NDBT_Tables::getTable(i);
- if (tab == NULL){
- return NDBT_ProgramExit(NDBT_FAILED);
- }
-
- // Set temporary table
- NdbDictionary::Table tmpTab(* tab);
- tmpTab.setStoredTable(_temp? 0 : 1);
-
- int r = pNdb->getDictionary()->createTable(tmpTab);
- int err = pNdb->getDictionary()->getNdbError().code;
- if(r == -1){
- if (existsOk && err == 721)
- ;
- else {
- return NDBT_FAILED;
- }
+ pNdb->getDictionary()->dropTable(NDBT_Tables::getTable(i)->getName());
+ int ret= createTable(pNdb,
+ NDBT_Tables::getTable(i)->getName(), _temp, existsOk);
+ if(ret){
+ return ret;
}
}
return NDBT_OK;
@@ -777,7 +819,8 @@ NDBT_Tables::createAllTables(Ndb* pNdb){
}
int
-NDBT_Tables::createTable(Ndb* pNdb, const char* _name, bool _temp){
+NDBT_Tables::createTable(Ndb* pNdb, const char* _name, bool _temp,
+ bool existsOk){
const NdbDictionary::Table* tab = NDBT_Tables::getTable(_name);
if (tab == NULL){
@@ -787,10 +830,61 @@ NDBT_Tables::createTable(Ndb* pNdb, const char* _name, bool _temp){
return NDBT_WRONGARGS;
}
- NdbDictionary::Table tmpTab(* tab);
- tmpTab.setStoredTable(_temp ? 0 : 1);
+ int r = 0;
+ do {
+ NdbDictionary::Table tmpTab(* tab);
+ tmpTab.setStoredTable(_temp ? 0 : 1);
+
+ r = pNdb->getDictionary()->createTable(tmpTab);
+ if(r == -1){
+ if(!existsOk){
+ ndbout << "Error: " << pNdb->getDictionary()->getNdbError() << endl;
+ break;
+ }
+ if(pNdb->getDictionary()->getNdbError().code != 721){
+ ndbout << "Error: " << pNdb->getDictionary()->getNdbError() << endl;
+ break;
+ }
+ r = 0;
+ }
+
+ Uint32 i = 0;
+ for(i = 0; indexes[i].m_table != 0; i++){
+ if(strcmp(indexes[i].m_table, _name) != 0)
+ continue;
+ Uint32 j = 0;
+ while(indexes[i].m_indexes[j] != 0){
+ NdbDictionary::Index tmpIndx;
+ BaseString name;
+ name.assfmt("%s$NDBT_IDX%d", _name, j);
+ tmpIndx.setName(name.c_str());
+ tmpIndx.setTable(_name);
+ bool logging = !_temp;
+ if(strcmp(indexes[i].m_indexes[j], "ORDERED") == 0){
+ logging = false;
+ tmpIndx.setType(NdbDictionary::Index::OrderedIndex);
+ } else if(strcmp(indexes[i].m_indexes[j], "UNIQUE") == 0){
+ tmpIndx.setType(NdbDictionary::Index::UniqueHashIndex);
+ } else {
+ ndbout << "Unknown index type";
+ abort();
+ }
+ tmpIndx.setLogging(logging);
+
+ j++;
+ while(indexes[i].m_indexes[j] != 0){
+ tmpIndx.addIndexColumn(indexes[i].m_indexes[j]);
+ j++;
+ }
+ j++;
+ if(pNdb->getDictionary()->createIndex(tmpIndx) != 0){
+ ndbout << pNdb->getDictionary()->getNdbError() << endl;
+ return NDBT_FAILED;
+ }
+ }
+ }
+ } while(false);
- int r = pNdb->getDictionary()->createTable(tmpTab);
return r;
}
@@ -815,7 +909,7 @@ NDBT_Tables::dropAllTables(Ndb* pNdb){
int
NDBT_Tables::print(const char * _name){
- const NdbDictionary::Table* tab = NDBT_Tables::getTable(_name);
+ const NDBT_Table * tab = (const NDBT_Table*)NDBT_Tables::getTable(_name);
if (tab == NULL){
ndbout << "Could not print table " << _name
<< ", it doesn't exist in list of tables "
@@ -835,7 +929,7 @@ NDBT_Tables::printAll(){
if (tab == NULL){
abort();
}
- ndbout << (* tab) << endl;
+ ndbout << (* (NDBT_Table*)tab) << endl;
}
return NDBT_OK;
diff --git a/ndb/test/src/NDBT_Test.cpp b/ndb/test/src/NDBT_Test.cpp
index 4cd2c96486b..b1691c379a9 100644
--- a/ndb/test/src/NDBT_Test.cpp
+++ b/ndb/test/src/NDBT_Test.cpp
@@ -132,6 +132,17 @@ void NDBT_Context::setProperty(const char* _name, Uint32 _val){
assert(b == true);
NdbMutex_Unlock(propertyMutexPtr);
}
+void
+NDBT_Context::decProperty(const char * name){
+ NdbMutex_Lock(propertyMutexPtr);
+ Uint32 val = 0;
+ if(props.get(name, &val)){
+ assert(val > 0);
+ props.put(name, (val - 1), true);
+ }
+ NdbCondition_Broadcast(propertyCondPtr);
+ NdbMutex_Unlock(propertyMutexPtr);
+}
void NDBT_Context::setProperty(const char* _name, const char* _val){
NdbMutex_Lock(propertyMutexPtr);
@@ -336,24 +347,24 @@ NDBT_TestCaseImpl1::NDBT_TestCaseImpl1(NDBT_TestSuite* psuite,
NDBT_TestCaseImpl1::~NDBT_TestCaseImpl1(){
NdbCondition_Destroy(waitThreadsCondPtr);
NdbMutex_Destroy(waitThreadsMutexPtr);
-
- for(size_t i = 0; i < initializers.size(); i++)
+ size_t i;
+ for(i = 0; i < initializers.size(); i++)
delete initializers[i];
initializers.clear();
- for(size_t i = 0; i < verifiers.size(); i++)
+ for(i = 0; i < verifiers.size(); i++)
delete verifiers[i];
verifiers.clear();
- for(size_t i = 0; i < finalizers.size(); i++)
+ for(i = 0; i < finalizers.size(); i++)
delete finalizers[i];
finalizers.clear();
- for(size_t i = 0; i < steps.size(); i++)
+ for(i = 0; i < steps.size(); i++)
delete steps[i];
steps.clear();
results.clear();
- for(size_t i = 0; i < testTables.size(); i++)
+ for(i = 0; i < testTables.size(); i++)
delete testTables[i];
testTables.clear();
- for(size_t i = 0; i < testResults.size(); i++)
+ for(i = 0; i < testResults.size(); i++)
delete testResults[i];
testResults.clear();
@@ -487,7 +498,8 @@ void NDBT_TestCaseImpl1::waitSteps(){
waitThreadsMutexPtr);
unsigned completedSteps = 0;
- for(unsigned i=0; i<steps.size(); i++){
+ unsigned i;
+ for(i=0; i<steps.size(); i++){
if (results[i] != NORESULT){
completedSteps++;
if (results[i] == NDBT_OK)
@@ -501,7 +513,7 @@ void NDBT_TestCaseImpl1::waitSteps(){
NdbMutex_Unlock(waitThreadsMutexPtr);
void *status;
- for(unsigned i=0; i<steps.size();i++){
+ for(i=0; i<steps.size();i++){
NdbThread_WaitFor(threads[i], &status);
NdbThread_Destroy(&threads[i]);
}
@@ -633,12 +645,12 @@ int NDBT_TestCaseImpl1::runSteps(NDBT_Context* ctx){
numStepsOk = 0;
numStepsFail = 0;
numStepsCompleted = 0;
-
- for (unsigned i = 0; i < steps.size(); i++)
+ unsigned i;
+ for (i = 0; i < steps.size(); i++)
startStepInThread(i, ctx);
waitSteps();
- for(unsigned i = 0; i < steps.size(); i++)
+ for(i = 0; i < steps.size(); i++)
if (results[i] != NDBT_OK)
res = NDBT_FAILED;
return res;
@@ -808,18 +820,19 @@ void NDBT_TestSuite::execute(Ndb* ndb, const NdbDictionary::Table* pTab,
const NdbDictionary::Table* pTab2 = pDict->getTable(pTab->getName());
if (createTable == true){
- if (pTab2 != 0 && !pTab->equal(* pTab2)){
+ if(pTab2 != 0 && pDict->dropTable(pTab->getName()) != 0){
numTestsFail++;
numTestsExecuted++;
- g_err << "ERROR0: Failed to create table " << pTab->getName() << endl;
+ g_err << "ERROR0: Failed to drop table " << pTab->getName() << endl;
tests[t]->saveTestResult(pTab, FAILED_TO_CREATE);
continue;
}
-
- if(pTab2 == 0 && pDict->createTable(* pTab) != 0){
+
+ if(NDBT_Tables::createTable(ndb, pTab->getName()) != 0){
numTestsFail++;
numTestsExecuted++;
- g_err << "ERROR1: Failed to create table " << pTab->getName() << endl;
+ g_err << "ERROR1: Failed to create table " << pTab->getName()
+ << pDict->getNdbError() << endl;
tests[t]->saveTestResult(pTab, FAILED_TO_CREATE);
continue;
}
@@ -994,6 +1007,7 @@ int NDBT_TestSuite::execute(int argc, const char** argv){
res = executeAll(_testname);
} else {
testSuiteTimer.doStart();
+ Ndb ndb("TEST_DB"); ndb.init();
for(int i = optind; i<argc; i++){
executeOne(argv[i], _testname);
}
@@ -1091,20 +1105,20 @@ void NDBT_TestCaseImpl1::print(){
abort();
}
}
-
- for(unsigned i=0; i<initializers.size(); i++){
+ unsigned i;
+ for(i=0; i<initializers.size(); i++){
ndbout << "Initializers[" << i << "]: " << endl;
initializers[i]->print();
}
- for(unsigned i=0; i<steps.size(); i++){
+ for(i=0; i<steps.size(); i++){
ndbout << "Step[" << i << "]: " << endl;
steps[i]->print();
}
- for(unsigned i=0; i<verifiers.size(); i++){
+ for(i=0; i<verifiers.size(); i++){
ndbout << "Verifier[" << i << "]: " << endl;
verifiers[i]->print();
}
- for(unsigned i=0; i<finalizers.size(); i++){
+ for(i=0; i<finalizers.size(); i++){
ndbout << "Finalizer[" << i << "]: " << endl;
finalizers[i]->print();
}
@@ -1116,6 +1130,11 @@ void NDBT_Step::print(){
}
-
-
-
+template class Vector<NDBT_TestCase*>;
+template class Vector<NDBT_TestCaseResult*>;
+template class Vector<NDBT_Step*>;
+template class Vector<NdbThread*>;
+template class Vector<NDBT_Verifier*>;
+template class Vector<NDBT_Initializer*>;
+template class Vector<NDBT_Finalizer*>;
+template class Vector<const NdbDictionary::Table*>;
diff --git a/ndb/test/src/NdbBackup.cpp b/ndb/test/src/NdbBackup.cpp
index 169034e0c07..a40c6ba7d7c 100644
--- a/ndb/test/src/NdbBackup.cpp
+++ b/ndb/test/src/NdbBackup.cpp
@@ -69,17 +69,24 @@ NdbBackup::getFileSystemPathForNode(int _node_id){
/**
* Fetch configuration from management server
*/
- ConfigRetriever cr;
+ ConfigRetriever cr(0, NODE_TYPE_API);
+ ndb_mgm_configuration * p = 0;
- ndb_mgm_configuration * p = cr.getConfig(host, port, 0);
- if(p == 0){
- const char * s = cr.getErrorString();
- if(s == 0)
- s = "No error given!";
+ BaseString tmp; tmp.assfmt("%s:%d", host.c_str(), port);
+ NdbMgmHandle handle = ndb_mgm_create_handle();
+ if(handle == 0 || ndb_mgm_connect(handle, tmp.c_str()) != 0 ||
+ (p = ndb_mgm_get_configuration(handle, 0)) == 0){
- ndbout << "Could not fetch configuration" << endl;
- ndbout << s << endl;
- return NULL;
+ const char * s = 0;
+ if(p == 0 && handle != 0){
+ s = ndb_mgm_get_latest_error_msg(handle);
+ if(s == 0)
+ s = "No error given!";
+
+ ndbout << "Could not fetch configuration" << endl;
+ ndbout << s << endl;
+ return NULL;
+ }
}
/**
@@ -90,7 +97,8 @@ NdbBackup::getFileSystemPathForNode(int _node_id){
ndbout << "Invalid configuration fetched, DB missing" << endl;
return NULL;
}
- unsigned int type = 123456;
+
+ unsigned int type = NODE_TYPE_DB + 1;
if(iter.get(CFG_TYPE_OF_SECTION, &type) || type != NODE_TYPE_DB){
ndbout <<"type = " << type << endl;
ndbout <<"Invalid configuration fetched, I'm wrong type of node" << endl;
@@ -141,31 +149,18 @@ NdbBackup::execRestore(bool _restore_data,
ndbout << "res: " << res << endl;
-#if 0
- snprintf(buf, 255, "ndb_restore -c \"nodeid=%d;host=%s\" -n %d -b %d %s %s %s/BACKUP/BACKUP-%d",
- ownNodeId,
- addr,
- _node_id,
- _backup_id,
- _restore_data?"-r":"",
- _restore_meta?"-m":"",
- path,
- _backup_id);
-
+ snprintf(buf, 255, "%sndb_restore -c \"host=%s\" -n %d -b %d %s %s .",
+#if 1
+ "",
+#else
+ "valgrind --leak-check=yes -v "
#endif
-
- snprintf(buf, 255, "ndb_restore -c \"nodeid=%d;host=%s\" -n %d -b %d %s %s .",
- ownNodeId,
- addr,
+ addr.c_str(),
_node_id,
_backup_id,
_restore_data?"-r":"",
_restore_meta?"-m":"");
- // path,
- // _backup_id);
-
-
ndbout << "buf: "<< buf <<endl;
res = system(buf);
diff --git a/ndb/test/src/NdbRestarter.cpp b/ndb/test/src/NdbRestarter.cpp
index b731cccb259..4d6d3ddc001 100644
--- a/ndb/test/src/NdbRestarter.cpp
+++ b/ndb/test/src/NdbRestarter.cpp
@@ -33,13 +33,11 @@
NdbRestarter::NdbRestarter(const char* _addr):
connected(false),
- addr(_addr),
- host(NULL),
port(-1),
handle(NULL),
m_config(0)
{
- if (addr == NULL){
+ if (_addr == NULL){
LocalConfig lcfg;
if(!lcfg.init()){
lcfg.printError();
@@ -48,32 +46,32 @@ NdbRestarter::NdbRestarter(const char* _addr):
return;
}
- if (lcfg.items == 0){
+ if (lcfg.ids.size() == 0){
g_err << "NdbRestarter - No management servers configured in local config file" << endl;
return;
}
- for (int i = 0; i<lcfg.items; i++){
- MgmtSrvrId * m = lcfg.ids[i];
+ for (int i = 0; i<lcfg.ids.size(); i++){
+ MgmtSrvrId * m = &lcfg.ids[i];
switch(m->type){
case MgmId_TCP:
char buf[255];
- snprintf(buf, 255, "%s:%d", m->data.tcp.remoteHost, m->data.tcp.port);
- addr = strdup(buf);
- host = strdup(m->data.tcp.remoteHost);
- port = m->data.tcp.port;
+ snprintf(buf, 255, "%s:%d", m->name.c_str(), m->port);
+ addr.assign(buf);
+ host.assign(m->name.c_str());
+ port = m->port;
+ return;
break;
case MgmId_File:
break;
default:
break;
}
- if (addr != NULL)
- break;
}
+ } else {
+ addr.assign(_addr);
}
-
}
NdbRestarter::~NdbRestarter(){
@@ -398,10 +396,10 @@ NdbRestarter::connect(){
g_err << "handle == NULL" << endl;
return -1;
}
- g_info << "Connecting to mgmsrv at " << addr << endl;
- if (ndb_mgm_connect(handle, addr) == -1) {
+ g_info << "Connecting to mgmsrv at " << addr.c_str() << endl;
+ if (ndb_mgm_connect(handle, addr.c_str()) == -1) {
MGMERR(handle);
- g_err << "Connection to " << addr << " failed" << endl;
+ g_err << "Connection to " << addr.c_str() << " failed" << endl;
return -1;
}
@@ -672,3 +670,5 @@ NdbRestarter::getConfig(){
m_config = ndb_mgm_get_configuration(handle, 0);
return m_config;
}
+
+template class Vector<ndb_mgm_node_state>;
diff --git a/ndb/test/src/NdbRestarts.cpp b/ndb/test/src/NdbRestarts.cpp
index f6a85d69fc2..b649a60d98b 100644
--- a/ndb/test/src/NdbRestarts.cpp
+++ b/ndb/test/src/NdbRestarts.cpp
@@ -625,9 +625,9 @@ int restartNFDuringNR(NdbRestarter& _restarter,
const NdbRestarts::NdbRestart* _restart){
myRandom48Init(NdbTick_CurrentMillisecond());
-
+ int i;
const int sz = sizeof(NFDuringNR_codes)/sizeof(NFDuringNR_codes[0]);
- for(int i = 0; i<sz; i++){
+ for(i = 0; i<sz; i++){
int randomId = myRandom48(_restarter.getNumDbNodes());
int nodeId = _restarter.getDbNodeId(randomId);
int error = NFDuringNR_codes[i];
@@ -673,7 +673,7 @@ int restartNFDuringNR(NdbRestarter& _restarter,
if(NdbEnv_GetEnv("USER", buf, 256) == 0 || strcmp(buf, "ejonore") != 0)
return NDBT_OK;
- for(int i = 0; i<sz; i++){
+ for(i = 0; i<sz; i++){
const int randomId = myRandom48(_restarter.getNumDbNodes());
int nodeId = _restarter.getDbNodeId(randomId);
const int error = NFDuringNR_codes[i];
@@ -753,14 +753,14 @@ NRDuringLCP_NonMaster_codes[] = {
int restartNodeDuringLCP(NdbRestarter& _restarter,
const NdbRestarts::NdbRestart* _restart) {
-
+ int i;
// Master
int val = DumpStateOrd::DihMinTimeBetweenLCP;
CHECK(_restarter.dumpStateAllNodes(&val, 1) == 0,
"Failed to set LCP to min value"); // Set LCP to min val
int sz = sizeof(NRDuringLCP_Master_codes)/
sizeof(NRDuringLCP_Master_codes[0]);
- for(int i = 0; i<sz; i++) {
+ for(i = 0; i<sz; i++) {
int error = NRDuringLCP_Master_codes[i];
int masterNodeId = _restarter.getMasterNodeId();
@@ -798,7 +798,7 @@ int restartNodeDuringLCP(NdbRestarter& _restarter,
// NON-Master
sz = sizeof(NRDuringLCP_NonMaster_codes)/
sizeof(NRDuringLCP_NonMaster_codes[0]);
- for(int i = 0; i<sz; i++) {
+ for(i = 0; i<sz; i++) {
int error = NRDuringLCP_NonMaster_codes[i];
int nodeId = getRandomNodeId(_restarter);
diff --git a/ndb/test/src/UtilTransactions.cpp b/ndb/test/src/UtilTransactions.cpp
index 3ef31a2f535..9f3f1d33587 100644
--- a/ndb/test/src/UtilTransactions.cpp
+++ b/ndb/test/src/UtilTransactions.cpp
@@ -47,10 +47,14 @@ UtilTransactions::clearTable(Ndb* pNdb,
}
}
+
int
UtilTransactions::clearTable1(Ndb* pNdb,
int records,
int parallelism){
+#if 1
+ return clearTable3(pNdb, records, 1);
+#else
// Scan all records exclusive and delete
// them one by one
int retryAttempt = 0;
@@ -191,12 +195,16 @@ UtilTransactions::clearTable1(Ndb* pNdb,
return NDBT_OK;
}
return NDBT_FAILED;
+#endif
}
int
UtilTransactions::clearTable2(Ndb* pNdb,
int records,
int parallelism){
+#if 1
+ return clearTable3(pNdb, records, parallelism);
+#else
// Scan all records exclusive and delete
// them one by one
int retryAttempt = 0;
@@ -336,6 +344,7 @@ UtilTransactions::clearTable2(Ndb* pNdb,
return NDBT_OK;
}
return NDBT_FAILED;
+#endif
}
int
@@ -403,7 +412,7 @@ UtilTransactions::clearTable3(Ndb* pNdb,
if(check != -1){
check = pTrans->execute(Commit);
- pTrans->releaseCompletedOperations();
+ pTrans->restart();
}
err = pTrans->getNdbError();
@@ -451,7 +460,7 @@ UtilTransactions::copyTableData(Ndb* pNdb,
int parallelism = 240;
int check;
NdbConnection *pTrans;
- NdbOperation *pOp;
+ NdbScanOperation *pOp;
NDBT_ResultRow row(tab);
while (true){
@@ -477,14 +486,15 @@ UtilTransactions::copyTableData(Ndb* pNdb,
return NDBT_FAILED;
}
- pOp = pTrans->getNdbOperation(tab.getName());
+ pOp = pTrans->getNdbScanOperation(tab.getName());
if (pOp == NULL) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
return NDBT_FAILED;
}
- check = pOp->openScanRead(parallelism);
+ NdbResultSet* rs = pOp->readTuples(NdbScanOperation::LM_Read,
+ parallelism);
if( check == -1 ) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
@@ -508,7 +518,7 @@ UtilTransactions::copyTableData(Ndb* pNdb,
}
}
- check = pTrans->executeScan();
+ check = pTrans->execute(NoCommit);
if( check == -1 ) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
@@ -516,39 +526,27 @@ UtilTransactions::copyTableData(Ndb* pNdb,
}
int eof;
- NdbConnection* pInsTrans;
-
- while((eof = pTrans->nextScanResult(true)) == 0){
- pInsTrans = pNdb->startTransaction();
- if (pInsTrans == NULL) {
- const NdbError err = pNdb->getNdbError();
- ERR(err);
- pNdb->closeTransaction(pInsTrans);
- return NDBT_FAILED;
- }
+ while((eof = rs->nextResult(true)) == 0){
do {
insertedRows++;
- if (addRowToInsert(pNdb, pInsTrans, row, destName) != 0){
- pNdb->closeTransaction(pInsTrans);
+ if (addRowToInsert(pNdb, pTrans, row, destName) != 0){
pNdb->closeTransaction(pTrans);
return NDBT_FAILED;
}
- } while((eof = pTrans->nextScanResult(false)) == 0);
-
- check = pInsTrans->execute(Commit);
+ } while((eof = rs->nextResult(false)) == 0);
+
+ check = pTrans->execute(Commit);
+ pTrans->restart();
if( check == -1 ) {
- const NdbError err = pInsTrans->getNdbError();
+ const NdbError err = pTrans->getNdbError();
ERR(err);
- pNdb->closeTransaction(pInsTrans);
pNdb->closeTransaction(pTrans);
return NDBT_FAILED;
}
- pNdb->closeTransaction(pInsTrans);
-
}
if (eof == -1) {
const NdbError err = pTrans->getNdbError();
-
+
if (err.status == NdbError::TemporaryError){
ERR(err);
pNdb->closeTransaction(pTrans);
@@ -562,30 +560,17 @@ UtilTransactions::copyTableData(Ndb* pNdb,
pNdb->closeTransaction(pTrans);
return NDBT_FAILED;
}
-
+
pNdb->closeTransaction(pTrans);
-
+
g_info << insertedRows << " rows copied" << endl;
-
+
return NDBT_OK;
}
return NDBT_FAILED;
}
int
-UtilTransactions::addRowToDelete(Ndb* pNdb,
- NdbConnection* pDelTrans,
- NdbOperation* pOrgOp){
-
- NdbOperation* pDelOp = pOrgOp->takeOverForDelete(pDelTrans);
- if (pDelOp == NULL){
- ERR(pNdb->getNdbError());
- return NDBT_FAILED;
- }
- return NDBT_OK;
-}
-
-int
UtilTransactions::addRowToInsert(Ndb* pNdb,
NdbConnection* pInsTrans,
NDBT_ResultRow & row,
@@ -621,101 +606,6 @@ UtilTransactions::addRowToInsert(Ndb* pNdb,
return NDBT_OK;
}
-// Take over one record from pOrgOp and delete it
-int
-UtilTransactions::takeOverAndDeleteRecord(Ndb* pNdb,
- NdbOperation* pOrgOp){
-
- int retryAttempt = 0;
- const int retryMax = 10;
- int check;
- NdbConnection *pDelTrans;
- NdbOperation *pDelOp;
-
- while (true){
-
- if (retryAttempt >= retryMax){
- g_info << "ERROR: has retried this operation " << retryAttempt
- << " times, failing!" << endl;
- return NDBT_FAILED;
- }
-
- pDelTrans = pNdb->startTransaction();
- if (pDelTrans == NULL) {
- const NdbError err = pNdb->getNdbError();
-
- if (err.status == NdbError::TemporaryError){
- ERR(err);
- NdbSleep_MilliSleep(50);
- retryAttempt++;
- continue;
- }
- ERR(err);
- return NDBT_FAILED;
- }
-
- if ((pDelOp = pOrgOp->takeOverForDelete(pDelTrans)) == NULL){
- ERR(pNdb->getNdbError());
- return NDBT_FAILED;
- }
-
-#if 0
- // It should not be necessary to call deleteTuple HERE!!!
- check = pDelOp->deleteTuple();
- if( check == -1 ) {
- ERR(pDelTrans->getNdbError());
- pNdb->closeTransaction(pDelTrans);
- return NDBT_FAILED;
- }
-#endif
-
- check = pDelTrans->execute( Commit );
- if(check == -1 ) {
- const NdbError err = pDelTrans->getNdbError();
- pNdb->closeTransaction(pDelTrans);
-
- ERR(err);
- if(err.code == 250 || err.code == 499)
- return RESTART_SCAN;
-
- switch(err.status){
- case NdbError::Success:
- g_info << "ERROR: NdbError reports success when transcaction failed"
- << endl;
- RETURN_FAIL(err);
- break;
-
- case NdbError::TemporaryError:
- NdbSleep_MilliSleep(50+50*retryAttempt);
- retryAttempt++;
- continue;
- break;
-
- case NdbError::UnknownResult:
- RETURN_FAIL(err);
- break;
-
- default:
- case NdbError::PermanentError:
- switch (err.classification){
- default:
- RETURN_FAIL(err);
- break;
- }
- break;
- }
- }
- else{
- pNdb->closeTransaction(pDelTrans);
- }
-
- return NDBT_OK;
- }
- return NDBT_FAILED;
-}
-
-
-
int
UtilTransactions::scanReadRecords(Ndb* pNdb,
@@ -730,7 +620,7 @@ UtilTransactions::scanReadRecords(Ndb* pNdb,
const int retryMax = 100;
int check;
NdbConnection *pTrans;
- NdbOperation *pOp;
+ NdbScanOperation *pOp;
NDBT_ResultRow row(tab);
while (true){
@@ -755,18 +645,18 @@ UtilTransactions::scanReadRecords(Ndb* pNdb,
return NDBT_FAILED;
}
- pOp = pTrans->getNdbOperation(tab.getName());
+ pOp = pTrans->getNdbScanOperation(tab.getName());
if (pOp == NULL) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
return NDBT_FAILED;
}
- if (exclusive == true)
- check = pOp->openScanExclusive(parallelism);
- else
- check = pOp->openScanRead(parallelism);
- if( check == -1 ) {
+ NdbResultSet * rs = pOp->readTuples(exclusive ?
+ NdbScanOperation::LM_Exclusive :
+ NdbScanOperation::LM_Read,
+ 0, parallelism);
+ if( rs == 0 ) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
return NDBT_FAILED;
@@ -778,7 +668,7 @@ UtilTransactions::scanReadRecords(Ndb* pNdb,
pNdb->closeTransaction(pTrans);
return NDBT_FAILED;
}
-
+
// Call getValue for all the attributes supplied in attrib_list
// ************************************************
for (int a = 0; a < noAttribs; a++){
@@ -793,8 +683,8 @@ UtilTransactions::scanReadRecords(Ndb* pNdb,
}
}
// *************************************************
-
- check = pTrans->executeScan();
+
+ check = pTrans->execute(NoCommit);
if( check == -1 ) {
const NdbError err = pTrans->getNdbError();
@@ -812,15 +702,14 @@ UtilTransactions::scanReadRecords(Ndb* pNdb,
int eof;
int rows = 0;
- eof = pTrans->nextScanResult();
- while(eof == 0){
+
+ while((eof = rs->nextResult()) == 0){
rows++;
// Call callback for each record returned
if(fn != NULL)
fn(&row);
- eof = pTrans->nextScanResult();
}
if (eof == -1) {
const NdbError err = pTrans->getNdbError();
@@ -856,14 +745,15 @@ UtilTransactions::selectCount(Ndb* pNdb,
int parallelism,
int* count_rows,
ScanLock lock,
- NdbConnection* pBuddyTrans){
+ NdbConnection* pTrans){
int retryAttempt = 0;
const int retryMax = 100;
int check;
- NdbConnection *pTrans;
- NdbOperation *pOp;
+ NdbScanOperation *pOp;
+ if(!pTrans)
+ pTrans = pNdb->startTransaction();
while (true){
if (retryAttempt >= retryMax){
@@ -871,39 +761,27 @@ UtilTransactions::selectCount(Ndb* pNdb,
<< " times, failing!" << endl;
return NDBT_FAILED;
}
-
- pTrans = pNdb->hupp(pBuddyTrans);
- if (pTrans == NULL) {
- const NdbError err = pNdb->getNdbError();
-
- if (err.status == NdbError::TemporaryError){
- NdbSleep_MilliSleep(50);
- retryAttempt++;
- continue;
- }
- ERR(err);
- return NDBT_FAILED;
- }
- pOp = pTrans->getNdbOperation(tab.getName());
+ pOp = pTrans->getNdbScanOperation(tab.getName());
if (pOp == NULL) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
return NDBT_FAILED;
}
+ NdbResultSet * rs;
switch(lock){
case SL_ReadHold:
- check = pOp->openScanReadHoldLock(parallelism);
+ rs = pOp->readTuples(NdbScanOperation::LM_Read);
break;
case SL_Exclusive:
- check = pOp->openScanExclusive(parallelism);
+ rs = pOp->readTuples(NdbScanOperation::LM_Exclusive);
break;
case SL_Read:
default:
- check = pOp->openScanRead(parallelism);
+ rs = pOp->readTuples(NdbScanOperation::LM_CommittedRead);
}
- if( check == -1 ) {
+ if( rs == 0) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
return NDBT_FAILED;
@@ -922,9 +800,9 @@ UtilTransactions::selectCount(Ndb* pNdb,
return NDBT_FAILED;
}
}
-
-
- check = pTrans->executeScan();
+
+
+ check = pTrans->execute(NoCommit);
if( check == -1 ) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
@@ -933,15 +811,14 @@ UtilTransactions::selectCount(Ndb* pNdb,
int eof;
int rows = 0;
- eof = pTrans->nextScanResult();
+
- while(eof == 0){
+ while((eof = rs->nextResult()) == 0){
rows++;
- eof = pTrans->nextScanResult();
}
if (eof == -1) {
const NdbError err = pTrans->getNdbError();
-
+
if (err.status == NdbError::TemporaryError){
pNdb->closeTransaction(pTrans);
NdbSleep_MilliSleep(50);
@@ -952,7 +829,7 @@ UtilTransactions::selectCount(Ndb* pNdb,
pNdb->closeTransaction(pTrans);
return NDBT_FAILED;
}
-
+
pNdb->closeTransaction(pTrans);
if (count_rows != NULL){
@@ -963,7 +840,6 @@ UtilTransactions::selectCount(Ndb* pNdb,
}
return NDBT_FAILED;
}
-
int
UtilTransactions::verifyIndex(Ndb* pNdb,
@@ -1028,7 +904,7 @@ UtilTransactions::scanAndCompareUniqueIndex(Ndb* pNdb,
const int retryMax = 100;
int check;
NdbConnection *pTrans;
- NdbOperation *pOp;
+ NdbScanOperation *pOp;
NDBT_ResultRow row(tab);
parallelism = 1;
@@ -1055,20 +931,21 @@ UtilTransactions::scanAndCompareUniqueIndex(Ndb* pNdb,
return NDBT_FAILED;
}
- pOp = pTrans->getNdbOperation(tab.getName());
+ pOp = pTrans->getNdbScanOperation(tab.getName());
if (pOp == NULL) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
return NDBT_FAILED;
}
+ NdbResultSet* rs;
if(transactional){
- check = pOp->openScanReadHoldLock(parallelism);
+ rs = pOp->readTuples(NdbScanOperation::LM_Read, 0, parallelism);
} else {
- check = pOp->openScanRead(parallelism);
+ rs = pOp->readTuples(NdbScanOperation::LM_CommittedRead, 0, parallelism);
}
-
- if( check == -1 ) {
+
+ if( rs == 0 ) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
return NDBT_FAILED;
@@ -1091,10 +968,10 @@ UtilTransactions::scanAndCompareUniqueIndex(Ndb* pNdb,
}
}
- check = pTrans->executeScan();
+ check = pTrans->execute(NoCommit);
if( check == -1 ) {
const NdbError err = pTrans->getNdbError();
-
+
if (err.status == NdbError::TemporaryError){
ERR(err);
pNdb->closeTransaction(pTrans);
@@ -1109,14 +986,14 @@ UtilTransactions::scanAndCompareUniqueIndex(Ndb* pNdb,
int eof;
int rows = 0;
- eof = pTrans->nextScanResult();
- while(eof == 0){
+
+ while((eof = rs->nextResult()) == 0){
rows++;
-
+
// ndbout << row.c_str().c_str() << endl;
-
-
+
+
if (readRowFromTableAndIndex(pNdb,
pTrans,
indexName,
@@ -1124,11 +1001,6 @@ UtilTransactions::scanAndCompareUniqueIndex(Ndb* pNdb,
pNdb->closeTransaction(pTrans);
return NDBT_FAILED;
}
-
-
-
-
- eof = pTrans->nextScanResult();
}
if (eof == -1) {
const NdbError err = pTrans->getNdbError();
@@ -1168,7 +1040,7 @@ UtilTransactions::readRowFromTableAndIndex(Ndb* pNdb,
NdbDictionary::Index::Type indexType= pIndex->getType();
int retryAttempt = 0;
const int retryMax = 100;
- int check;
+ int check, a;
NdbConnection *pTrans1=NULL;
NdbResultSet *cursor= NULL;
NdbOperation *pOp;
@@ -1228,7 +1100,7 @@ UtilTransactions::readRowFromTableAndIndex(Ndb* pNdb,
#if VERBOSE
printf("PK: ");
#endif
- for(int a = 0; a<tab.getNoOfColumns(); a++){
+ for(a = 0; a<tab.getNoOfColumns(); a++){
const NdbDictionary::Column* attr = tab.getColumn(a);
if (attr->getPrimaryKey() == true){
if (pOp->equal(attr->getName(), row.attributeStore(a)->aRef()) != 0){
@@ -1247,7 +1119,7 @@ UtilTransactions::readRowFromTableAndIndex(Ndb* pNdb,
#if VERBOSE
printf("Reading %u attributes: ", tab.getNoOfColumns());
#endif
- for(int a = 0; a<tab.getNoOfColumns(); a++){
+ for(a = 0; a<tab.getNoOfColumns(); a++){
if((tabRow.attributeStore(a) =
pOp->getValue(tab.getColumn(a)->getName())) == 0) {
ERR(pTrans1->getNdbError());
@@ -1265,13 +1137,13 @@ UtilTransactions::readRowFromTableAndIndex(Ndb* pNdb,
* Read the record from INDEX_TABLE
*/
NdbIndexOperation* pIndexOp= NULL;
- NdbScanOperation *pScanOp= NULL;
+ NdbIndexScanOperation *pScanOp= NULL;
{
void* pOpCheck= NULL;
if (indexType == NdbDictionary::Index::UniqueHashIndex) {
pOpCheck= pIndexOp= pTrans1->getNdbIndexOperation(indexName, tab.getName());
} else {
- pOpCheck= pScanOp= pTrans1->getNdbScanOperation(indexName, tab.getName());
+ pOpCheck= pScanOp= pTrans1->getNdbIndexScanOperation(indexName, tab.getName());
}
if (pOpCheck == NULL) {
@@ -1298,7 +1170,7 @@ UtilTransactions::readRowFromTableAndIndex(Ndb* pNdb,
#if VERBOSE
printf("SI: ");
#endif
- for(int a = 0; a<(int)pIndex->getNoOfColumns(); a++){
+ for(a = 0; a<(int)pIndex->getNoOfColumns(); a++){
const NdbDictionary::Column * col = pIndex->getColumn(a);
int r;
@@ -1308,7 +1180,7 @@ UtilTransactions::readRowFromTableAndIndex(Ndb* pNdb,
// setBound not possible for null attributes
if ( !row.attributeStore(col->getName())->isNULL() ) {
r = pScanOp->setBound(col->getName(),
- NdbOperation::BoundEQ,
+ NdbIndexScanOperation::BoundEQ,
row.attributeStore(col->getName())->aRef());
}
}
@@ -1328,7 +1200,7 @@ UtilTransactions::readRowFromTableAndIndex(Ndb* pNdb,
#if VERBOSE
printf("Reading %u attributes: ", tab.getNoOfColumns());
#endif
- for(int a = 0; a<tab.getNoOfColumns(); a++){
+ for(a = 0; a<tab.getNoOfColumns(); a++){
void* pCheck;
if (pIndexOp)
diff --git a/ndb/test/tools/cpcc.cpp b/ndb/test/tools/cpcc.cpp
index e768d707bbc..e30d458ffee 100644
--- a/ndb/test/tools/cpcc.cpp
+++ b/ndb/test/tools/cpcc.cpp
@@ -192,7 +192,7 @@ main(int argc, const char** argv){
,{ "rm", 0, arg_flag, &rm, "-c rm", "undefine process(es)" }
};
const int num_args = 10;
-
+ int i;
int optind = 0;
char desc[] = "[host:[port]]\n";
@@ -215,13 +215,13 @@ main(int argc, const char** argv){
Expression * m_expr = 0;
- for(int i = optind; i<argc; i++){
+ for(i = optind; i<argc; i++){
add_host(g_hosts, argv[i]);
}
OrExpr * orE = new OrExpr(new Operate(cmd, g_settings), true);
m_expr = orE;
- for(int i = optind; i<argc; i++){
+ for(i = optind; i<argc; i++){
BaseString tmp(argv[i]);
Vector<BaseString> split;
tmp.split(split, ":");
@@ -347,3 +347,5 @@ Operate::evaluate(SimpleCpcClient* c, const SimpleCpcClient::Process & pp){
return true;
}
+template class Vector<Expression*>;
+template class Vector<SimpleCpcClient*>;
diff --git a/ndb/test/tools/create_index.cpp b/ndb/test/tools/create_index.cpp
index dc9e6c606d6..f883755ea24 100644
--- a/ndb/test/tools/create_index.cpp
+++ b/ndb/test/tools/create_index.cpp
@@ -29,10 +29,13 @@ main(int argc, const char** argv){
const char* _dbname = "TEST_DB";
int _help = 0;
+ int _ordered, _pk;
struct getargs args[] = {
{ "database", 'd', arg_string, &_dbname, "dbname",
"Name of database table is in"},
+ { "ordered", 'o', arg_flag, &_ordered, "Create ordered index", "" },
+ { "pk", 'p', arg_flag, &_pk, "Create index on primary key", "" },
{ "usage", '?', arg_flag, &_help, "Print help", "" }
};
@@ -73,14 +76,21 @@ main(int argc, const char** argv){
}
NdbDictionary::Index ind;
+ if(_ordered){
+ ind.setType(NdbDictionary::Index::OrderedIndex);
+ ind.setLogging(false);
+ } else {
+ ind.setType(NdbDictionary::Index::UniqueHashIndex);
+ }
char buf[512];
- sprintf(buf, "IND_%s", argv[i]);
+ sprintf(buf, "IND_%s_%s_%c",
+ argv[i], (_pk ? "PK" : "FULL"), (_ordered ? 'O' : 'U'));
ind.setName(buf);
ind.setTable(argv[i]);
- ind.setType(NdbDictionary::Index::UniqueHashIndex);
- for(int c = 0; c<tab->getNoOfColumns(); c++)
- ind.addIndexColumn(tab->getColumn(c)->getName());
-
+ for(int c = 0; c<tab->getNoOfColumns(); c++){
+ if(!_pk || tab->getColumn(c)->getPrimaryKey())
+ ind.addIndexColumn(tab->getColumn(c)->getName());
+ }
ndbout << "creating index " << buf << " on table " << argv[i] << "...";
const int res = dict->createIndex(ind);
if(res != 0)
diff --git a/ndb/test/tools/hugoPkReadRecord.cpp b/ndb/test/tools/hugoPkReadRecord.cpp
index ac17ffffee8..85f20bd2060 100644
--- a/ndb/test/tools/hugoPkReadRecord.cpp
+++ b/ndb/test/tools/hugoPkReadRecord.cpp
@@ -43,7 +43,7 @@ int main(int argc, const char** argv)
};
int num_args = sizeof(args) / sizeof(args[0]);
- int optind = 0;
+ int optind = 0, i;
if(getarg(args, num_args, argc, argv, &optind) || argv[optind] == NULL) {
arg_printusage(args, num_args, argv[0], "table name\n");
@@ -80,7 +80,7 @@ int main(int argc, const char** argv)
}
op->readTuple();
NdbRecAttr** data = new NdbRecAttr*[table->getNoOfColumns()];
- for (int i = 0; i < table->getNoOfColumns(); i++)
+ for (i = 0; i < table->getNoOfColumns(); i++)
{
const NdbDictionary::Column* c = table->getColumn(i);
if (c->getPrimaryKey())
@@ -93,11 +93,10 @@ int main(int argc, const char** argv)
data[i] = op->getValue(c->getName(), NULL);
}
}
-
if (conn->execute(Commit) == 0)
{
// Print column names
- for (int i = 0; i < table->getNoOfColumns(); i++)
+ for (i = 0; i < table->getNoOfColumns(); i++)
{
const NdbDictionary::Column* c = table->getColumn(i);
@@ -111,7 +110,7 @@ int main(int argc, const char** argv)
{
g_info << hex;
}
- for (int i = 0; i < table->getNoOfColumns(); i++)
+ for (i = 0; i < table->getNoOfColumns(); i++)
{
NdbRecAttr* a = data[i];
switch(a->getType())
diff --git a/ndb/tools/delete_all.cpp b/ndb/tools/delete_all.cpp
index dabd9a0e8fa..5110947c6a2 100644
--- a/ndb/tools/delete_all.cpp
+++ b/ndb/tools/delete_all.cpp
@@ -143,7 +143,7 @@ int clear_table(Ndb* pNdb, const NdbDictionary::Table* pTab, int parallelism)
if(check != -1){
check = pTrans->execute(Commit);
- pTrans->releaseCompletedOperations();
+ pTrans->restart();
}
err = pTrans->getNdbError();
diff --git a/ndb/tools/desc.cpp b/ndb/tools/desc.cpp
index a5ff11edca9..e5b98c4c8e9 100644
--- a/ndb/tools/desc.cpp
+++ b/ndb/tools/desc.cpp
@@ -73,7 +73,8 @@ int main(int argc, const char** argv){
ndbout << "-- Indexes -- " << endl;
ndbout << "PRIMARY KEY(";
- for (unsigned j= 0; j < pTab->getNoOfPrimaryKeys(); j++)
+ unsigned j;
+ for (j= 0; j < pTab->getNoOfPrimaryKeys(); j++)
{
const NdbDictionary::Column * col = pTab->getColumn(j);
ndbout << col->getName();
@@ -82,7 +83,7 @@ int main(int argc, const char** argv){
}
ndbout << ") - UniqueHashIndex" << endl;
- for (unsigned j= 0; j < list.count; j++) {
+ for (j= 0; j < list.count; j++) {
NdbDictionary::Dictionary::List::Element& elt = list.elements[j];
const NdbDictionary::Index *pIdx = dict->getIndex(elt.name, argv[i]);
if (!pIdx){
diff --git a/ndb/tools/select_all.cpp b/ndb/tools/select_all.cpp
index 34f63a095bb..329ed87bc48 100644
--- a/ndb/tools/select_all.cpp
+++ b/ndb/tools/select_all.cpp
@@ -29,11 +29,13 @@
int scanReadRecords(Ndb*,
const NdbDictionary::Table*,
+ const NdbDictionary::Index*,
int parallel,
int lockType,
bool headers,
bool useHexFormat,
- char delim);
+ char delim,
+ bool orderby);
int main(int argc, const char** argv){
int _parallelism = 240;
@@ -44,6 +46,7 @@ int main(int argc, const char** argv){
const char* _dbname = "TEST_DB";
int _help = 0;
int _lock = 0;
+ int _order = 0;
struct getargs args[] = {
{ "database", 'd', arg_string, &_dbname, "dbname",
@@ -57,7 +60,8 @@ int main(int argc, const char** argv){
"delimiter" },
{ "usage", '?', arg_flag, &_help, "Print help", "" },
{ "lock", 'l', arg_integer, &_lock,
- "Read(0), Read-hold(1), Exclusive(2)", "lock"}
+ "Read(0), Read-hold(1), Exclusive(2)", "lock"},
+ { "order", 'o', arg_flag, &_order, "Sort resultset according to index", ""}
};
int num_args = sizeof(args) / sizeof(args[0]);
int optind = 0;
@@ -90,6 +94,11 @@ int main(int argc, const char** argv){
// Check if table exists in db
const NdbDictionary::Table* pTab = NDBT_Table::discoverTableFromDb(&MyNdb, _tabname);
+ const NdbDictionary::Index * pIdx = 0;
+ if(optind+1 < argc){
+ pIdx = MyNdb.getDictionary()->getIndex(argv[optind+1], _tabname);
+ }
+
if(pTab == NULL){
ndbout << " Table " << _tabname << " does not exist!" << endl;
return NDBT_ProgramExit(NDBT_WRONGARGS);
@@ -97,11 +106,12 @@ int main(int argc, const char** argv){
if (scanReadRecords(&MyNdb,
pTab,
+ pIdx,
_parallelism,
_lock,
_header,
_useHexFormat,
- (char)*_delimiter) != 0){
+ (char)*_delimiter, _order) != 0){
return NDBT_ProgramExit(NDBT_FAILED);
}
@@ -111,17 +121,19 @@ int main(int argc, const char** argv){
int scanReadRecords(Ndb* pNdb,
const NdbDictionary::Table* pTab,
+ const NdbDictionary::Index* pIdx,
int parallel,
int _lock,
bool headers,
bool useHexFormat,
- char delimiter){
+ char delimiter, bool order){
int retryAttempt = 0;
const int retryMax = 100;
int check;
NdbConnection *pTrans;
- NdbOperation *pOp;
+ NdbScanOperation *pOp;
+ NdbIndexScanOperation * pIOp;
NDBT_ResultRow * row = new NDBT_ResultRow(*pTab, delimiter);
@@ -146,29 +158,45 @@ int scanReadRecords(Ndb* pNdb,
return -1;
}
- pOp = pTrans->getNdbOperation(pTab->getName());
+
+ pOp = (!pIdx) ? pTrans->getNdbScanOperation(pTab->getName()) :
+ pIOp=pTrans->getNdbIndexScanOperation(pIdx->getName(), pTab->getName());
+
if (pOp == NULL) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
return -1;
}
- switch(_lock){
+ NdbResultSet * rs;
+ switch(_lock + (3 * order)){
case 1:
- check = pOp->openScanReadHoldLock(parallel);
+ rs = pOp->readTuples(NdbScanOperation::LM_Read, 0, parallel);
break;
case 2:
- check = pOp->openScanExclusive(parallel);
+ rs = pOp->readTuples(NdbScanOperation::LM_Exclusive, 0, parallel);
+ break;
+ case 3:
+ rs = pIOp->readTuples(NdbScanOperation::LM_CommittedRead, 0, parallel,
+ true);
break;
+ case 4:
+ rs = pIOp->readTuples(NdbScanOperation::LM_Read, 0, parallel, true);
+ break;
+ case 5:
+ rs = pIOp->readTuples(NdbScanOperation::LM_Exclusive, 0, parallel, true);
+ break;
+ case 0:
default:
- check = pOp->openScanRead(parallel);
+ rs = pOp->readTuples(NdbScanOperation::LM_CommittedRead, 0, parallel);
+ break;
}
- if( check == -1 ) {
+ if( rs == 0 ){
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
return -1;
}
-
+
if(0){
NdbScanFilter sf(pOp);
#if 0
@@ -229,10 +257,10 @@ int scanReadRecords(Ndb* pNdb,
}
}
- check = pTrans->executeScan();
+ check = pTrans->execute(NoCommit);
if( check == -1 ) {
const NdbError err = pTrans->getNdbError();
-
+
if (err.status == NdbError::TemporaryError){
pNdb->closeTransaction(pTrans);
NdbSleep_MilliSleep(50);
@@ -246,11 +274,11 @@ int scanReadRecords(Ndb* pNdb,
if (headers)
row->header(ndbout) << endl;
-
+
int eof;
int rows = 0;
- eof = pTrans->nextScanResult();
-
+ eof = rs->nextResult();
+
while(eof == 0){
rows++;
@@ -260,7 +288,7 @@ int scanReadRecords(Ndb* pNdb,
ndbout << (*row) << endl;
}
- eof = pTrans->nextScanResult();
+ eof = rs->nextResult();
}
if (eof == -1) {
const NdbError err = pTrans->getNdbError();
diff --git a/ndb/tools/select_count.cpp b/ndb/tools/select_count.cpp
index cae91feb378..2c43af20e64 100644
--- a/ndb/tools/select_count.cpp
+++ b/ndb/tools/select_count.cpp
@@ -30,8 +30,7 @@ static int
select_count(Ndb* pNdb, const NdbDictionary::Table* pTab,
int parallelism,
int* count_rows,
- UtilTransactions::ScanLock lock,
- NdbConnection* pBuddyTrans=0);
+ UtilTransactions::ScanLock lock);
int main(int argc, const char** argv){
const char* _dbname = "TEST_DB";
@@ -95,14 +94,13 @@ int
select_count(Ndb* pNdb, const NdbDictionary::Table* pTab,
int parallelism,
int* count_rows,
- UtilTransactions::ScanLock lock,
- NdbConnection* pBuddyTrans){
+ UtilTransactions::ScanLock lock){
int retryAttempt = 0;
const int retryMax = 100;
int check;
NdbConnection *pTrans;
- NdbOperation *pOp;
+ NdbScanOperation *pOp;
while (true){
@@ -112,7 +110,7 @@ select_count(Ndb* pNdb, const NdbDictionary::Table* pTab,
return NDBT_FAILED;
}
- pTrans = pNdb->hupp(pBuddyTrans);
+ pTrans = pNdb->startTransaction();
if (pTrans == NULL) {
const NdbError err = pNdb->getNdbError();
@@ -124,26 +122,27 @@ select_count(Ndb* pNdb, const NdbDictionary::Table* pTab,
ERR(err);
return NDBT_FAILED;
}
- pOp = pTrans->getNdbOperation(pTab->getName());
+ pOp = pTrans->getNdbScanOperation(pTab->getName());
if (pOp == NULL) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
return NDBT_FAILED;
}
+ NdbResultSet * rs;
switch(lock){
case UtilTransactions::SL_ReadHold:
- check = pOp->openScanReadHoldLock(parallelism);
+ rs = pOp->readTuples(NdbScanOperation::LM_Read, 0, parallelism);
break;
case UtilTransactions::SL_Exclusive:
- check = pOp->openScanExclusive(parallelism);
+ rs = pOp->readTuples(NdbScanOperation::LM_Exclusive, 0, parallelism);
break;
case UtilTransactions::SL_Read:
default:
- check = pOp->openScanRead(parallelism);
+ rs = pOp->readTuples(NdbScanOperation::LM_Dirty, 0, parallelism);
}
- if( check == -1 ) {
+ if( rs == 0 ) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
return NDBT_FAILED;
@@ -156,7 +155,7 @@ select_count(Ndb* pNdb, const NdbDictionary::Table* pTab,
return NDBT_FAILED;
}
- check = pTrans->executeScan();
+ check = pTrans->execute(NoCommit);
if( check == -1 ) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
@@ -165,11 +164,11 @@ select_count(Ndb* pNdb, const NdbDictionary::Table* pTab,
int eof;
int rows = 0;
- eof = pTrans->nextScanResult();
+ eof = rs->nextResult();
while(eof == 0){
rows++;
- eof = pTrans->nextScanResult();
+ eof = rs->nextResult();
}
if (eof == -1) {
const NdbError err = pTrans->getNdbError();
diff --git a/ndb/tools/waiter.cpp b/ndb/tools/waiter.cpp
index 7ce2739a157..86d34066c55 100644
--- a/ndb/tools/waiter.cpp
+++ b/ndb/tools/waiter.cpp
@@ -22,21 +22,26 @@
#include <NdbSleep.h>
#include <getarg.h>
#include <kernel/ndb_limits.h>
-#include "../src/common/mgmcommon/LocalConfig.hpp"
+#include "../include/mgmcommon/LocalConfig.hpp"
#include <NDBT.hpp>
int
-waitClusterStarted(const char* _addr, unsigned int _timeout= 120);
+waitClusterStatus(const char* _addr,
+ ndb_mgm_node_status _status= NDB_MGM_NODE_STATUS_STARTED,
+ unsigned int _timeout= 120);
int main(int argc, const char** argv){
const char* _hostName = NULL;
+ int _no_contact = 0;
int _help = 0;
struct getargs args[] = {
+ { "no-contact", 0, arg_flag, &_no_contact, "Wait for cluster no contact", "" },
{ "usage", '?', arg_flag, &_help, "Print help", "" }
};
+
int num_args = sizeof(args) / sizeof(args[0]);
int optind = 0;
char desc[] =
@@ -62,13 +67,13 @@ int main(int argc, const char** argv){
return NDBT_ProgramExit(NDBT_FAILED);
}
- for (int i = 0; i<lcfg.items; i++)
+ for (int i = 0; i<lcfg.ids.size();i++)
{
- MgmtSrvrId * m = lcfg.ids[i];
+ MgmtSrvrId * m = &lcfg.ids[i];
switch(m->type){
case MgmId_TCP:
- snprintf(buf, 255, "%s:%d", m->data.tcp.remoteHost, m->data.tcp.port);
+ snprintf(buf, 255, "%s:%d", m->name.c_str(), m->port);
_hostName = buf;
break;
case MgmId_File:
@@ -86,7 +91,10 @@ int main(int argc, const char** argv){
}
}
- if (waitClusterStarted(_hostName) != 0)
+ if (_no_contact) {
+ if (waitClusterStatus(_hostName, NDB_MGM_NODE_STATUS_NO_CONTACT) != 0)
+ return NDBT_ProgramExit(NDBT_FAILED);
+ } else if (waitClusterStatus(_hostName) != 0)
return NDBT_ProgramExit(NDBT_FAILED);
return NDBT_ProgramExit(NDBT_OK);
@@ -121,7 +129,8 @@ getStatus(){
retries++;
continue;
}
- for (int i = 0; i < status->no_of_nodes; i++){
+ int count = status->no_of_nodes;
+ for (int i = 0; i < count; i++){
node = &status->node_states[i];
switch(node->node_type){
case NDB_MGM_NODE_TYPE_NDB:
@@ -142,7 +151,7 @@ getStatus(){
apiNodes.clear();
free(status);
status = NULL;
- i = status->no_of_nodes;
+ count = 0;
ndbout << "kalle"<< endl;
break;
@@ -164,9 +173,10 @@ getStatus(){
}
int
-waitClusterStarted(const char* _addr, unsigned int _timeout)
+waitClusterStatus(const char* _addr,
+ ndb_mgm_node_status _status,
+ unsigned int _timeout)
{
- ndb_mgm_node_status _status = NDB_MGM_NODE_STATUS_STARTED;
int _startphase = -1;
int _nodes[MAX_NDB_NODES];
@@ -290,10 +300,12 @@ waitClusterStarted(const char* _addr, unsigned int _timeout)
allInState = false;
}
}
- g_info << "Waiting for cluster enter state"
+ g_info << "Waiting for cluster enter state "
<< ndb_mgm_get_node_status_string(_status)<< endl;
NdbSleep_SecSleep(1);
attempts++;
}
return 0;
}
+
+template class Vector<ndb_mgm_node_state>;